diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a5f1d2b7..2324d199f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [1.6.0] - August 12, 2021 + +### Added + +- Ability to add custom type schema overrides for edge case types. + ## [1.5.1] - August 12th, 2021 ### Changed diff --git a/README.md b/README.md index f16e2ac6f..f3aa62f31 100644 --- a/README.md +++ b/README.md @@ -216,6 +216,25 @@ routing { } ``` +## Custom Type Overrides + +Kompendium does its best to analyze types and to generate an OpenAPI format accordingly. However, there are certain +classes that just don't play nice with the standard reflection analysis that Kompendium performs. +Should you encounter a data type that Kompendium cannot comprehend, you will need to +add it explicitly. For example, adding the Joda Time `DateTime` object would be as simple as the following + +```kotlin + Kompendium.addCustomTypeSchema(DateTime::class, FormatSchema("date-time", "string")) +``` + +Since `Kompendium` is an object, this needs to be declared once, ahead of the actual API instantiation. This way, this +type override can be cached ahead of reflection. Kompendium will then match all instances of this type and return the +specified schema. + +So how do you know a type can and cannot be inferred? The safe bet is that it can be. So go ahead and give it a shot. +However, in the very odd scenario (almost always having to do with date/time libraries 😤) where it can't, you can rest +safely knowing that you have the option to inject a custom override should you need to. + ## Limitations ### Kompendium as a singleton @@ -234,7 +253,6 @@ should have. There are several outstanding features that have been added to the - AsyncAPI Integration - Field Validation -- MavenCentral Release If you have a feature that you would like to see implemented that is not on this list, or discover a 🐞, please open an issue [here](https://github.com/bkbnio/kompendium/issues/new) diff --git a/kompendium-core/src/main/kotlin/io/bkbn/kompendium/Kompendium.kt b/kompendium-core/src/main/kotlin/io/bkbn/kompendium/Kompendium.kt index e9ea11559..ab7e8fb90 100644 --- a/kompendium-core/src/main/kotlin/io/bkbn/kompendium/Kompendium.kt +++ b/kompendium-core/src/main/kotlin/io/bkbn/kompendium/Kompendium.kt @@ -4,8 +4,10 @@ import io.bkbn.kompendium.models.meta.ErrorMap import io.bkbn.kompendium.models.meta.SchemaMap import io.bkbn.kompendium.models.oas.OpenApiSpec import io.bkbn.kompendium.models.oas.OpenApiSpecInfo +import io.bkbn.kompendium.models.oas.TypedSchema import io.bkbn.kompendium.path.CorePathCalculator import io.bkbn.kompendium.path.PathCalculator +import kotlin.reflect.KClass /** * Maintains all state for the Kompendium library @@ -31,4 +33,8 @@ object Kompendium { ) cache = emptyMap() } + + fun addCustomTypeSchema(clazz: KClass<*>, schema: TypedSchema) { + cache = cache.plus(clazz.simpleName!! to schema) + } } diff --git a/kompendium-playground/build.gradle.kts b/kompendium-playground/build.gradle.kts index 2438444d9..0ad68b2e2 100644 --- a/kompendium-playground/build.gradle.kts +++ b/kompendium-playground/build.gradle.kts @@ -18,6 +18,8 @@ dependencies { implementation(libs.bundles.ktorAuth) implementation(libs.bundles.logging) + implementation("joda-time:joda-time:2.10.10") + testImplementation("org.jetbrains.kotlin:kotlin-test") testImplementation("org.jetbrains.kotlin:kotlin-test-junit") } diff --git a/kompendium-playground/src/main/kotlin/io/bkbn/kompendium/playground/Main.kt b/kompendium-playground/src/main/kotlin/io/bkbn/kompendium/playground/Main.kt index 1cd5d1b7b..ce17269e0 100644 --- a/kompendium-playground/src/main/kotlin/io/bkbn/kompendium/playground/Main.kt +++ b/kompendium-playground/src/main/kotlin/io/bkbn/kompendium/playground/Main.kt @@ -1,5 +1,6 @@ package io.bkbn.kompendium.playground +import io.bkbn.kompendium.Kompendium import io.bkbn.kompendium.Notarized.notarizedDelete import io.bkbn.kompendium.Notarized.notarizedException import io.bkbn.kompendium.Notarized.notarizedGet @@ -7,7 +8,9 @@ import io.bkbn.kompendium.Notarized.notarizedPost import io.bkbn.kompendium.Notarized.notarizedPut import io.bkbn.kompendium.auth.KompendiumAuth.notarizedBasic import io.bkbn.kompendium.models.meta.ResponseInfo +import io.bkbn.kompendium.models.oas.FormatSchema import io.bkbn.kompendium.playground.PlaygroundToC.testAuthenticatedSingleGetInfo +import io.bkbn.kompendium.playground.PlaygroundToC.testCustomOverride import io.bkbn.kompendium.playground.PlaygroundToC.testGetWithExamples import io.bkbn.kompendium.playground.PlaygroundToC.testIdGetInfo import io.bkbn.kompendium.playground.PlaygroundToC.testPostWithExamples @@ -36,8 +39,11 @@ import io.ktor.serialization.json import io.ktor.server.engine.embeddedServer import io.ktor.server.netty.Netty import io.ktor.webjars.Webjars +import org.joda.time.DateTime fun main() { + Kompendium.addCustomTypeSchema(DateTime::class, FormatSchema("date-time", "string")) + embeddedServer( Netty, port = 8081, @@ -114,6 +120,11 @@ fun Application.mainModule() { call.respondText { "heya" } } } + route("custom_override") { + notarizedGet(testCustomOverride) { + call.respondText { DateTime.now().toString() } + } + } authenticate("basic") { route("/authenticated/single") { notarizedGet(testAuthenticatedSingleGetInfo) { diff --git a/kompendium-playground/src/main/kotlin/io/bkbn/kompendium/playground/Models.kt b/kompendium-playground/src/main/kotlin/io/bkbn/kompendium/playground/Models.kt index 4e6d96b64..ae8ad6496 100644 --- a/kompendium-playground/src/main/kotlin/io/bkbn/kompendium/playground/Models.kt +++ b/kompendium-playground/src/main/kotlin/io/bkbn/kompendium/playground/Models.kt @@ -3,6 +3,7 @@ package io.bkbn.kompendium.playground import io.bkbn.kompendium.annotations.KompendiumField import io.bkbn.kompendium.annotations.KompendiumParam import io.bkbn.kompendium.annotations.ParamType +import org.joda.time.DateTime data class ExampleParams( @KompendiumParam(ParamType.PATH) val id: Int, @@ -30,3 +31,5 @@ data class ExampleResponse(val c: String) data class ExceptionResponse(val message: String) data class ExampleCreatedResponse(val id: Int, val c: String) + +data class DateTimeWrapper(val dt: DateTime) diff --git a/kompendium-playground/src/main/kotlin/io/bkbn/kompendium/playground/PlaygroundToC.kt b/kompendium-playground/src/main/kotlin/io/bkbn/kompendium/playground/PlaygroundToC.kt index 5c822f2cf..745bcef5b 100644 --- a/kompendium-playground/src/main/kotlin/io/bkbn/kompendium/playground/PlaygroundToC.kt +++ b/kompendium-playground/src/main/kotlin/io/bkbn/kompendium/playground/PlaygroundToC.kt @@ -55,6 +55,15 @@ object PlaygroundToC { description = "Returns a different sample" ) ) + val testCustomOverride = MethodInfo.GetInfo( + summary = "custom schema test", + description = "testing", + tags = setOf("custom"), + responseInfo = ResponseInfo( + status = HttpStatusCode.OK, + description = "good tings" + ) + ) val testSingleGetInfoWithThrowable = testSingleGetInfo.copy( summary = "Show me the error baby 🙏", canThrow = setOf(Exception::class)