encode oas to json internally (#69)

This commit is contained in:
Ryan Brink
2021-06-04 16:51:06 -04:00
committed by GitHub
parent aa3290243b
commit 925172cf86
39 changed files with 309 additions and 284 deletions

View File

@ -1,5 +1,11 @@
# Changelog
## [1.3.0] - June 4th, 2021
### Changed
- Explicitly encode JSON object by default
## [1.2.3] - June 3rd, 2021
### Added

View File

@ -104,13 +104,8 @@ suggestions on better implementations are welcome 🤠
### Serialization
Kompendium is serialization agnostic, meaning that there is no serializer library included out of the box. This grants
developer flexibility, at the cost of some potential extra legwork. The example in the playground shows Jackson working
pretty much out of the box, but more explicit serializers like Moshi and Kotlinx Serialization will require registering
custom serializers in order to encode the api spec payload.
This overhead is annoying, and will hopefully be reduced in the future. Should you have ideas on how to tackle this
issue, please head on over to the discussion on this topic [here](https://github.com/bkbnio/kompendium/discussions/64)
Under the hood, Kompendium uses Jackson to serialize the final api spec. However, this implementation detail
does not leak to the actual API, meaning that users are free to choose the serialization library of their choice.
## Examples

View File

@ -1,7 +1,7 @@
import com.adarshr.gradle.testlogger.theme.ThemeType
import com.adarshr.gradle.testlogger.TestLoggerExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import com.adarshr.gradle.testlogger.theme.ThemeType
import io.gitlab.arturbosch.detekt.extensions.DetektExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.jetbrains.kotlin.jvm") version "1.5.0" apply false

View File

@ -1,5 +1,5 @@
# Kompendium
project.version=1.2.3
project.version=1.3.0
# Kotlin
kotlin.code.style=official
# Gradle

View File

@ -1,6 +1,8 @@
[versions]
kotlin = "1.4.32"
ktor = "1.5.3"
kotlinx-serialization = "1.2.1"
jackson-kotlin = "2.12.0"
slf4j = "1.7.30"
logback = "1.2.3"
swagger-ui = "3.47.1"
@ -10,11 +12,17 @@ swagger-ui = "3.47.1"
ktor-server-core = { group = "io.ktor", name = "ktor-server-core", version.ref = "ktor" }
ktor-server-netty = { group = "io.ktor", name = "ktor-server-netty", version.ref = "ktor" }
ktor-jackson = { group = "io.ktor", name = "ktor-jackson", version.ref = "ktor" }
ktor-serialization = { group = "io.ktor", name = "ktor-serialization", version.ref = "ktor" }
ktor-html-builder = { group = "io.ktor", name = "ktor-html-builder", version.ref = "ktor" }
ktor-auth-lib = { group = "io.ktor", name = "ktor-auth", version.ref = "ktor" }
ktor-auth-jwt = { group = "io.ktor", name = "ktor-auth-jwt", version.ref = "ktor" }
ktor-webjars = { group = "io.ktor", name = "ktor-webjars", version.ref = "ktor" }
# Serialization
jackson-module-kotlin = { group = "com.fasterxml.jackson.module", name = "jackson-module-kotlin", version.ref = "jackson-kotlin" }
kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
# Logging
slf4j = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4j" }
logback-classic = { group = "ch.qos.logback", name = "logback-classic", version.ref = "logback" }
@ -23,7 +31,10 @@ logback-core = { group = "ch.qos.logback", name = "logback-core", version.ref =
# webjars
webjars-swagger-ui = { group = "org.webjars", name = "swagger-ui", version.ref = "swagger-ui" }
# Testing
ktor-server-test-host = { group = "io.ktor", name = "ktor-server-test-host", version.ref = "ktor" }
[bundles]
ktor = [ "ktor-server-core", "ktor-server-netty", "ktor-html-builder" ]
ktorAuth = [ "ktor-auth-lib", "ktor-auth-jwt" ]
logging = [ "slf4j", "logback-classic", "logback-core" ]
ktor = ["ktor-server-core", "ktor-server-netty", "ktor-html-builder"]
ktorAuth = ["ktor-auth-lib", "ktor-auth-jwt"]
logging = ["slf4j", "logback-classic", "logback-core"]

View File

@ -14,8 +14,8 @@ dependencies {
testImplementation(libs.ktor.jackson)
testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.12.0")
testImplementation("io.ktor:ktor-server-test-host:1.5.3")
testImplementation(libs.jackson.module.kotlin)
testImplementation(libs.ktor.server.test.host)
}
java {

View File

@ -20,8 +20,8 @@
"name" : "aa",
"in" : "query",
"schema" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -51,16 +51,16 @@
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : {

View File

@ -20,8 +20,8 @@
"name" : "aa",
"in" : "query",
"schema" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -51,16 +51,16 @@
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : {

View File

@ -20,8 +20,8 @@
"name" : "aa",
"in" : "query",
"schema" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -51,16 +51,16 @@
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : {

View File

@ -20,8 +20,8 @@
"name" : "aa",
"in" : "query",
"schema" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -51,16 +51,16 @@
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : {

View File

@ -20,8 +20,8 @@
"name" : "aa",
"in" : "query",
"schema" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -52,16 +52,16 @@
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : {

View File

@ -7,12 +7,14 @@ plugins {
dependencies {
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation(libs.jackson.module.kotlin)
implementation(libs.bundles.ktor)
testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
testImplementation(libs.ktor.serialization)
testImplementation(libs.kotlinx.serialization.json)
testImplementation(libs.ktor.jackson)
testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.12.0")
testImplementation("io.ktor:ktor-server-test-host:1.5.3")
testImplementation(libs.ktor.server.test.host)
}
java {

View File

@ -1,20 +1,26 @@
package io.bkbn.kompendium.routes
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import io.bkbn.kompendium.models.oas.OpenApiSpec
import io.ktor.application.call
import io.ktor.response.respond
import io.ktor.response.respondText
import io.ktor.routing.Routing
import io.ktor.routing.get
import io.ktor.routing.route
import io.bkbn.kompendium.models.oas.OpenApiSpec
/**
* Provides an out-of-the-box route to return the generated [OpenApiSpec]
* @param oas spec that is returned
*/
fun Routing.openApi(oas: OpenApiSpec) {
val om = ObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.enable(SerializationFeature.INDENT_OUTPUT)
route("/openapi.json") {
get {
call.respond(oas)
call.respondText { om.writeValueAsString(oas) }
}
}
}

View File

@ -18,10 +18,11 @@ import io.bkbn.kompendium.routes.openApi
import io.bkbn.kompendium.routes.redoc
import io.bkbn.kompendium.util.TestHelpers.getFileSnapshot
import io.bkbn.kompendium.util.complexType
import io.bkbn.kompendium.util.configModule
import io.bkbn.kompendium.util.jacksonConfigModule
import io.bkbn.kompendium.util.emptyGet
import io.bkbn.kompendium.util.genericPolymorphicResponse
import io.bkbn.kompendium.util.genericPolymorphicResponseMultipleImpls
import io.bkbn.kompendium.util.kotlinxConfigModule
import io.bkbn.kompendium.util.nestedUnderRootModule
import io.bkbn.kompendium.util.nonRequiredParamsGet
import io.bkbn.kompendium.util.notarizedDeleteModule
@ -57,7 +58,7 @@ internal class KompendiumTest {
@Test
fun `Notarized Get records all expected information`() {
withTestApplication({
configModule()
kotlinxConfigModule()
docs()
notarizedGetModule()
}) {
@ -73,7 +74,7 @@ internal class KompendiumTest {
@Test
fun `Notarized Get does not interrupt the pipeline`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
notarizedGetModule()
}) {
@ -89,7 +90,7 @@ internal class KompendiumTest {
@Test
fun `Notarized Post records all expected information`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
notarizedPostModule()
}) {
@ -105,7 +106,7 @@ internal class KompendiumTest {
@Test
fun `Notarized post does not interrupt the pipeline`() {
withTestApplication({
configModule()
kotlinxConfigModule()
docs()
notarizedPostModule()
}) {
@ -121,7 +122,7 @@ internal class KompendiumTest {
@Test
fun `Notarized Put records all expected information`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
notarizedPutModule()
}) {
@ -138,7 +139,7 @@ internal class KompendiumTest {
@Test
fun `Notarized put does not interrupt the pipeline`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
notarizedPutModule()
}) {
@ -154,7 +155,7 @@ internal class KompendiumTest {
@Test
fun `Notarized delete records all expected information`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
notarizedDeleteModule()
}) {
@ -170,7 +171,7 @@ internal class KompendiumTest {
@Test
fun `Notarized delete does not interrupt the pipeline`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
notarizedDeleteModule()
}) {
@ -185,7 +186,7 @@ internal class KompendiumTest {
@Test
fun `Path parser stores the expected path`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
pathParsingTestModule()
}) {
@ -201,7 +202,7 @@ internal class KompendiumTest {
@Test
fun `Can notarize the root route`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
rootModule()
}) {
@ -217,7 +218,7 @@ internal class KompendiumTest {
@Test
fun `Can call the root route`() {
withTestApplication({
configModule()
kotlinxConfigModule()
docs()
rootModule()
}) {
@ -233,7 +234,7 @@ internal class KompendiumTest {
@Test
fun `Nested under root module does not append trailing slash`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
nestedUnderRootModule()
}) {
@ -249,7 +250,7 @@ internal class KompendiumTest {
@Test
fun `Can notarize a trailing slash route`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
trailingSlash()
}) {
@ -265,7 +266,7 @@ internal class KompendiumTest {
@Test
fun `Can call a trailing slash route`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
trailingSlash()
}) {
@ -281,7 +282,7 @@ internal class KompendiumTest {
@Test
fun `Can notarize a complex type`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
complexType()
}) {
@ -297,7 +298,7 @@ internal class KompendiumTest {
@Test
fun `Can notarize primitives`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
primitives()
}) {
@ -313,7 +314,7 @@ internal class KompendiumTest {
@Test
fun `Can notarize a top level list response`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
returnsList()
}) {
@ -329,7 +330,7 @@ internal class KompendiumTest {
@Test
fun `Can notarize route with no request params and no response body`() {
withTestApplication({
configModule()
kotlinxConfigModule()
docs()
emptyGet()
}) {
@ -345,7 +346,7 @@ internal class KompendiumTest {
@Test
fun `Can notarize route with non-required params`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
nonRequiredParamsGet()
}) {
@ -361,7 +362,7 @@ internal class KompendiumTest {
@Test
fun `Generates the expected redoc`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
returnsList()
}) {
@ -378,7 +379,7 @@ internal class KompendiumTest {
fun `Generates additional responses when passed a throwable`() {
withTestApplication({
statusPageModule()
configModule()
jacksonConfigModule()
docs()
notarizedGetWithNotarizedException()
}) {
@ -395,7 +396,7 @@ internal class KompendiumTest {
fun `Generates additional responses when passed multiple throwables`() {
withTestApplication({
statusPageMultiExceptions()
configModule()
jacksonConfigModule()
docs()
notarizedGetWithMultipleThrowables()
}) {
@ -411,7 +412,7 @@ internal class KompendiumTest {
@Test
fun `Can generate example response and request bodies`() {
withTestApplication({
configModule()
kotlinxConfigModule()
docs()
withExamples()
}) {
@ -427,7 +428,7 @@ internal class KompendiumTest {
@Test
fun `Can generate a default parameter value`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
withDefaultParameter()
}) {
@ -443,7 +444,7 @@ internal class KompendiumTest {
@Test
fun `Can generate a polymorphic response type`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
polymorphicResponse()
}) {
@ -459,7 +460,7 @@ internal class KompendiumTest {
@Test
fun `Can generate a response type with a generic type`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
simpleGenericResponse()
}) {
@ -475,7 +476,7 @@ internal class KompendiumTest {
@Test
fun `Can generate a polymorphic response type with generics`() {
withTestApplication({
configModule()
jacksonConfigModule()
docs()
genericPolymorphicResponse()
}) {
@ -491,7 +492,7 @@ internal class KompendiumTest {
@Test
fun `Absolute Psycho Inheritance Test`() {
withTestApplication({
configModule()
kotlinxConfigModule()
docs()
genericPolymorphicResponseMultipleImpls()
}) {

View File

@ -21,8 +21,9 @@ import io.ktor.response.respond
import io.ktor.response.respondText
import io.ktor.routing.route
import io.ktor.routing.routing
import io.ktor.serialization.json
fun Application.configModule() {
fun Application.jacksonConfigModule() {
install(ContentNegotiation) {
jackson {
enable(SerializationFeature.INDENT_OUTPUT)
@ -31,6 +32,12 @@ fun Application.configModule() {
}
}
fun Application.kotlinxConfigModule() {
install(ContentNegotiation) {
json()
}
}
fun Application.statusPageModule() {
install(StatusPages) {
notarizedException<Exception, ExceptionResponse>(

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -62,24 +62,25 @@
"type" : "string"
},
"SimpleEnum" : {
"enum" : [ "ONE", "TWO" ],
"type" : "string"
"type" : "string",
"enum" : [ "ONE", "TWO" ]
},
"CrazyItem" : {
"type" : "object",
"properties" : {
"enumeration" : {
"$ref" : "#/components/schemas/SimpleEnum"
}
},
"type" : "object"
}
},
"Map-String-CrazyItem" : {
"type" : "object",
"additionalProperties" : {
"$ref" : "#/components/schemas/CrazyItem"
},
"type" : "object"
}
},
"NestedComplexItem" : {
"type" : "object",
"properties" : {
"alias" : {
"$ref" : "#/components/schemas/Map-String-CrazyItem"
@ -87,16 +88,16 @@
"name" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"List-NestedComplexItem" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/NestedComplexItem"
},
"type" : "array"
}
},
"ComplexRequest" : {
"type" : "object",
"properties" : {
"amazingField" : {
"$ref" : "#/components/schemas/String"
@ -107,14 +108,14 @@
"tables" : {
"$ref" : "#/components/schemas/List-NestedComplexItem"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"TestCreatedResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
@ -122,8 +123,7 @@
"id" : {
"$ref" : "#/components/schemas/Int"
}
},
"type" : "object"
}
}
},
"securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -80,22 +80,23 @@
"type" : "string"
},
"TestNested" : {
"type" : "object",
"properties" : {
"nesty" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Gibbity-TestNested" : {
"type" : "object",
"properties" : {
"a" : {
"$ref" : "#/components/schemas/TestNested"
}
},
"type" : "object"
}
},
"Bibbity-TestNested" : {
"type" : "object",
"properties" : {
"b" : {
"$ref" : "#/components/schemas/String"
@ -103,22 +104,22 @@
"f" : {
"$ref" : "#/components/schemas/TestNested"
}
},
"type" : "object"
}
},
"SimpleGibbit" : {
"type" : "object",
"properties" : {
"a" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"ComplexGibbit" : {
"type" : "object",
"properties" : {
"b" : {
"$ref" : "#/components/schemas/String"
@ -126,10 +127,10 @@
"c" : {
"$ref" : "#/components/schemas/Int"
}
},
"type" : "object"
}
},
"Gibbity-FlibbityGibbit" : {
"type" : "object",
"properties" : {
"a" : {
"anyOf" : [ {
@ -138,10 +139,10 @@
"$ref" : "#/components/schemas/ComplexGibbit"
} ]
}
},
"type" : "object"
}
},
"Bibbity-FlibbityGibbit" : {
"type" : "object",
"properties" : {
"b" : {
"$ref" : "#/components/schemas/String"
@ -153,8 +154,7 @@
"$ref" : "#/components/schemas/ComplexGibbit"
} ]
}
},
"type" : "object"
}
}
},
"securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -86,31 +86,32 @@
"components" : {
"schemas" : {
"Long" : {
"format" : "int64",
"type" : "integer"
"type" : "integer",
"format" : "int64"
},
"List-Long" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/Long"
},
"type" : "array"
}
},
"Double" : {
"format" : "double",
"type" : "number"
"type" : "number",
"format" : "double"
},
"String" : {
"type" : "string"
},
"TestNested" : {
"type" : "object",
"properties" : {
"nesty" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"TestRequest" : {
"type" : "object",
"properties" : {
"aaa" : {
"$ref" : "#/components/schemas/List-Long"
@ -121,16 +122,15 @@
"fieldName" : {
"$ref" : "#/components/schemas/TestNested"
}
},
"type" : "object"
}
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
}
},
"securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -51,10 +51,11 @@
"type" : "string"
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"TestGeneric-Int" : {
"type" : "object",
"properties" : {
"messy" : {
"$ref" : "#/components/schemas/String"
@ -62,8 +63,7 @@
"potato" : {
"$ref" : "#/components/schemas/Int"
}
},
"type" : "object"
}
}
},
"securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa",
"in" : "query",
"schema" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -68,16 +68,16 @@
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa",
"in" : "query",
"schema" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -61,8 +61,8 @@
"type" : "string"
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa",
"in" : "query",
"schema" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -68,16 +68,16 @@
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa",
"in" : "query",
"schema" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -78,24 +78,24 @@
"type" : "string"
},
"ExceptionResponse" : {
"type" : "object",
"properties" : {
"message" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa",
"in" : "query",
"schema" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -81,24 +81,24 @@
"type" : "string"
},
"ExceptionResponse" : {
"type" : "object",
"properties" : {
"message" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa",
"in" : "query",
"schema" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -76,31 +76,32 @@
"components" : {
"schemas" : {
"Long" : {
"format" : "int64",
"type" : "integer"
"type" : "integer",
"format" : "int64"
},
"List-Long" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/Long"
},
"type" : "array"
}
},
"Double" : {
"format" : "double",
"type" : "number"
"type" : "number",
"format" : "double"
},
"String" : {
"type" : "string"
},
"TestNested" : {
"type" : "object",
"properties" : {
"nesty" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"TestRequest" : {
"type" : "object",
"properties" : {
"aaa" : {
"$ref" : "#/components/schemas/List-Long"
@ -111,14 +112,14 @@
"fieldName" : {
"$ref" : "#/components/schemas/TestNested"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"TestCreatedResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
@ -126,8 +127,7 @@
"id" : {
"$ref" : "#/components/schemas/Int"
}
},
"type" : "object"
}
}
},
"securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -59,8 +59,8 @@
"components" : {
"schemas" : {
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"Boolean" : {
"type" : "boolean"

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa",
"in" : "query",
"schema" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -76,31 +76,32 @@
"components" : {
"schemas" : {
"Long" : {
"format" : "int64",
"type" : "integer"
"type" : "integer",
"format" : "int64"
},
"List-Long" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/Long"
},
"type" : "array"
}
},
"Double" : {
"format" : "double",
"type" : "number"
"type" : "number",
"format" : "double"
},
"String" : {
"type" : "string"
},
"TestNested" : {
"type" : "object",
"properties" : {
"nesty" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"TestRequest" : {
"type" : "object",
"properties" : {
"aaa" : {
"$ref" : "#/components/schemas/List-Long"
@ -111,14 +112,14 @@
"fieldName" : {
"$ref" : "#/components/schemas/TestNested"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"TestCreatedResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
@ -126,8 +127,7 @@
"id" : {
"$ref" : "#/components/schemas/Int"
}
},
"type" : "object"
}
}
},
"securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa",
"in" : "query",
"schema" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -68,16 +68,16 @@
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -55,18 +55,19 @@
"type" : "string"
},
"SimpleGibbit" : {
"type" : "object",
"properties" : {
"a" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"ComplexGibbit" : {
"type" : "object",
"properties" : {
"b" : {
"$ref" : "#/components/schemas/String"
@ -74,8 +75,7 @@
"c" : {
"$ref" : "#/components/schemas/Int"
}
},
"type" : "object"
}
}
},
"securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -55,22 +55,23 @@
"type" : "string"
},
"TestNested" : {
"type" : "object",
"properties" : {
"nesty" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Gibbity-TestNested" : {
"type" : "object",
"properties" : {
"a" : {
"$ref" : "#/components/schemas/TestNested"
}
},
"type" : "object"
}
},
"Bibbity-TestNested" : {
"type" : "object",
"properties" : {
"b" : {
"$ref" : "#/components/schemas/String"
@ -78,8 +79,7 @@
"f" : {
"$ref" : "#/components/schemas/TestNested"
}
},
"type" : "object"
}
}
},
"securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -32,9 +32,9 @@
"name" : "a",
"in" : "query",
"schema" : {
"format" : "int32",
"default" : 100,
"type" : "integer",
"default" : 100
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -65,16 +65,16 @@
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"Boolean" : {
"type" : "boolean"

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa",
"in" : "query",
"schema" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -68,22 +68,22 @@
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"List-TestResponse" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/TestResponse"
},
"type" : "array"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa",
"in" : "query",
"schema" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -68,16 +68,16 @@
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa",
"in" : "query",
"schema" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
@ -68,16 +68,16 @@
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
},
"type" : "object"
}
},
"Int" : {
"format" : "int32",
"type" : "integer"
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : { }

View File

@ -13,6 +13,8 @@ dependencies {
implementation(libs.bundles.ktor)
implementation(libs.ktor.jackson)
implementation(libs.kotlinx.serialization.json)
implementation(libs.ktor.serialization)
implementation(libs.bundles.ktorAuth)
implementation(libs.bundles.logging)

View File

@ -1,24 +1,5 @@
package io.bkbn.kompendium.playground
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.databind.SerializationFeature
import io.ktor.application.Application
import io.ktor.application.call
import io.ktor.application.install
import io.ktor.auth.Authentication
import io.ktor.auth.UserIdPrincipal
import io.ktor.auth.authenticate
import io.ktor.features.ContentNegotiation
import io.ktor.features.StatusPages
import io.ktor.http.HttpStatusCode
import io.ktor.jackson.jackson
import io.ktor.response.respond
import io.ktor.response.respondText
import io.ktor.routing.route
import io.ktor.routing.routing
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import io.ktor.webjars.Webjars
import io.bkbn.kompendium.Notarized.notarizedDelete
import io.bkbn.kompendium.Notarized.notarizedException
import io.bkbn.kompendium.Notarized.notarizedGet
@ -38,6 +19,23 @@ import io.bkbn.kompendium.playground.PlaygroundToC.testSinglePutInfo
import io.bkbn.kompendium.routes.openApi
import io.bkbn.kompendium.routes.redoc
import io.bkbn.kompendium.swagger.swaggerUI
import io.ktor.application.Application
import io.ktor.application.call
import io.ktor.application.install
import io.ktor.auth.Authentication
import io.ktor.auth.UserIdPrincipal
import io.ktor.auth.authenticate
import io.ktor.features.ContentNegotiation
import io.ktor.features.StatusPages
import io.ktor.http.HttpStatusCode
import io.ktor.response.respond
import io.ktor.response.respondText
import io.ktor.routing.route
import io.ktor.routing.routing
import io.ktor.serialization.json
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import io.ktor.webjars.Webjars
fun main() {
embeddedServer(
@ -52,10 +50,7 @@ var featuresInstalled = false
fun Application.configModule() {
if (!featuresInstalled) {
install(ContentNegotiation) {
jackson {
enable(SerializationFeature.INDENT_OUTPUT)
setSerializationInclusion(JsonInclude.Include.NON_NULL)
}
json()
}
install(Authentication) {
notarizedBasic("basic") {

View File

@ -12,8 +12,8 @@ dependencies {
implementation(libs.webjars.swagger.ui)
testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.12.0")
testImplementation("io.ktor:ktor-server-test-host:1.5.3")
testImplementation(libs.jackson.module.kotlin)
testImplementation(libs.ktor.server.test.host)
}
java {