fix: allow for request bodies to be marked as required=false (#470)

This commit is contained in:
NovolMob
2023-05-22 16:39:04 +03:00
committed by GitHub
parent f49fcb2a22
commit 588e52c9df
6 changed files with 179 additions and 5 deletions

View File

@ -4,9 +4,9 @@
### Added ### Added
### Changed - Added `required` parameter in request info builder.
- Route generation with parameters doesn`t add parameters to the path. ### Changed
### Remove ### Remove

View File

@ -10,7 +10,8 @@ class RequestInfo private constructor(
val typeEnrichment: TypeEnrichment<*>?, val typeEnrichment: TypeEnrichment<*>?,
val description: String, val description: String,
val examples: Map<String, MediaType.Example>?, val examples: Map<String, MediaType.Example>?,
val mediaTypes: Set<String> val mediaTypes: Set<String>,
val required: Boolean
) { ) {
companion object { companion object {
@ -27,6 +28,11 @@ class RequestInfo private constructor(
private var description: String? = null private var description: String? = null
private var examples: Map<String, MediaType.Example>? = null private var examples: Map<String, MediaType.Example>? = null
private var mediaTypes: Set<String>? = null private var mediaTypes: Set<String>? = null
private var required: Boolean? = null
fun required(r: Boolean) = apply {
this.required = r
}
fun requestType(t: KType) = apply { fun requestType(t: KType) = apply {
this.requestType = t this.requestType = t
@ -56,7 +62,8 @@ class RequestInfo private constructor(
description = description ?: error("Description must be present"), description = description ?: error("Description must be present"),
typeEnrichment = typeEnrichment, typeEnrichment = typeEnrichment,
examples = examples, examples = examples,
mediaTypes = mediaTypes ?: setOf("application/json") mediaTypes = mediaTypes ?: setOf("application/json"),
required = required ?: true
) )
} }
} }

View File

@ -131,7 +131,7 @@ object Helpers {
mediaTypes = reqInfo.mediaTypes, mediaTypes = reqInfo.mediaTypes,
enrichment = reqInfo.typeEnrichment enrichment = reqInfo.typeEnrichment
), ),
required = true required = reqInfo.required
) )
} }

View File

@ -52,6 +52,7 @@ import io.bkbn.kompendium.core.util.polymorphicResponse
import io.bkbn.kompendium.core.util.postNoReqBody import io.bkbn.kompendium.core.util.postNoReqBody
import io.bkbn.kompendium.core.util.primitives import io.bkbn.kompendium.core.util.primitives
import io.bkbn.kompendium.core.util.reqRespExamples import io.bkbn.kompendium.core.util.reqRespExamples
import io.bkbn.kompendium.core.util.optionalReqExample
import io.bkbn.kompendium.core.util.requiredParams import io.bkbn.kompendium.core.util.requiredParams
import io.bkbn.kompendium.core.util.responseHeaders import io.bkbn.kompendium.core.util.responseHeaders
import io.bkbn.kompendium.core.util.returnsList import io.bkbn.kompendium.core.util.returnsList
@ -178,6 +179,9 @@ class KompendiumTest : DescribeSpec({
it("Can describe example parameters") { it("Can describe example parameters") {
openApiTestAllSerializers("T0021__example_parameters.json") { exampleParams() } openApiTestAllSerializers("T0021__example_parameters.json") { exampleParams() }
} }
it("Can generate example optional request body") {
openApiTestAllSerializers("T0069__example_optional_req.json") { optionalReqExample() }
}
} }
describe("Defaults") { describe("Defaults") {
it("Can generate a default parameter value") { it("Can generate a default parameter value") {

View File

@ -55,3 +55,30 @@ fun Routing.exampleParams() = basicGetGenerator<TestResponse>(
) )
) )
) )
fun Routing.optionalReqExample() {
route(rootPath) {
install(NotarizedRoute()) {
post = PostInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
description(defaultRequestDescription)
requestType<TestRequest>()
examples(
"Testerina" to TestRequest(TestNested("asdf"), 1.5, emptyList())
)
required(false)
}
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
examples(
"Testerino" to TestResponse("Heya")
)
}
}
}
}
}

View File

@ -0,0 +1,136 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"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": {
"/": {
"post": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"requestBody": {
"description": "You gotta send it",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestRequest"
},
"examples": {
"Testerina": {
"value": {
"fieldName": {
"nesty": "asdf"
},
"b": 1.5,
"aaa": []
}
}
}
}
},
"required": false
},
"responses": {
"200": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestResponse"
},
"examples": {
"Testerino": {
"value": {
"c": "Heya"
}
}
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"TestResponse": {
"type": "object",
"properties": {
"c": {
"type": "string"
}
},
"required": [
"c"
]
},
"TestRequest": {
"type": "object",
"properties": {
"aaa": {
"items": {
"type": "number",
"format": "int64"
},
"type": "array"
},
"b": {
"type": "number",
"format": "double"
},
"fieldName": {
"$ref": "#/components/schemas/TestNested"
}
},
"required": [
"aaa",
"b",
"fieldName"
]
},
"TestNested": {
"type": "object",
"properties": {
"nesty": {
"type": "string"
}
},
"required": [
"nesty"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}