fix: free form annotation can be applied to top level type (#219)
This commit is contained in:
@ -12,6 +12,10 @@
|
||||
|
||||
## Released
|
||||
|
||||
## [2.3.1] - March 5th, 2022
|
||||
### Changed
|
||||
- Can now apply `@FreeFormObject` to top level types
|
||||
|
||||
## [2.3.0] - March 1st, 2022
|
||||
### Added
|
||||
- Brand new SwaggerUI support as a KTor plugin with WebJar under the hood and flexible configuration
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Kompendium
|
||||
project.version=2.3.0
|
||||
project.version=2.3.1
|
||||
# Kotlin
|
||||
kotlin.code.style=official
|
||||
# Gradle
|
||||
|
@ -1,5 +1,5 @@
|
||||
package io.bkbn.kompendium.annotations
|
||||
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS)
|
||||
annotation class FreeFormObject
|
||||
|
@ -24,6 +24,7 @@ import kotlin.reflect.KProperty1
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.full.createType
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
import kotlin.reflect.full.hasAnnotation
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.javaField
|
||||
import org.slf4j.LoggerFactory
|
||||
@ -44,6 +45,10 @@ object ObjectHandler : SchemaHandler {
|
||||
// Only analyze if component has not already been stored in the cache
|
||||
if (!cache.containsKey(slug)) {
|
||||
logger.debug("$slug was not found in cache, generating now")
|
||||
// check if free form object
|
||||
if (clazz.hasAnnotation<FreeFormObject>()) {
|
||||
cache[type.getSimpleSlug()] = FreeFormSchema()
|
||||
} else {
|
||||
// todo this should be some kind of empty schema at this point, then throw error if not updated eventually
|
||||
cache[type.getSimpleSlug()] = ReferencedSchema(type.getReferenceSlug())
|
||||
val typeMap: TypeMap = clazz.typeParameters.zip(type.arguments).toMap()
|
||||
@ -59,6 +64,7 @@ object ObjectHandler : SchemaHandler {
|
||||
cache[slug] = schema
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates each member with a Pair of prop name to property schema
|
||||
|
@ -18,6 +18,7 @@ import io.bkbn.kompendium.core.util.exampleParams
|
||||
import io.bkbn.kompendium.core.util.exclusiveMinMax
|
||||
import io.bkbn.kompendium.core.util.formattedParam
|
||||
import io.bkbn.kompendium.core.util.formattedType
|
||||
import io.bkbn.kompendium.core.util.freeFormField
|
||||
import io.bkbn.kompendium.core.util.freeFormObject
|
||||
import io.bkbn.kompendium.core.util.genericPolymorphicResponse
|
||||
import io.bkbn.kompendium.core.util.genericPolymorphicResponseMultipleImpls
|
||||
@ -302,6 +303,9 @@ class KompendiumTest : DescribeSpec({
|
||||
}
|
||||
describe("Free Form") {
|
||||
it("Can create a free-form field") {
|
||||
openApiTestAllSerializers("free_form_field.json") { freeFormField() }
|
||||
}
|
||||
it("Can create a top-level free form object") {
|
||||
openApiTestAllSerializers("free_form_object.json") { freeFormObject() }
|
||||
}
|
||||
}
|
||||
|
@ -579,6 +579,16 @@ fun Application.multipleOfDouble() {
|
||||
}
|
||||
}
|
||||
|
||||
fun Application.freeFormField() {
|
||||
routing {
|
||||
route("/test/required_param") {
|
||||
notarizedGet(TestResponseInfo.freeFormField) {
|
||||
call.respond(HttpStatusCode.OK, TestResponse("hi"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Application.freeFormObject() {
|
||||
routing {
|
||||
route("/test/required_param") {
|
||||
|
70
kompendium-core/src/test/resources/free_form_field.json
Normal file
70
kompendium-core/src/test/resources/free_form_field.json
Normal file
@ -0,0 +1,70 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
"description": "An amazing, fully-ish 😉 generated API spec",
|
||||
"termsOfService": "https://example.com",
|
||||
"contact": {
|
||||
"name": "Homer Simpson",
|
||||
"url": "https://gph.is/1NPUDiM",
|
||||
"email": "chunkylover53@aol.com"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT",
|
||||
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://myawesomeapi.com",
|
||||
"description": "Production instance of my API"
|
||||
},
|
||||
{
|
||||
"url": "https://staging.myawesomeapi.com",
|
||||
"description": "Where the fun stuff happens"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/required_param": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "required param",
|
||||
"description": "Cool stuff",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/FreeFormData"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"FreeFormData": {
|
||||
"properties": {
|
||||
"data": {
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"data"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
||||
},
|
||||
"security": [],
|
||||
"tags": []
|
||||
}
|
@ -38,7 +38,8 @@
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/FreeFormData"
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -49,20 +50,7 @@
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"FreeFormData": {
|
||||
"properties": {
|
||||
"data": {
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"data"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"schemas": {},
|
||||
"securitySchemes": {}
|
||||
},
|
||||
"security": [],
|
||||
|
@ -141,6 +141,9 @@ data class FreeFormData(
|
||||
val data: JsonElement
|
||||
)
|
||||
|
||||
@FreeFormObject
|
||||
object AnythingGoesMan
|
||||
|
||||
data class MinMaxFreeForm(
|
||||
@FreeFormObject
|
||||
@MinProperties(5)
|
||||
|
@ -258,7 +258,13 @@ object TestResponseInfo {
|
||||
responseInfo = simpleOkResponse()
|
||||
)
|
||||
|
||||
val freeFormObject = GetInfo<Unit, FreeFormData>(
|
||||
val freeFormField = GetInfo<Unit, FreeFormData>(
|
||||
summary = "required param",
|
||||
description = "Cool stuff",
|
||||
responseInfo = simpleOkResponse()
|
||||
)
|
||||
|
||||
val freeFormObject = GetInfo<Unit, AnythingGoesMan>(
|
||||
summary = "required param",
|
||||
description = "Cool stuff",
|
||||
responseInfo = simpleOkResponse()
|
||||
|
Reference in New Issue
Block a user