Skip to content

Commit f4e08ec

Browse files
committed
[WIP] feat(server): OpenAPI spec generation
1 parent e9378e7 commit f4e08ec

File tree

3 files changed

+39
-20
lines changed

3 files changed

+39
-20
lines changed

build.gradle.kts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ apply(from = "version.gradle.kts")
66
plugins {
77
application
88
alias(libs.plugins.kotlin.serialization)
9+
alias(libs.plugins.ktor)
910
id("snoty.buildinfo-conventions")
1011
id("snoty.doctor-conventions")
1112
id("snoty.kotlin-conventions")
@@ -91,6 +92,7 @@ dependencies { with(libs) {
9192
implementation(ktor.server.auth)
9293
implementation(ktor.server.auth.jwt)
9394
implementation(ktor.server.contentNegotiation)
95+
implementation(ktor.server.routing.openapi)
9496

9597
// monitoring
9698
implementation(monitoring.ktor.opentelemetry)
@@ -131,6 +133,14 @@ if (isDevelopment) {
131133
}
132134
}
133135

136+
ktor {
137+
openApi {
138+
enabled = true
139+
codeInferenceEnabled = true
140+
onlyCommented = false
141+
}
142+
}
143+
134144
application {
135145
mainClass.set("me.snoty.backend.MainKt")
136146

gradle/libs.versions.toml

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ jib = { id = "com.google.cloud.tools.jib", version = "3.4.4" }
3232
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
3333
kotlin-kover = { id = "org.jetbrains.kotlinx.kover", version = "0.9.1" }
3434
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
35+
ktor = { id = "io.ktor.plugin", version.ref = "ktor" }
3536

3637
[libraries]
3738
configuration-hoplite-core = { group = "com.sksamuel.hoplite", name = "hoplite-core", version.ref = "hoplite" }
@@ -62,24 +63,25 @@ authentication-keycloak-adminClient = { group = "org.keycloak", name = "keycloak
6263

6364
integrationPlugin-ksp-api = { group = "com.google.devtools.ksp", name = "symbol-processing-api", version.ref = "ksp" }
6465

65-
ktor-client-okhttp = { group = "io.ktor", name = "ktor-client-okhttp-jvm", version.ref = "ktor" }
66-
ktor-client-contentNegotiation = { group = "io.ktor", name = "ktor-client-content-negotiation-jvm", version.ref = "ktor" }
67-
ktor-client-core = { group = "io.ktor", name = "ktor-client-core-jvm", version.ref = "ktor" }
68-
ktor-serialization-kotlinx-json = { group = "io.ktor", name = "ktor-serialization-kotlinx-json-jvm", version.ref = "ktor" }
69-
ktor-server-auth = { group = "io.ktor", name = "ktor-server-auth-jvm", version.ref = "ktor" }
70-
ktor-server-auth-jwt = { group = "io.ktor", name = "ktor-server-auth-jwt-jvm", version.ref = "ktor" }
71-
ktor-server-call-id = { group = "io.ktor", name = "ktor-server-call-id-jvm", version.ref = "ktor" }
72-
ktor-server-call-logging = { group = "io.ktor", name = "ktor-server-call-logging-jvm", version.ref = "ktor" }
73-
ktor-server-contentNegotiation = { group = "io.ktor", name = "ktor-server-content-negotiation-jvm", version.ref = "ktor" }
74-
ktor-server-core = { group = "io.ktor", name = "ktor-server-core-jvm", version.ref = "ktor" }
75-
ktor-server-sse = { group = "io.ktor", name = "ktor-server-sse-jvm", version.ref = "ktor" }
76-
ktor-server-cors = { group = "io.ktor", name = "ktor-server-cors-jvm", version.ref = "ktor" }
77-
ktor-server-defaultHeaders = { group = "io.ktor", name = "ktor-server-default-headers-jvm", version.ref = "ktor" }
78-
ktor-server-doubleReceive = { group = "io.ktor", name = "ktor-server-double-receive-jvm", version.ref = "ktor" }
79-
ktor-server-forwardedHeader = { group = "io.ktor", name = "ktor-server-forwarded-header-jvm", version.ref = "ktor" }
80-
ktor-server-hostCommon = { group = "io.ktor", name = "ktor-server-host-common-jvm", version.ref = "ktor" }
81-
ktor-server-netty = { group = "io.ktor", name = "ktor-server-netty-jvm", version.ref = "ktor" }
82-
ktor-server-statusPages = { group = "io.ktor", name = "ktor-server-status-pages-jvm", version.ref = "ktor" }
66+
ktor-client-okhttp = { group = "io.ktor", name = "ktor-client-okhttp", version.ref = "ktor" }
67+
ktor-client-contentNegotiation = { group = "io.ktor", name = "ktor-client-content-negotiation", version.ref = "ktor" }
68+
ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor" }
69+
ktor-serialization-kotlinx-json = { group = "io.ktor", name = "ktor-serialization-kotlinx-json", version.ref = "ktor" }
70+
ktor-server-auth = { group = "io.ktor", name = "ktor-server-auth", version.ref = "ktor" }
71+
ktor-server-auth-jwt = { group = "io.ktor", name = "ktor-server-auth-jwt", version.ref = "ktor" }
72+
ktor-server-call-id = { group = "io.ktor", name = "ktor-server-call-id", version.ref = "ktor" }
73+
ktor-server-call-logging = { group = "io.ktor", name = "ktor-server-call-logging", version.ref = "ktor" }
74+
ktor-server-contentNegotiation = { group = "io.ktor", name = "ktor-server-content-negotiation", version.ref = "ktor" }
75+
ktor-server-core = { group = "io.ktor", name = "ktor-server-core", version.ref = "ktor" }
76+
ktor-server-routing-openapi = { group = "io.ktor", name = "ktor-server-routing-openapi", version.ref = "ktor" }
77+
ktor-server-sse = { group = "io.ktor", name = "ktor-server-sse", version.ref = "ktor" }
78+
ktor-server-cors = { group = "io.ktor", name = "ktor-server-cors", version.ref = "ktor" }
79+
ktor-server-defaultHeaders = { group = "io.ktor", name = "ktor-server-default-headers", version.ref = "ktor" }
80+
ktor-server-doubleReceive = { group = "io.ktor", name = "ktor-server-double-receive", version.ref = "ktor" }
81+
ktor-server-forwardedHeader = { group = "io.ktor", name = "ktor-server-forwarded-header", version.ref = "ktor" }
82+
ktor-server-hostCommon = { group = "io.ktor", name = "ktor-server-host-common", version.ref = "ktor" }
83+
ktor-server-netty = { group = "io.ktor", name = "ktor-server-netty", version.ref = "ktor" }
84+
ktor-server-statusPages = { group = "io.ktor", name = "ktor-server-status-pages", version.ref = "ktor" }
8385

8486
libraries-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "coroutines" }
8587
libraries-bson-kotlin = { group = "org.mongodb", name = "bson-kotlin", version.ref = "mongodb" }
@@ -97,7 +99,7 @@ log-kotlinLogging = { group = "io.github.oshai", name = "kotlin-logging", versio
9799
log-logback = { group = "ch.qos.logback", name = "logback-classic", version = "1.5.12" }
98100

99101
monitoring-ktor-opentelemetry = { group = "io.opentelemetry.instrumentation", name = "opentelemetry-ktor-3.0", version.ref = "opentelemetry-instrumentation" }
100-
monitoring-ktor-server-metricsMicrometer = { group = "io.ktor", name = "ktor-server-metrics-micrometer-jvm", version.ref = "ktor" }
102+
monitoring-ktor-server-metricsMicrometer = { group = "io.ktor", name = "ktor-server-metrics-micrometer", version.ref = "ktor" }
101103
monitoring-micrometer = { group = "io.micrometer", name = "micrometer-core", version.ref = "micrometer" }
102104
monitoring-micrometer-prometheus = { group = "io.micrometer", name = "micrometer-registry-prometheus", version.ref = "micrometer" }
103105
monitoring-opentelemetry-api = { group = "io.opentelemetry", name = "opentelemetry-api", version.ref = "opentelemetry" }
@@ -114,7 +116,7 @@ monitoring-opentelemetry-testing = { group = "io.opentelemetry", name = "opentel
114116
tests-json = { group = "org.json", name = "json", version = "20250107" }
115117
tests-junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit" }
116118
tests-junit-launcher = { group = "org.junit.platform", name = "junit-platform-launcher", version = "1.12.2" }
117-
tests-ktor-server-testHost = { group = "io.ktor", name = "ktor-server-test-host-jvm", version.ref = "ktor" }
119+
tests-ktor-server-testHost = { group = "io.ktor", name = "ktor-server-test-host", version.ref = "ktor" }
118120
tests-mockk = { group = "io.mockk", name = "mockk", version = "1.13.13" }
119121
tests-testcontainers = { group = "org.testcontainers", name = "testcontainers", version.ref = "testcontainers" }
120122
tests-testcontainers-junit = { group = "org.testcontainers", name = "testcontainers-junit-jupiter", version.ref = "testcontainers" }

src/main/kotlin/me/snoty/backend/server/resources/AboutResource.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package me.snoty.backend.server.resources
22

3+
import io.ktor.openapi.*
34
import io.ktor.server.response.*
45
import io.ktor.server.routing.*
6+
import io.ktor.server.routing.openapi.*
57
import kotlinx.serialization.Serializable
68
import me.snoty.backend.build.BuildInfo
79
import me.snoty.backend.server.routing.Resource
@@ -29,4 +31,9 @@ fun AboutResource(buildInfo: BuildInfo) = Resource {
2931
buildInfo = buildInfo
3032
))
3133
}
34+
35+
get("/openapi.json") {
36+
val doc = OpenApiDoc(info = OpenApiInfo(buildInfo.application, buildInfo.version)) + application.routingRoot.descendants()
37+
call.respond(doc)
38+
}
3239
}

0 commit comments

Comments
 (0)