Generates all the boring network API code from a Swagger spec.
Available for:
- Ktor Server
- Ktor Client (soon)
- Swift client (hopefully)
Kebab-Krafter is a gradle plugin to auto-generate network interfaces from a set of swagger API documentation.
To start using the plugin just add to your build.gradle.kts file:
id("com.diconium.mobile.tools.kebab-krafter") version "latest_version"Just add the configuration to your gradle script
ktorServer {
// Root package name for the generated code
packageName = "root.package.name.for.the.generated.code"
// file system location for the swagger spec
specFile = File(rootDir, "swagger/api.yml")
// definition for the receiver class for the API controllers
contextSpec {
packageName = "com.myserver.api"
className = "CallScope"
factoryName = "from"
}
}and with that you can execute ./gradlew generateKtorServer to auto-genearted a Route.installGeneratedRoutes, all the data classes using kotlinx-serialization and the interfaces for each endpoint in the following format:
public interface GetPathName {
public fun CallScope.execute(pathParameters, queryParameters, body) : ResponseBody
}From that you just have to implement the interfaces!
The contextSpec is a "joker-card" to extract any metadata needed from the Ktor.ApplicationCall before passing to the controller. In the sample app you can see it extracting the accept-language header into a Locale object.
In the snippet above the context was named CallScope in the package com.myserver.api, a simple example for it would be:
interface CallScope {
val locale: Locale // define meta-data your controller needs from the request
companion object {
// define a factory function to create the object
fun from(call: ApplicationCall): CallScope = CallScopeImpl(call)
}
}Making this context an interface is advisable, so that it's trivial to unit test the controller by creating a FakeContext()
// implement the real object separetely, to make it trivial to implement unit tests.
private class CallScopeImpl(private val call: ApplicationCall) : CallScope {
override val locale: Locale by lazy {
call.request.acceptLanguage().toLocale()
}
}The generated installGeneratedRoutes receives a object of type ServiceLocator located in the same package of the installGeneratedRoutes.
The ServiceLocator is a very simple get<T> interface that can be adapted to any dependency injection you want to use. For example using Koin it would be something like:
class KoinServiceLocator(private val koin: Koin) : ServiceLocator {
override fun <T : Any> getService(type: KClass<T>): T = koin.get(type)
}Check the sample/ app with the "Pet Store" for a full example.
The most practical way is to open on IntelliJ the sample app. The sample/settings.gradle points to the source code of the plugin and applies it to the project.
After gradle import/index the source code from the plugin will be linked and display on the IDE and it's trivial to do the changes on the plugin and see the effects on the sample.
It might become necessary during the plugin development to disable the task caching and auto-execution.
For that:
- In
KtorServerExtension.ktcomment outOutputDirectoryandOptionalfromoutputFolderand add@get:Console - In
ApplyGenerateKtorServer.ktand replace in bothsourceSet.<type>.srcDirs(task)tosourceSet.<type>.srcDirs(target.defaultOutput).
This way you can control when the code is generated, but it will still be linked to the sourceSet
See also the list of contributors who participated in this project.