{"payload":{"feedbackUrl":"https://github.com/orgs/community/discussions/53140","repo":{"id":229844927,"defaultBranch":"master","name":"fabrikt","ownerLogin":"cjbooms","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2019-12-24T00:56:42.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/868640?v=4","public":true,"private":false,"isOrgOwned":false},"refInfo":{"name":"","listCacheKey":"v0:1720965248.0","currentOid":""},"activityList":{"items":[{"before":"aa02621661e5de0398c52e0a1a27e3c18437f191","after":null,"ref":"refs/heads/nullable-arrays","pushedAt":"2024-07-14T11:51:58.000Z","pushType":"branch_deletion","commitsCount":0,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"}},{"before":"9600df34693627f398db5c19a51838aadd6d92cf","after":"8caa7c4bc270fb269dd84c896be1e0bb9252f718","ref":"refs/heads/master","pushedAt":"2024-07-14T11:51:52.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Nullable arrays (#301)\n\n* test: Added nullableArrayItems model generation test\n\n* Fix nullable array parameterized type.\nAlso combining the two latest test cases around nullable true into existing test cases to reduce example set\n\n---------\n\nCo-authored-by: DavidMazarro ","shortMessageHtmlLink":"Nullable arrays (#301)"}},{"before":null,"after":"aa02621661e5de0398c52e0a1a27e3c18437f191","ref":"refs/heads/nullable-arrays","pushedAt":"2024-07-13T21:36:45.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Fix nullable array parameterized type.\nAlso combining the two latest test cases around nullable true into existing test cases to reduce example set","shortMessageHtmlLink":"Fix nullable array parameterized type."}},{"before":"7f2ccb04d5bd31a1ce9f97d32bee97469b824708","after":"9600df34693627f398db5c19a51838aadd6d92cf","ref":"refs/heads/master","pushedAt":"2024-07-13T20:42:58.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"add end2end tests for jackson model generation (#299)\n\n* add end2end tests for jackson model generation\r\n\r\n* add end2end tests for maps\r\n\r\n* add ploymorphisms\r\n\r\n* add end2end tests for deep nested ploymorphism\r\n\r\n* apply review comment: skip nulls\r\n\r\n---------\r\n\r\nCo-authored-by: Jens Zettelmeyer ","shortMessageHtmlLink":"add end2end tests for jackson model generation (#299)"}},{"before":"71103e3867006f162c0acdab3c0de12a240ec0d5","after":"7f2ccb04d5bd31a1ce9f97d32bee97469b824708","ref":"refs/heads/master","pushedAt":"2024-07-10T17:13:38.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Add e2e tests for Ktor server interfaces (#290)","shortMessageHtmlLink":"Add e2e tests for Ktor server interfaces (#290)"}},{"before":"3e642e770e80559e1a02e24a92712f1c9bc4febf","after":null,"ref":"refs/heads/lenient-object-definition","pushedAt":"2024-07-08T22:14:40.000Z","pushType":"branch_deletion","commitsCount":0,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"}},{"before":"750a5cde32dd2a579fecf0e60d83996c9b3b1132","after":"71103e3867006f162c0acdab3c0de12a240ec0d5","ref":"refs/heads/master","pushedAt":"2024-07-08T22:14:36.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Fix Jens issue. (#298)\n\nNeed to be lenient with inline object definitions like we are with top-level, and not require explicit `type: object` non-empty properties should be enough to assume object intent","shortMessageHtmlLink":"Fix Jens issue. (#298)"}},{"before":null,"after":"3e642e770e80559e1a02e24a92712f1c9bc4febf","ref":"refs/heads/lenient-object-definition","pushedAt":"2024-07-08T21:49:28.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Fix Jens issue.\nNeed to be lenient with inline object definitions like we are with top-level, and not require explicit `type: object` non-empty properties should be enough to assume object intent","shortMessageHtmlLink":"Fix Jens issue."}},{"before":"56076f6c90b2efbfbeec0151f5efb67444662b6b","after":"750a5cde32dd2a579fecf0e60d83996c9b3b1132","ref":"refs/heads/master","pushedAt":"2024-07-05T18:20:12.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Update publish.yml\n\nsecrets","shortMessageHtmlLink":"Update publish.yml"}},{"before":"e5f655ddcb0c16c1f984dfac1d42dc1e3eecc71f","after":"56076f6c90b2efbfbeec0151f5efb67444662b6b","ref":"refs/heads/master","pushedAt":"2024-07-05T16:50:19.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Update publish.yml\n\nupdate env variables","shortMessageHtmlLink":"Update publish.yml"}},{"before":"d22cbc130f004d3c3e7a2561f3d06bb8e0886d21","after":"e5f655ddcb0c16c1f984dfac1d42dc1e3eecc71f","ref":"refs/heads/master","pushedAt":"2024-07-05T16:47:02.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Update publish.yml\n\nfix secret","shortMessageHtmlLink":"Update publish.yml"}},{"before":"b1d033561ec41ab8715c5e0e7c8312929e829bda","after":"d22cbc130f004d3c3e7a2561f3d06bb8e0886d21","ref":"refs/heads/master","pushedAt":"2024-07-05T16:32:15.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Update build.gradle.kts\n\nchanging to user token","shortMessageHtmlLink":"Update build.gradle.kts"}},{"before":"254076b254bba5cf6a9483f4fbc3a84543d3756f","after":"b1d033561ec41ab8715c5e0e7c8312929e829bda","ref":"refs/heads/master","pushedAt":"2024-07-05T16:01:35.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Update publish.yml\n\nupdate action version","shortMessageHtmlLink":"Update publish.yml"}},{"before":"8c0852e98a5484391ed23dba9b594bb013f208b9","after":"254076b254bba5cf6a9483f4fbc3a84543d3756f","ref":"refs/heads/master","pushedAt":"2024-07-05T16:01:03.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Update build.yml\n\nupdate action versions","shortMessageHtmlLink":"Update build.yml"}},{"before":"39d34ef0f855f97ea60fc86c7c85da7dc7ee7653","after":"8c0852e98a5484391ed23dba9b594bb013f208b9","ref":"refs/heads/master","pushedAt":"2024-07-05T15:58:03.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Update build.yml","shortMessageHtmlLink":"Update build.yml"}},{"before":"a8c9cc13ae31d77d1a3fc8a6570eed9bd8264f21","after":"39d34ef0f855f97ea60fc86c7c85da7dc7ee7653","ref":"refs/heads/master","pushedAt":"2024-07-05T15:57:47.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Update publish.yml\n\nBump actions version","shortMessageHtmlLink":"Update publish.yml"}},{"before":"6b7334902f3bbb99cf8792a09b2dbda8b8701849","after":"a8c9cc13ae31d77d1a3fc8a6570eed9bd8264f21","ref":"refs/heads/master","pushedAt":"2024-07-05T15:45:47.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"fix: Nullable object fields now working as expected (#291) (#294)\n\n* test: Created test for an object that has a required but nullable field\r\n\r\n* test: Created test for an array of nullable items\r\n\r\n* test: Updated `details` model with a nullable map of nullable values\r\n\r\n* refactor: Replaced if/else-if with when in `createModels`\r\n\r\n* test: Updated `NullableArrayItems` to be nullable\r\n\r\n* refactor: Style changes to be more consistent\r\n\r\n* fix: Nullable object fields (among others) now work as expected\r\n\r\n* test: Removed nullableArrayItems test for now\r\n\r\nCo-authored-by: David Mazarro ","shortMessageHtmlLink":"fix: Nullable object fields now working as expected (#291) (#294)"}},{"before":"6b7334902f3bbb99cf8792a09b2dbda8b8701849","after":"ac4cee20eb0de98fd8572b61b58ca41732447722","ref":"refs/heads/DavidMazarro-fix-nullable","pushedAt":"2024-07-05T15:15:22.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"fix: Nullable object fields now working as expected (#291)\n\n* test: Created test for an object that has a required but nullable field\n\n* test: Created test for an array of nullable items\n\n* test: Updated `details` model with a nullable map of nullable values\n\n* refactor: Replaced if/else-if with when in `createModels`\n\n* test: Updated `NullableArrayItems` to be nullable\n\n* refactor: Style changes to be more consistent\n\n* fix: Nullable object fields (among others) now work as expected\n\n* test: Removed nullableArrayItems test for now","shortMessageHtmlLink":"fix: Nullable object fields now working as expected (#291)"}},{"before":null,"after":"6b7334902f3bbb99cf8792a09b2dbda8b8701849","ref":"refs/heads/DavidMazarro-fix-nullable","pushedAt":"2024-06-21T10:05:55.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Use KotlinPoet %T for call.receive (#288)\n\nFixes an issue where invalid code generated when request body is an list of models.","shortMessageHtmlLink":"Use KotlinPoet %T for call.receive (#288)"}},{"before":"259d4dea31008a85fdbd116d326c57d5870cd191","after":"6b7334902f3bbb99cf8792a09b2dbda8b8701849","ref":"refs/heads/master","pushedAt":"2024-05-23T08:30:00.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Use KotlinPoet %T for call.receive (#288)\n\nFixes an issue where invalid code generated when request body is an list of models.","shortMessageHtmlLink":"Use KotlinPoet %T for call.receive (#288)"}},{"before":"6addbbdcd4efe48b1c293d2b3cb6a91138b16533","after":"259d4dea31008a85fdbd116d326c57d5870cd191","ref":"refs/heads/master","pushedAt":"2024-05-02T20:06:34.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Ktor typed respond functions (#286)\n\n* Introduce generateLibrary on controller generators\n\n* Introduce typed decorator for ApplicationCall\n\nFor routes that respond with content, a decorator is passed to controller functions and enables the implementation to use `call.respondTyped()` which enforces the correct return type for the route.\n\nAll other `call.respondX` functions are still available and thus the decoration functions as a drop-in replacement for ApplicationCall.\n\nFor routes that do not respond with content the regular ApplicationCall is passed.\n\n* Remove unnecessary factory function","shortMessageHtmlLink":"Ktor typed respond functions (#286)"}},{"before":"8c021c20bd5ee7f2cbdc16f01824ff8a44bd91af","after":"6addbbdcd4efe48b1c293d2b3cb6a91138b16533","ref":"refs/heads/master","pushedAt":"2024-04-25T21:26:50.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"fix: don't duplicate classes in nested polymorphic models (#285)\n\n* fix: don't duplicate classes in nested polymorphic models\n\nThis filters the models in groupClasses again, to make sure no sealed\nclasses are generated multiple times.\nGroupClasses was adding the child class to the superclass, even though\nit created it's own class again because it's sealed and has children.\n\n* Remove grouping of Sealed classes entirely. Not required since Kotlin 1.5\n\n* remove redundant test example\n\n---------\n\nCo-authored-by: ymarion ","shortMessageHtmlLink":"fix: don't duplicate classes in nested polymorphic models (#285)"}},{"before":"547f4b66be136b613a5dde93252d06b13ca13166","after":"afeb1bc7fc925ea32f2fbd5106c8dc01c57c3326","ref":"refs/heads/duplicateClassesInPolymorphicSubclasses-2","pushedAt":"2024-04-25T20:14:55.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"remove redundant test example","shortMessageHtmlLink":"remove redundant test example"}},{"before":"0f53a5413eba84a4b4a6df6f2d7248e457895c5d","after":"547f4b66be136b613a5dde93252d06b13ca13166","ref":"refs/heads/duplicateClassesInPolymorphicSubclasses-2","pushedAt":"2024-04-25T20:03:19.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Remove grouping of Sealed classes entirely. Not required since Kotlin 1.5","shortMessageHtmlLink":"Remove grouping of Sealed classes entirely. Not required since Kotlin…"}},{"before":"1e95d4cc67b5bcc946928614c71ff0899db480ef","after":"0f53a5413eba84a4b4a6df6f2d7248e457895c5d","ref":"refs/heads/duplicateClassesInPolymorphicSubclasses-2","pushedAt":"2024-04-25T19:59:00.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Remove grouping of Sealed classes entirely. Not required since Kotlin 1.5","shortMessageHtmlLink":"Remove grouping of Sealed classes entirely. Not required since Kotlin…"}},{"before":"efe95658df1ee8b2ab9b3992dfa180e2e8322253","after":"1e95d4cc67b5bcc946928614c71ff0899db480ef","ref":"refs/heads/duplicateClassesInPolymorphicSubclasses-2","pushedAt":"2024-04-25T19:15:12.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"fix: don't duplicate classes in nested polymorphic models\n\nThis filters the models in groupClasses again, to make sure no sealed\nclasses are generated multiple times.\nGroupClasses was adding the child class to the superclass, even though\nit created it's own class again because it's sealed and has children.","shortMessageHtmlLink":"fix: don't duplicate classes in nested polymorphic models"}},{"before":null,"after":"efe95658df1ee8b2ab9b3992dfa180e2e8322253","ref":"refs/heads/duplicateClassesInPolymorphicSubclasses-2","pushedAt":"2024-04-25T18:59:23.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"fix: don't duplicate classes in nested polymorphic models\n\nThis filters the models in groupClasses again, to make sure no sealed\nclasses are generated multiple times.\nGroupClasses was adding the child class to the superclass, even though\nit created it's own class again because it's sealed and has children.","shortMessageHtmlLink":"fix: don't duplicate classes in nested polymorphic models"}},{"before":null,"after":"8c021c20bd5ee7f2cbdc16f01824ff8a44bd91af","ref":"refs/heads/fix_duplicated_classes_nested_polymorphic_models","pushedAt":"2024-04-25T18:56:16.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Ktor server routes and controller interfaces (#280)\n\n### Design choices\r\n\r\nInspired by #214, Ktor server code is generated as a controller interface with methods for the routes along with a companion object which is used for mounting the routes on the Ktor server (see example further down).\r\n\r\nKtor is by design very flexible, and thus in order for us to be able to generate code we need to make certain design decisions. The approach with routing function + an interface should work well for most cases. The users are still free to configure Ktor however they like, including where they mount the routes and how the implement the controller interface.\r\n\r\nKtor's ApplicationCall is passed to the controller methods to allow them to perform additional logic on the incoming/outgoing request. One might desire to create an extension function for resolving the current user or respond directly with a redirect which requires having access to `call`.\r\n\r\nController methods responsible for responding to the request (`call.respond()`). If no respond is sent, Ktor will respond with 404 per default.\r\n\r\n**Example**\r\n\r\n```kotlin\r\npublic interface InternalEventsController {\r\n\r\n public suspend fun post(bulkEntityDetails: BulkEntityDetails, call: ApplicationCall)\r\n\r\n public companion object {\r\n public fun Route.internalEventsRoutes(controller: InternalEventsController) {\r\n authenticate(\"oauth2\") {\r\n post(\"/internal/events\") {\r\n val bulkEntityDetails = call.receive()\r\n controller.post(bulkEntityDetails, call)\r\n }\r\n }\r\n }\r\n }\r\n}\r\n```\r\n\r\n**Usage example**\r\n\r\n```kotlin\r\nfun main() {\r\n embeddedServer(Netty, port = 8080) {\r\n routing {\r\n internalEventsRoutes(object : InternalEventsController {\r\n override suspend fun post(\r\n bulkEntityDetails: BulkEntityDetails,\r\n call: ApplicationCall\r\n ) {\r\n call.respond(HttpStatusCode.OK, EventResults(emptyList()))\r\n }\r\n })\r\n }\r\n }.start(wait = true)\r\n}\r\n```\r\n\r\nHere the controller interface is implemented as an object, but one could also implement is as a regular class which would make things like dependency injection and modularisation easier.\r\n\r\n### Changes\r\n1. Add Ktor route & controller interface generation.\r\n2. Split controller interface generator abstract class in two; one for annotation based libraries (Spring, Micronaut) and one common for all.\r\n\r\n### Known limitations\r\n1. Headers are always handled as strings. Should be OK for now, but an improvement would be to also handle those in a typed way (including conversion from string).","shortMessageHtmlLink":"Ktor server routes and controller interfaces (#280)"}},{"before":"6e1d953b17e1d3927da008528278ae1dafc6dee6","after":"8c021c20bd5ee7f2cbdc16f01824ff8a44bd91af","ref":"refs/heads/master","pushedAt":"2024-04-25T18:50:11.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"Ktor server routes and controller interfaces (#280)\n\n### Design choices\r\n\r\nInspired by #214, Ktor server code is generated as a controller interface with methods for the routes along with a companion object which is used for mounting the routes on the Ktor server (see example further down).\r\n\r\nKtor is by design very flexible, and thus in order for us to be able to generate code we need to make certain design decisions. The approach with routing function + an interface should work well for most cases. The users are still free to configure Ktor however they like, including where they mount the routes and how the implement the controller interface.\r\n\r\nKtor's ApplicationCall is passed to the controller methods to allow them to perform additional logic on the incoming/outgoing request. One might desire to create an extension function for resolving the current user or respond directly with a redirect which requires having access to `call`.\r\n\r\nController methods responsible for responding to the request (`call.respond()`). If no respond is sent, Ktor will respond with 404 per default.\r\n\r\n**Example**\r\n\r\n```kotlin\r\npublic interface InternalEventsController {\r\n\r\n public suspend fun post(bulkEntityDetails: BulkEntityDetails, call: ApplicationCall)\r\n\r\n public companion object {\r\n public fun Route.internalEventsRoutes(controller: InternalEventsController) {\r\n authenticate(\"oauth2\") {\r\n post(\"/internal/events\") {\r\n val bulkEntityDetails = call.receive()\r\n controller.post(bulkEntityDetails, call)\r\n }\r\n }\r\n }\r\n }\r\n}\r\n```\r\n\r\n**Usage example**\r\n\r\n```kotlin\r\nfun main() {\r\n embeddedServer(Netty, port = 8080) {\r\n routing {\r\n internalEventsRoutes(object : InternalEventsController {\r\n override suspend fun post(\r\n bulkEntityDetails: BulkEntityDetails,\r\n call: ApplicationCall\r\n ) {\r\n call.respond(HttpStatusCode.OK, EventResults(emptyList()))\r\n }\r\n })\r\n }\r\n }.start(wait = true)\r\n}\r\n```\r\n\r\nHere the controller interface is implemented as an object, but one could also implement is as a regular class which would make things like dependency injection and modularisation easier.\r\n\r\n### Changes\r\n1. Add Ktor route & controller interface generation.\r\n2. Split controller interface generator abstract class in two; one for annotation based libraries (Spring, Micronaut) and one common for all.\r\n\r\n### Known limitations\r\n1. Headers are always handled as strings. Should be OK for now, but an improvement would be to also handle those in a typed way (including conversion from string).","shortMessageHtmlLink":"Ktor server routes and controller interfaces (#280)"}},{"before":"cbb86bdc4af73e9252c30470012fc18eb3721971","after":"6e1d953b17e1d3927da008528278ae1dafc6dee6","ref":"refs/heads/master","pushedAt":"2024-04-25T18:48:33.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"cjbooms","name":"Conor Gallagher","path":"/cjbooms","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/868640?s=80&v=4"},"commit":{"message":"test: model tests check generation into multiple files (#283)\n\nThis changes the ModelGeneratorTest so that it checks all files that\r\nwould normally be generated.\r\nRemoves the old Models.kt file and replaces it with the single files","shortMessageHtmlLink":"test: model tests check generation into multiple files (#283)"}}],"hasNextPage":true,"hasPreviousPage":false,"activityType":"all","actor":null,"timePeriod":"all","sort":"DESC","perPage":30,"cursor":"djE6ks8AAAAEfvW91AA","startCursor":null,"endCursor":null}},"title":"Activity · cjbooms/fabrikt"}