diff options
3 files changed, 38 insertions, 4 deletions
diff --git a/server/core/build.gradle.kts b/server/core/build.gradle.kts index deee068..f254df1 100644 --- a/server/core/build.gradle.kts +++ b/server/core/build.gradle.kts @@ -2,6 +2,7 @@ plugins { kotlin("jvm") kotlin("plugin.serialization") application + id("com.github.gmazzo.buildconfig") } @@ -29,3 +30,6 @@ application { "-Dledger.databasefolder=${project(":mod").file("run/money-ledger").absoluteFile}") mainClass.set("moe.nea.ledger.server.core.ApplicationKt") } +buildConfig { + packageName("moe.nea.ledger.gen") +} diff --git a/server/core/src/main/kotlin/moe/nea/ledger/server/core/Application.kt b/server/core/src/main/kotlin/moe/nea/ledger/server/core/Application.kt index 56492db..eef43d6 100644 --- a/server/core/src/main/kotlin/moe/nea/ledger/server/core/Application.kt +++ b/server/core/src/main/kotlin/moe/nea/ledger/server/core/Application.kt @@ -12,11 +12,14 @@ import io.ktor.server.routing.route import io.ktor.server.routing.routing import kotlinx.serialization.json.Json import moe.nea.ledger.database.Database +import moe.nea.ledger.gen.BuildConfig import moe.nea.ledger.server.core.api.Documentation import moe.nea.ledger.server.core.api.Info +import moe.nea.ledger.server.core.api.Server import moe.nea.ledger.server.core.api.apiRouting import moe.nea.ledger.server.core.api.openApiDocsJson import moe.nea.ledger.server.core.api.openApiUi +import moe.nea.ledger.server.core.api.setApiRoot import java.io.File fun main(args: Array<String>) { @@ -30,7 +33,10 @@ fun Application.module() { info = Info( "Ledger Analysis Server", "Your local API for loading ledger data", - "TODO: buildconfig" + BuildConfig.VERSION + ) + servers.add( + Server("http://localhost:8080/api", "Your Local Server") ) } install(ContentNegotiation) { @@ -44,8 +50,9 @@ fun Application.module() { database.loadAndUpgrade() routing { route("/api") { - this.apiRouting(database) + setApiRoot() get { call.respondRedirect("/openapi/") } + apiRouting(database) } route("/api.json") { openApiDocsJson() diff --git a/server/swagger/src/main/kotlin/moe/nea/ledger/server/core/api/docs.kt b/server/swagger/src/main/kotlin/moe/nea/ledger/server/core/api/docs.kt index fd63f81..5d222ee 100644 --- a/server/swagger/src/main/kotlin/moe/nea/ledger/server/core/api/docs.kt +++ b/server/swagger/src/main/kotlin/moe/nea/ledger/server/core/api/docs.kt @@ -7,6 +7,8 @@ import io.ktor.http.content.OutgoingContent import io.ktor.http.defaultForFilePath import io.ktor.server.application.ApplicationCallPipeline import io.ktor.server.application.BaseApplicationPlugin +import io.ktor.server.application.host +import io.ktor.server.application.port import io.ktor.server.response.respond import io.ktor.server.response.respondText import io.ktor.server.routing.HttpMethodRouteSelector @@ -239,6 +241,12 @@ class Documentation(config: Configuration) { override fun install(pipeline: ApplicationCallPipeline, configure: Configuration.() -> Unit): Documentation { val config = Configuration().also(configure) + if (config.servers.isEmpty()) { + config.servers.add(Server( + "http://${pipeline.environment.config.host}:${pipeline.environment.config.port}", + "Server", + )) + } val plugin = Documentation(config) return plugin } @@ -246,6 +254,9 @@ class Documentation(config: Configuration) { val info = config.info var root: RoutingNode? = null + private set + val servers: List<Server> = config.servers + private val documentationNodes = mutableMapOf<DocumentationPath, DocumentationContext>() fun createDocumentationNode(endpoint: DocumentationEndpoint) = documentationNodes.getOrPut(endpoint.path) { DocumentationContext(endpoint.path) } @@ -254,8 +265,7 @@ class Documentation(config: Configuration) { private val openApiJson by lazy { OpenApiModel( info = info, - // TODO: generate server list better - servers = listOf(Server("http://localhost:8080", "Local Server")), + servers = servers, paths = documentationNodes.map { OpenApiPath(it.key.path) to it.value.intoJson() }.toMap() @@ -266,12 +276,18 @@ class Documentation(config: Configuration) { return openApiJson } + fun setRootNode(routingNode: RoutingNode) { + require(documentationNodes.isEmpty()) { "Cannot set API root node after routes have been documented: ${documentationNodes.keys}" } + this.root = routingNode + } + class Configuration { var info: Info = Info( title = "Example API Docs", description = "Missing description", version = "0.0.0" ) + val servers: MutableList<Server> = mutableListOf() } } @@ -282,3 +298,10 @@ fun Route.docs(block: DocumentationOperationContext.() -> Unit) { block(node) } +/** + * Mark this current routing node as API route. Note that this will not apply retroactively and all api requests must be declared relative to this one. + */ +fun Route.setApiRoot() { + plugin(Documentation).setRootNode(this as RoutingNode) +} + |