{"id":13288521,"url":"https://github.com/lerenn/asyncapi-codegen","last_synced_at":"2025-12-24T16:59:37.059Z","repository":{"id":65910968,"uuid":"596978905","full_name":"lerenn/asyncapi-codegen","owner":"lerenn","description":"An AsyncAPI Golang Code generator that generates all Go code from the broker to the application/user. Just plug your application to your favorite message broker!","archived":false,"fork":false,"pushed_at":"2025-02-18T10:33:06.000Z","size":997,"stargazers_count":107,"open_issues_count":27,"forks_count":24,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-18T11:30:42.381Z","etag":null,"topics":["asyncapi","asyncapi-generator","asyncapi-tooling","asyncapi-tools","code-generation","generator","go","golang","kafka","nats","nats-messaging"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lerenn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["lerenn"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2023-02-03T11:00:04.000Z","updated_at":"2025-02-18T10:33:14.000Z","dependencies_parsed_at":"2023-02-24T11:30:50.263Z","dependency_job_id":"96d40885-2f38-445c-a6e8-f6eaecc8e6ee","html_url":"https://github.com/lerenn/asyncapi-codegen","commit_stats":null,"previous_names":[],"tags_count":109,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lerenn%2Fasyncapi-codegen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lerenn%2Fasyncapi-codegen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lerenn%2Fasyncapi-codegen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lerenn%2Fasyncapi-codegen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lerenn","download_url":"https://codeload.github.com/lerenn/asyncapi-codegen/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242805420,"owners_count":20187995,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asyncapi","asyncapi-generator","asyncapi-tooling","asyncapi-tools","code-generation","generator","go","golang","kafka","nats","nats-messaging"],"created_at":"2024-07-29T16:56:55.510Z","updated_at":"2025-12-24T16:59:37.050Z","avatar_url":"https://github.com/lerenn.png","language":"Go","funding_links":["https://github.com/sponsors/lerenn"],"categories":[],"sub_categories":[],"readme":"# AsyncAPI Codegen\n\nAn AsyncAPI Golang Code generator that generates all Go code from the broker\nto the application/user. Just plug your application to your favorite message broker!\n\n![AsyncAPI Codegen Preview](./assets/codegen-preview.svg)\n\n**⚠️ We do our best to progressively satisfy the entire AsyncAPI specification,**\n**but some features may still be missing: please raise an issue on any bug or**\n**missing feature.**\n\n**❤️ Support is greatly appreciated and contributions are welcomed!**\n\n*Inspired from popular [deepmap/oapi-codegen](https://github.com/deepmap/oapi-codegen)*\n\n## Contents\n\n* [Supported functionalities](#supported-functionalities)\n* [Usage](#usage)\n* [Concepts](#concepts)\n* [Examples](#examples)\n* [Supported Brokers](#supported-brokers)\n  * [Kafka](#kafka)\n  * [NATS](#nats) / [NATS JetStream](#nats-jetstream)\n  * [Custom broker](#custom-broker)\n* [CLI options](#cli-options)\n* [Advanced topics](#advanced-topics)\n  * [Middlewares](#middlewares)\n  * [Context](#context)\n  * [Logging](#logging)\n  * [Versioning](#versioning)\n  * [Extensions](#specification-extensions)\n  * [ErrorHandler](#errorhandler)\n  * [Validations](#validations)\n* [Contributing and support](#contributing-and-support)\n\n## Supported functionalities\n\n* AsyncAPI versions:\n  * 2.6.0\n  * 3.0.0\n* Brokers:\n  * Kafka\n  * NATS / NATS JetStream\n  * Custom\n* Formats:\n  * JSON\n* Logging:\n  * Elastic Common Schema (JSON)\n  * Text (Humand readable)\n  * Custom\n* Others:\n  * Versioning support\n\n## Usage\n\nIn order to use this library in your code, please execute the following lines:\n\n```shell\n# Install the tool\ngo install github.com/lerenn/asyncapi-codegen/cmd/asyncapi-codegen@latest\n\n# Generate the code from the asyncapi file\nasyncapi-codegen -i ./asyncapi.yaml -p \u003cyour-package\u003e -o ./asyncapi.gen.go\n\n# Install dependencies needed by the generated code\ngo get -u github.com/lerenn/asyncapi-codegen/pkg/extensions\n```\n\nYou can also specify the generation part by adding a `go generate` instruction\nat the beginning of your file:\n\n```golang\n//go:generate go run github.com/lerenn/asyncapi-codegen/cmd/asyncapi-codegen@\u003cversion\u003e -i ./asyncapi.yaml -p \u003cyour-package\u003e -o ./asyncapi.gen.go\n```\n\n### Docker image\n\nYou can also use the dockerized version of this tool:\n\n```bash\ndocker run -v .:/code -w /code lerenn/asyncapi-codegen asyncapi-codegen -i ./asyncapi.yaml -p \u003cyour-package\u003e -o ./asyncapi.gen.go\n```\n\n## Concepts\n\n![basic schema](assets/basic-schema.svg)\n\nLet's imagine a message broker centric architecture: you have the application\nthat you are developing on the right and the potential user(s) on the left.\n\nBeing a two directional communication, both of them can communicate to each\nother through the broker. They can even communicate with themselves, in case\nof multiple users or application replication.\n\nFor more information about this, please refere to the [official AsyncAPI\nconcepts](https://www.asyncapi.com/docs/concepts).\n\n### With Async API generated code\n\n![with codegen schema](assets/with-codegen-schema.svg)\n\n* \u003cspan style=\"color:yellow\"\u003eYellow parts\u003c/span\u003e: when using the codegen tool,\nyou will generate the code that will act as an adapter (called **controller**)\nbetween the user, the broker, and the application.\n* \u003cspan style=\"color:red\"\u003eRed parts\u003c/span\u003e: you will need to fill these parts\nbetween user, broker and application. These will allow message production and\nreception with the generated code.\n* \u003cspan style=\"color:orange\"\u003eOrange parts\u003c/span\u003e: these parts will be available\nin this repository if you use an already supported broker. However, you can also\nuse the implement it yourself if the broker is not supported yet.\n\n## Examples\n\nHere is a list of example, from basic to advanced ones.\n\n**Please note that the examples are separated in different subdirectories per broker.**\n\nIt is strongly advised to read them in present order, following your AsyncAPI version.\n\n* **HelloWorld**:\n  * [AsyncAPI v2](./examples/helloworld/v2/README.md)\n  * [AsyncAPI v3](./examples/helloworld/v3/README.md)\n* **Ping**:\n  * [AsyncAPI v2](./examples/ping/v2/README.md)\n  * [AsyncAPI v3](./examples/ping/v3/README.md)\n\n## Supported Brokers\n\nIn order to connect your broker to the autogenerated code, you will need to\ncreate a controller that will be used to publish and subscribe to messages.\n\nYou can use one of the already supported brokers or implement your own.\n\n### Kafka\n\nIn order to use Kafka as a broker, you can use the following code:\n\n```golang\nbroker, _ := kafka.NewController([]string{\"\u003chost\u003e:\u003cport\u003e\", /* additional hosts */}, /* options */)\n```\n\nHere are the options that you can use with the Kafka controller:\n\n* `WithGroupdID`: specify the group ID that will be used by the controller. If not specified, default queue name (`asyncapi`) will be used.\n* `WithPartition`: specify the partition that will be used by the controller. If not specified, default partition (`0`) will be used.\n* `WithMaxBytes`: specify the maximum size of a message that will be received. If not specified, default value (`10e6`, meaning `10MB`) will be used.\n* `WithLogger`: specify the logger that will be used by the controller. If not specified, a silent logger is used that won't log anything.\n* `WithAutoCommit`: specify if the broker should use auto-commit for incoming messages or manual commits. Note that commits are managed by the broker implementation regardless, with manual commits they are executed after the message is complete processed. Subscribers retain the option to manually handle errors via the ErrorHandler, to use mechanisms such as dead letter or retry topics. The default value is `true`\n* `WithSasl`: specify sasl mechanism to connect to the broker. Per default no mechanism will be used.\n* `WithTLS`: specify tls config to connect to the broker. Per default no tls config will be used.\n* `WithConnectionTest`: specify if the controller should make a connection test on creation. The default value is `true`\n\n#### Authentication and TLS\n\nTo use a TLS connection and or authentication for the connection to the kafka broker the following options can be used:\n\n```golang\n// Plain mechanism\nkafkaController, err := kafka.NewController([]string{\"\u003chost\u003e:\u003cport\u003e\"},\n    kafka.WithGroupID(queueGroupID),\n    kafka.WithSasl(plain.Mechanism{Username: \"\u003cuser\u003e\", Password: \"\u003cpassword\u003e\"}),\n)\n\n// Sha256 mechanism\nsha256Mechanism, err := scram.Mechanism(scram.SHA256, \"\u003cuser\u003e\", \"\u003cpassword\u003e\")\nif err != nil {\n    // handle error\n}\n\nkafkaController, err := kafka.NewController([]string{\"\u003chost\u003e:\u003cport\u003e\"},\n    kafka.WithGroupID(queueGroupID),\n    kafka.WithSasl(sha256Mechanism),\n)\n\n// Sha512 mechanism\nsha512Mechanism, err := scram.Mechanism(scram.SHA512, \"\u003cuser\u003e\", \"\u003cpassword\u003e\")\nif err != nil {\n    // handle error\n}\n\nkafkaController, err := kafka.NewController([]string{\"\u003chost\u003e:\u003cport\u003e\"},\n    kafka.WithGroupID(queueGroupID),\n    kafka.WithSasl(sha512Mechanism),\n)\n\n// TLS\n// configure tls.config\nmyTLSConfig := \u0026tls.Config{}\n\nkafkaController, err := kafka.NewController([]string{\"\u003chost\u003e:\u003cport\u003e\"},\n    kafka.WithGroupID(queueGroupID),\n    kafka.WithTLS(myTLSConfig),\n)\n```\n\n### NATS\n\nIn order to use NATS as a broker, you can use the following code:\n\n```golang\n// Create the NATS controller\nbroker, _ := nats.NewController(\"nats://\u003chost\u003e:\u003cport\u003e\")\ndefer broker.Close()\n\n// Add NATS controller to a new App controller\nctrl, err := NewAppController(broker, /* options */)\n\n//...\n```\n\nHere are the options that you can use with the NATS controller:\n\n* `WithLogger`: specify the logger that will be used by the controller. If not specified, a silent logger is used that won't log anything.\n* `WithQueueGroup`: specify the queue group that will be used by the controller. If not specified, default queue name (`asyncapi`) will be used.\n* `WithConnectionOpts`: specify connection Options for establishing connection with nats see [Nats Options](https://pkg.go.dev/github.com/nats-io/go-nats#Option) for more information. If not specified, no options will be used.\n\n#### Authentication and TLS\n\nTo use a TLS connection and or authentication for the connection to the nats broker the following nats options can be used:\n\n```golang\nimport (\n\"github.com/lerenn/asyncapi-codegen/pkg/extensions/brokers/nats\"\n\n// import natsio go client option\nnatsio \"github.com/nats-io/nats.go\"\n\n)\n\nfunc main(){\n\n    myTLSConfig := \u0026tls.Config{}\n\n    natsController, err := nats.NewController(\"nats://\u003chost\u003e:\u003cport\u003e\",\n\t\tnats.WithQueueGroup(queueGroupID),\n\t\tnats.WithConnectionOpts(natsio.UserCredentials(\"\u003cuser.jwt\u003e\", \"\u003cuser.nk\u003e\"), natsio.Secure(myTLSConfig))\n\t)\n\n}\n```\n\n### NATS JetStream\n\nIn order to use NATS JetStream as a broker, you can use the following code:\n\n```golang\n// Create the NATS controller\nbroker, _ := natsjetstream.NewController(\"nats://\u003chost\u003e:\u003cport\u003e\", /* options */)\ndefer broker.Close()\n\n// Add NATS controller to a new App controller\nctrl, err := NewAppController(broker)\n\n//...\n```\n\nIt is important to either create/update a stream with `WithStreamConfig` or to use `WithStream` to specify the stream that will be used by the broker.\nConsumer for the user controller can be either created/updated with `WithConsumerConfig` or `WithConsumer`.\n\n#### Limitations\n\n* the messages will be ack'd from the consumer even though the subscription was not setup (this will be logged)\n\n### Custom broker\n\nIn order to connect your application and your user to your broker, we need to\nprovide a controller to it. Here is the interface that you need to satisfy:\n\n```go\nimport(\n  \"github.com/lerenn/asyncapi-codegen/pkg/extensions\"\n)\n\ntype BrokerController interface {\n  // Publish a message to the broker\n  Publish(ctx context.Context, channel string, mw extensions.BrokerMessage) error\n\n  // Subscribe to messages from the broker\n  Subscribe(ctx context.Context, channel string) (msgs chan extensions.BrokerMessage, stop chan any, err error)\n}\n```\n\nYou can find that there is an `extensions.BrokerMessage` structure that is provided and\nthat aims to abstract the event broker technology.\n\nBy writing your own by satisfying this interface, you will be able to connect\nyour broker to the generated code.\n\n## CLI options\n\n### Generation parts (`-g, --generate`)\n\nThe default options for asyncapi-codegen will generate everything; user, application,\nand type definitions but you can generate subsets of those via the -generate\nflag. It defaults to user,application,types\nbut you can specify any combination of those.\n\nHere are the universal parts that you can generate:\n\n* `application`: generate the application boilerplate. `application` requires\n  the types in the same package to compile.\n* `user`: generate the user boilerplate. It, too, requires the types to be\n  present in its package.\n* `types`: all type definitions for all types in the AsyncAPI spec.\n  This will be everything under `#components`, as well as request parameter,\n  request body, and response type objects.\n\n### Package name (`-p, --package`)\n\nThe package name is the name of the package that will be used in the generated\ncode. It is important to have the same package name for the user, application,\nand types in order to compile the code.\n\n### Input files (`-i, --input`)\n\nThe input file is the path to the AsyncAPI specification file that will be used\nto generate the code. It can be either a JSON or a YAML file.\n\nAlso, you can specify dependencies by separating them with a comma:\n\n```shell\nasyncapi-codegen -i ./asyncapi.yaml,./dependency1.yaml,./dependency2.yaml -p \u003cyour-package\u003e -o ./asyncapi.gen.go\n```\n\n### Output file (`-o, --output`)\n\nThe output file is the path to the file that will be generated by the tool. It\nwill contain the generated code.\n\n### Disable formatting (`-f, --disable-formatting`)\n\nBy default, the generated code will be formatted using `gofmt`. If you want to\ndisable this feature, you can use the `-f` flag.\n\n### JSON keys conversion (`-c, --convert-keys`)\n\nBy default, the generation will use the key specified in the asyncapi codegen.\nThis is also called the `none` convertion. You can also convert your keys to\n`snake`, `camel`, or `kebab`.\n\n#### Example\n\nGiven this schema:\n\n```yaml\nPayload:\n  type: object\n  properties:\n    This_is a-Property:\n      type: string\n```\n\nHere are the generated JSON sent, given by the different options:\n* No conversion (`none`): `{ \"This_is a-Property\": \"value\" }`\n* Camel case (`camel`): `{ \"ThisIsAProperty\": \"value\" }`\n* Kebab case (`kebab`): `{ \"this-is-a-property\": \"value\" }`\n* Snake case (`snake`): `{ \"this_is_a_property\": \"value\" }`\n\n## Advanced topics\n\n### Middlewares\n\nYou can use middlewares that will be executing when receiving and publishing\nmessages. You can add one or multiple middlewares using the  `WithMiddlewares`\nfunction in the initialization of the App or User controller:\n\n```golang\n// Create a new app controller with middlewares\nctrl, _ := NewAppController(/* Broker of your choice */, WithMiddlewares(myMiddleware1, myMiddleware2 /*, ... */))\n```\n\nHere the function signature that should be satisfied:\n\n```golang\nfunc(ctx context.Context, msg *extensions.BrokerMessage, next extensions.NextMiddleware) error\n```\n\n**Note:** the returned context will be the one that will be passed to following\nmiddlewares, and finally to the generated code (and subscription callback).\n\n#### Examples\n\n##### Filtering messages\n\n```golang\nimport(\n  \"github.com/lerenn/asyncapi-codegen/pkg/extensions\"\n  // ...\n)\n\nfunc myMiddleware(ctx context.Context, _ *extensions.BrokerMessage, _ middleware.Next) error {\n  // Execute this middleware only if this is a received message\n  extensions.IfContextValueEquals(ctx, extensions.ContextKeyIsDirection, \"reception\", func() {\n    // Do specific stuff if message is received\n  })\n\n  return nil\n}\n```\n\nYou can even discriminate on more specification. Please see the [Context section](#context).\n\n##### Modify messages before sending/receiving\n\n```golang\nimport(\n  \"github.com/lerenn/asyncapi-codegen/pkg/extensions\"\n  // ...\n)\n\nfunc myMiddleware(_ context.Context, msg *extensions.BrokerMessage, _ middleware.Next) error {\n  msg.Headers[\"additional\"] = \"some-info\"\n  return nil\n}\n```\n\n##### Stopping message processing\n\n```golang\nimport(\n  \"github.com/lerenn/asyncapi-codegen/pkg/extensions\"\n  // ...\n)\n\nfunc myMiddleware(_ context.Context, msg *extensions.BrokerMessage, _ middleware.Next) error {\n  if msg.Headers[\"author\"] != \"me\" {\n    return fmt.Errorf(\"this is not me, aborting...\")\n  }\n  return nil\n}\n```\n\n#### Executing code after receiving/publishing the message\n\nBy default, middlewares will be executed right before the operation. If there is\na need to execute code before and/or after the operation, you can call the `next`\nargument that represents the next middleware that should be executed or the\noperation corresponding code if this was the last middleware.\n\nHere is an example:\n\n```golang\nimport(\n  \"github.com/lerenn/asyncapi-codegen/pkg/extensions\"\n  // ...\n)\n\nfunc surroundingMiddleware(ctx context.Context, next extensions.NextMiddleware) error {\n  // Pre-operation\n  fmt.Println(\"This will be displayed BEFORE the reception/publication\")\n\n  // Calling next middleware or reception/publication code\n  // The given context will be the one propagated to other middlewares and operation source code\n  err := next(ctx)\n\n  // Post-operation\n  fmt.Println(\"This will be displayed AFTER the reception/publication\")\n\n  return err\n}\n```\n\n### Context\n\nWhen receiving the context from generated code (either in subscription,\nmiddleware, logging, etc), you can get some information embedded in context.\n\nTo get these information, please use the functions from\n`github.com/lerenn/asyncapi-codegen/pkg/extensions`:\n\n```golang\n// Execute this middleware only if this is from \"ping\" channel\nextensions.IfContextValueEquals(ctx, extensions.ContextKeyIsChannel, \"ping\", func() {\n  // Do specific stuff if the channel is ping\n})\n```\n\nYou can find other keys in the package `pkg/extensions`.\n\n### Logging\n\nYou can have 2 types of logging:\n* **Controller logging**: logs the internal operations of the controller (subscription, malformed messages, etc);\n* **Publication/Reception logging**: logs every publication or reception of messages.\n\n#### Controller logging\n\nTo log internal operation of the controller, the only thing you have to do is\nto initialize the controller with a logger, with the function `WithLogger()`:\n\n```golang\nimport(\n  \"github.com/lerenn/asyncapi-codegen/pkg/extensions/brokers\"\n  // ...\n)\n\nfunc main() {\n  // Create a new app controller with an Elastic Common Schema JSON compatible logger\n  ctrl, _ := NewAppController(/* Broker of your choice */, WithLogger(log.NewECS()))\n\n  // ...\n}\n```\n\nYou can find all loggers in the directory `pkg/log`.\n\n#### Publication/Reception logging\n\nTo log published and received messages, you'll have to pass a logger as a middleware\nin order to execute it on every published and received messages:\n\n```golang\nimport(\n  \"github.com/lerenn/asyncapi-codegen/pkg/extensions/brokers\"\n  // ...\n)\n\nfunc main() {\n  // Create a new app controller with a middleware for logging incoming/outgoing messages\n  loggingMiddleware := middleware.Logging(log.NewECS())\n  ctrl, _ := NewAppController(/* Broker of your choice */, WithMiddlewares(loggingMiddleware))\n\n  // ...\n}\n```\n\n#### Custom logging\n\nIt is possible to set your own logger to the generated code, all you have to do\nis to fill the following interface:\n\n```golang\ntype Logger interface {\n    // Info logs information based on a message and key-value elements\n    Info(ctx log.Context, msg string, info ...log.AdditionalInfo)\n\n    // Error logs error based on a message and key-value elements\n    Error(ctx log.Context, msg string, info ...log.AdditionalInfo)\n}\n```\n\nHere is a basic implementation example:\n\n```golang\ntype SimpleLogger struct{}\n\nfunc (logger SimpleLogger) formatLog(ctx log.Context, info ...log.AdditionalInfo) string {\n  var formattedLogInfo string\n  for i := 0; i \u003c len(keyvals)-1; i += 2 {\n    formattedLogInfo = fmt.Sprintf(\"%s, %s: %+v\", formattedLogInfo, info.Key, info.Value)\n  }\n  return fmt.Sprintf(\"%s, context: %+v\", formattedLogInfo, ctx)\n}\n\nfunc (logger SimpleLogger) Info(ctx log.Context, msg string, info ...log.AdditionalInfo) {\n  log.Printf(\"INFO: %s%s\", msg, logger.formatLog(ctx, info...))\n}\n\nfunc (logger SimpleLogger) Error(ctx log.Context, msg string, info ...log.AdditionalInfo) {\n  log.Printf(\"ERROR: %s%s\", msg, logger.formatLog(ctx, info...))\n}\n```\n\nYou can then create a controller with a logger using similar lines:\n\n```golang\n// Create a new app controller with the custom logger\nctrl, _ := NewAppController(\n  /* Broker of your choice */,\n  WithLogger(SimpleLogger{}),                         /* Use on as internal logger */\n  WithMiddleware(middleware.Logging(SimpleLogger{})), /* Use to log incoming/outgoing messages */\n)\n```\n\n### Versioning\n\nIf you are in need to do a migration or support multiple versions of your\nAsyncAPI specifications, you can use the `versioning` package:\n\n```golang\n\nimport (\n  \"github.com/lerenn/asyncapi-codegen/pkg/extensions/brokers/nats\"\n  \"github.com/lerenn/asyncapi-codegen/pkg/extensions/versioning\"\n  v1 \"path/to/asyncapi/spec/version/1\"\n  v2 \"path/to/asyncapi/spec/version/2\"\n)\n\nfunc main() {\n  // Create a broker (here from NATS)\n  broker, _ := nats.NewController(\"nats://nats:4222\"))\n  defer broker.Close()\n\n  // Add a version wrapper to the broker\n  vw := versioning.NewWrapper(broker)\n\n  // Create application for version 1\n  appV1, _ := v1.NewAppController(vw, /* controller options */)\n  defer appV1.Close(context.Background())\n\n  // Create v2 app\n  appV2, _ := v2.NewAppController(vw, /* controller options */)\n  defer appV2.Close(context.Background())\n\n  // ...\n}\n```\n\nThen you can use each application independently:\n\n```golang\nerr := appV1.SubscribeHello(context.Background(), func(ctx context.Context, msg v1.HelloMessage) {\n  // Stuff for version 1\n})\n\nerr := appV2.SubscribeHello(context.Background(), func(ctx context.Context, msg v2.HelloMessage) {\n  // Stuff for version 2\n})\n```\n\nThat way, you can support multiple different versions with the same broker.\n\n#### Version tagging\n\nThe versioning feature will add an `application-version` header to each\nmessage in order to have the correct version of the application on each of\nthem.\n\n##### Non-tagged messages\n\nIf messages can have no `application-version`, you can use the option `WithDefaultVersion`\nto add a default version to non-tagged messages.\n\n```golang\nvw := versioning.NewWrapper(broker, versioning.WithDefaultVersion(\"1.1.4\"))\n```\n\n##### Change header key for application version\n\nAlso, if you don't want to use this header as a recipient to the application version,\nyou can specify your own header with the option `WithVersionHeaderKey`.\n\n```golang\nvw := versioning.NewWrapper(broker, versioning.WithVersionHeaderKey(\"my-version-key\"))\n```\n\n#### Knowing generated version\n\nIf you want to use the version of the AsyncAPI document used, you can access the constant\n`AsyncAPIVersion` that is generated with the types. It is generated as followed:\n\n```go\nconst AsyncAPIVersion = \"{{ .Info.Version }}\"\n```\n\n### Specification extensions\n\n#### Schema Object extensions\n\nThese extension properties apply to \"Schema Objects\" in AsyncAPI spec.\n\n* `x-go-type`: Overrides the default Go type with the specified Go type name.\n\n  For example,\n\n  ```yaml\n  schemas:\n    Object:\n      properties:\n        flag:\n          type: integer\n          x-go-type: uint8\n  ```\n\n  will be generated as\n\n  ```go\n  type Object struct {\n          Flag uint8 `json:\"flag\"`\n  }\n  ```\n\n* `x-go-type-import`: Specifies the import package for `x-go-type`.\n                      This has two properties `name` and `path`.\n        `path` is the package import path, e.g. `github.com/google/uuid`.\n        `name` is the package import name, which is optional.\n  For example,\n\n  ```yaml\n  schemas:\n    Object:\n      properties:\n        flag:\n          type: integer\n          x-go-type: mypackage.Flag\n          x-go-type-import:\n            path: abc.xyz/repo/mypackage\n  ```\n\n  will be generated as\n\n  ```go\n  import (\n          \"abc.xyz/repo/mypackage\"\n  )\n\n  // ...\n\n  type Object struct {\n          Flag mypackage.Flag `json:\"flag\"`\n  }\n  ```\n\n  while\n\n  ```yaml\n  schemas:\n    Object:\n      properties:\n        flag:\n          type: integer\n          x-go-type: alias.Flag\n          x-go-type-import:\n            path: abc.xyz/repo/mypackage\n            name: alias\n  ```\n\n  will be generated as\n\n  ```go\n  import (\n          alias \"abc.xyz/repo/mypackage\"\n  )\n\n  // ...\n\n  type Object struct {\n          Flag alias.Flag `json:\"flag\"`\n  }\n  ```\n\n* `x-omitempty`: Controls the addition of the `omitempty` tag in JSON tags of generated Go structures.\n  When set to `false`, the `omitempty` tag won't be added even for optional fields.\n\n  For example,\n\n  ```yaml\n  schemas:\n    User:\n      type: object\n      properties:\n        id:\n          type: string\n        name:\n          type: string\n          x-omitempty: false\n  ```\n\n  will be generated as\n\n  ```go\n  type User struct {\n      Id   *string `json:\"id,omitempty\"`\n      Name *string `json:\"name\"`\n  }\n  ```\n\n### ErrorHandler\n\nYou can use an error handler that will be executed when processing for messages\nfailed. To add a custom ErrorHandler to your controller use the  `WithErrorHandler`\nfunction in the initialization of the App or User controller:\n\n```golang\n// Create a new app controller with ErrorHandler\nctrl, _ := NewAppController(/* Broker of your choice */, WithErrorHandler(myErrorHandler), ...)\n```\n\nHere the function signature that should be satisfied:\n\n```golang\nfunc(ctx context.Context, topic string, msg *AcknowledgeableBrokerMessage, err error)\n```\n\n**Note:** The default ErrorHandler is a Noop ErrorHandler doing nothing. By using a ErrorHandler you can add custom behavior for example to move messages to retry or dead letter topics/queues. \nAcks and Naks will be executed after the ErrorHandler, you can use the AcknowledgeableBrokerMessage in the handler to Ack/Nak the message manually.\n\n#### Examples\n\n##### Use the Logging ErrorHandler\n```golang\n// Create a new app controller with Logging ErrorHandler\nctrl, _ := NewAppController(/* Broker of your choice */, WithErrorHandler(errorhandlers.Logging(mylogger)), ...)\n```\n\n##### Build a custom ErrorHandler and handle Ack/Nak of the message\n```golang\nfunc(ctx context.Context, topic string, msg *extensions.AcknowledgeableBrokerMessage, err error) {\n    // check error or move message to some other queue/topic\n    handleTheErrorSomehow()\n\n    // Ack or Nak the message\n    msg.Ack()\n    msg.Nak()\n}\n```\n\n### Validations\n\nYou can use [go-playground/validator](https://github.com/go-playground/validator) to validate the fields content against the contract.\n\nThe following tags are currently supported:\n\n| Asyncapi         | Validator tag  | Comment                                                      |\n|------------------|----------------|--------------------------------------------------------------|\n| required         | required       | For a full support, the flag `--force-pointers` is necessary |\n| minLength        | min            |                                                              |\n| maxLength        | max            |                                                              |\n| minimum          | gte            |                                                              |\n| maximum          | lte            |                                                              |\n| exclusiveMinimum | gt             |                                                              |\n| exclusiveMaximum | lt             |                                                              |\n| uniqueItems      | unique         | Only for arrays                                              |\n| enum             | oneof          | Only string enum are supported                               |    \n\n\n## Contributing and support\n\nIf you find any bug or lacking a feature, please raise an issue on the Github repository!\n\nAlso please do not hesitate to propose any improvment or bug fix on PR.\nAny contribution is warmly welcomed!\n\nAnd if you find this project useful, please support it through the Support feature\non Github.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flerenn%2Fasyncapi-codegen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flerenn%2Fasyncapi-codegen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flerenn%2Fasyncapi-codegen/lists"}