parameter support (#27)
This commit is contained in:
10
CHANGELOG.md
10
CHANGELOG.md
@ -1,5 +1,15 @@
|
||||
# Changelog
|
||||
|
||||
## [0.4.0] - April 17th, 2021
|
||||
|
||||
### Added
|
||||
|
||||
- Basic Query and Path Parameter Support 🍻
|
||||
|
||||
### Changed
|
||||
|
||||
- No content workaround, flow will likely need refactoring for clarity.
|
||||
|
||||
## [0.3.0] - April 17th, 2021
|
||||
|
||||
### Changed
|
||||
|
18
README.md
18
README.md
@ -40,7 +40,6 @@ dependencies {
|
||||
### Warning 🚨
|
||||
Kompendium is still under active development ⚠️ There are a number of yet-to-be-implemented features, including
|
||||
|
||||
- Query and Path Parameters 🔍
|
||||
- Tags 🏷
|
||||
- Multiple Responses 📜
|
||||
- Security Schemas 🔏
|
||||
@ -70,11 +69,18 @@ meaning that swapping in a default Ktor route and a Kompendium `notarized` route
|
||||
In general, Kompendium tries to limit the number of annotations that developers need to use in order to get an app
|
||||
integrated.
|
||||
|
||||
Currently, there is only a single Kompendium annotation
|
||||
Currently, the annotations used by Kompendium are as follows
|
||||
|
||||
- `KompendiumField`
|
||||
- `PathParam`
|
||||
- `QueryParam`
|
||||
- `HeaderParam`
|
||||
- `CookieParam`
|
||||
|
||||
The intended purpose is to offer field level overrides such as naming conventions (ie snake instead of camel).
|
||||
The intended purpose of `KompendiumField` is to offer field level overrides such as naming conventions (ie snake instead of camel).
|
||||
|
||||
The 4 "param" annotations are to offer supplemental information in data classes that describe the set of parameters types
|
||||
that a notarized route needs to analyze.
|
||||
|
||||
## Examples
|
||||
|
||||
@ -108,16 +114,16 @@ fun Application.mainModule() {
|
||||
}
|
||||
}
|
||||
route("/single") {
|
||||
notarizedGet<ExampleRequest, ExampleResponse>(testSingleGetInfo) {
|
||||
notarizedGet<ExampleParams, ExampleResponse>(testSingleGetInfo) {
|
||||
call.respondText("get single")
|
||||
}
|
||||
notarizedPost<ExampleParams, ExampleRequest, ExampleCreatedResponse>(testSinglePostInfo) {
|
||||
notarizedPost<Unit, ExampleRequest, ExampleCreatedResponse>(testSinglePostInfo) {
|
||||
call.respondText("test post")
|
||||
}
|
||||
notarizedPut<ExampleParams, ExampleRequest, ExampleCreatedResponse>(testSinglePutInfo) {
|
||||
call.respondText { "hey" }
|
||||
}
|
||||
notarizedDelete<Unit, DeleteResponse>(testSingleDeleteInfo) {
|
||||
notarizedDelete<Unit, Unit>(testSingleDeleteInfo) {
|
||||
call.respondText { "heya" }
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ complexity:
|
||||
includePrivateDeclarations: false
|
||||
ComplexMethod:
|
||||
active: true
|
||||
threshold: 15
|
||||
threshold: 25
|
||||
ignoreSingleWhenExpression: false
|
||||
ignoreSimpleWhenEntries: false
|
||||
ignoreNestingFunctions: false
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Kompendium
|
||||
project.version=0.3.0
|
||||
project.version=0.4.0
|
||||
# Kotlin
|
||||
kotlin.code.style=official
|
||||
# Gradle
|
||||
|
@ -5,25 +5,39 @@ import io.ktor.http.HttpMethod
|
||||
import io.ktor.routing.Route
|
||||
import io.ktor.routing.method
|
||||
import io.ktor.util.pipeline.PipelineInterceptor
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.javaField
|
||||
import kotlin.reflect.typeOf
|
||||
import org.leafygreens.kompendium.Kontent.generateKontent
|
||||
import org.leafygreens.kompendium.Kontent.generateParameterKontent
|
||||
import org.leafygreens.kompendium.annotations.CookieParam
|
||||
import org.leafygreens.kompendium.annotations.HeaderParam
|
||||
import org.leafygreens.kompendium.annotations.PathParam
|
||||
import org.leafygreens.kompendium.annotations.QueryParam
|
||||
import org.leafygreens.kompendium.models.meta.MethodInfo
|
||||
import org.leafygreens.kompendium.models.meta.RequestInfo
|
||||
import org.leafygreens.kompendium.models.meta.ResponseInfo
|
||||
import org.leafygreens.kompendium.models.meta.SchemaMap
|
||||
import org.leafygreens.kompendium.models.oas.OpenApiSpec
|
||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecInfo
|
||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecMediaType
|
||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecParameter
|
||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecPathItem
|
||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecPathItemOperation
|
||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecReferenceObject
|
||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecRequest
|
||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecResponse
|
||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecSchemaRef
|
||||
import org.leafygreens.kompendium.util.Helpers.calculatePath
|
||||
import org.leafygreens.kompendium.util.Helpers.getReferenceSlug
|
||||
|
||||
object Kompendium {
|
||||
|
||||
var cache: SchemaMap = emptyMap()
|
||||
|
||||
var openApiSpec = OpenApiSpec(
|
||||
info = OpenApiSpecInfo(),
|
||||
servers = mutableListOf(),
|
||||
@ -34,46 +48,47 @@ object Kompendium {
|
||||
inline fun <reified TParam : Any, reified TResp : Any> Route.notarizedGet(
|
||||
info: MethodInfo,
|
||||
noinline body: PipelineInterceptor<Unit, ApplicationCall>
|
||||
): Route = notarizationPreFlight<Unit, TResp>() { requestType, responseType ->
|
||||
): Route = notarizationPreFlight<TParam, Unit, TResp>() { paramType, requestType, responseType ->
|
||||
val path = calculatePath()
|
||||
openApiSpec.paths.getOrPut(path) { OpenApiSpecPathItem() }
|
||||
openApiSpec.paths[path]?.get = info.parseMethodInfo(HttpMethod.Get, requestType, responseType)
|
||||
openApiSpec.paths[path]?.get = info.parseMethodInfo(HttpMethod.Get, paramType, requestType, responseType)
|
||||
return method(HttpMethod.Get) { handle(body) }
|
||||
}
|
||||
|
||||
inline fun <reified TParam : Any, reified TReq : Any, reified TResp : Any> Route.notarizedPost(
|
||||
info: MethodInfo,
|
||||
noinline body: PipelineInterceptor<Unit, ApplicationCall>
|
||||
): Route = notarizationPreFlight<TReq, TResp>() { requestType, responseType ->
|
||||
): Route = notarizationPreFlight<TParam, TReq, TResp>() { paramType, requestType, responseType ->
|
||||
val path = calculatePath()
|
||||
openApiSpec.paths.getOrPut(path) { OpenApiSpecPathItem() }
|
||||
openApiSpec.paths[path]?.post = info.parseMethodInfo(HttpMethod.Post, requestType, responseType)
|
||||
openApiSpec.paths[path]?.post = info.parseMethodInfo(HttpMethod.Post, paramType, requestType, responseType)
|
||||
return method(HttpMethod.Post) { handle(body) }
|
||||
}
|
||||
|
||||
inline fun <reified TParam : Any, reified TReq : Any, reified TResp : Any> Route.notarizedPut(
|
||||
info: MethodInfo,
|
||||
noinline body: PipelineInterceptor<Unit, ApplicationCall>,
|
||||
): Route = notarizationPreFlight<TReq, TResp>() { requestType, responseType ->
|
||||
): Route = notarizationPreFlight<TParam, TReq, TResp>() { paramType, requestType, responseType ->
|
||||
val path = calculatePath()
|
||||
openApiSpec.paths.getOrPut(path) { OpenApiSpecPathItem() }
|
||||
openApiSpec.paths[path]?.put = info.parseMethodInfo(HttpMethod.Put, requestType, responseType)
|
||||
openApiSpec.paths[path]?.put = info.parseMethodInfo(HttpMethod.Put, paramType, requestType, responseType)
|
||||
return method(HttpMethod.Put) { handle(body) }
|
||||
}
|
||||
|
||||
inline fun <reified TParam : Any, reified TResp : Any> Route.notarizedDelete(
|
||||
info: MethodInfo,
|
||||
noinline body: PipelineInterceptor<Unit, ApplicationCall>
|
||||
): Route = notarizationPreFlight<Unit, TResp> { requestType, responseType ->
|
||||
): Route = notarizationPreFlight<TParam, Unit, TResp> { paramType, requestType, responseType ->
|
||||
val path = calculatePath()
|
||||
openApiSpec.paths.getOrPut(path) { OpenApiSpecPathItem() }
|
||||
openApiSpec.paths[path]?.delete = info.parseMethodInfo(HttpMethod.Delete, requestType, responseType)
|
||||
openApiSpec.paths[path]?.delete = info.parseMethodInfo(HttpMethod.Delete, paramType, requestType, responseType)
|
||||
return method(HttpMethod.Delete) { handle(body) }
|
||||
}
|
||||
|
||||
// TODO here down is a mess, needs refactor once core functionality is in place
|
||||
fun MethodInfo.parseMethodInfo(
|
||||
method: HttpMethod,
|
||||
paramType: KType,
|
||||
requestType: KType,
|
||||
responseType: KType
|
||||
) = OpenApiSpecPathItemOperation(
|
||||
@ -81,25 +96,27 @@ object Kompendium {
|
||||
description = this.description,
|
||||
tags = this.tags,
|
||||
deprecated = this.deprecated,
|
||||
responses = responseType.toSpec(responseInfo)?.let { mapOf(it) },
|
||||
requestBody = if (method != HttpMethod.Get) requestType.toSpec(requestInfo) else null
|
||||
parameters = paramType.toParameterSpec(),
|
||||
responses = responseType.toResponseSpec(responseInfo)?.let { mapOf(it) },
|
||||
requestBody = if (method != HttpMethod.Get) requestType.toRequestSpec(requestInfo) else null
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
inline fun <reified TReq : Any, reified TResp : Any> notarizationPreFlight(
|
||||
block: (KType, KType) -> Route
|
||||
inline fun <reified TParam : Any, reified TReq : Any, reified TResp : Any> notarizationPreFlight(
|
||||
block: (KType, KType, KType) -> Route
|
||||
): Route {
|
||||
val responseKontent = generateKontent<TResp>()
|
||||
val requestKontent = generateKontent<TReq>()
|
||||
openApiSpec.components.schemas.putAll(responseKontent)
|
||||
openApiSpec.components.schemas.putAll(requestKontent)
|
||||
cache = generateKontent<TResp>(cache)
|
||||
cache = generateKontent<TReq>(cache)
|
||||
cache = generateParameterKontent<TParam>(cache)
|
||||
openApiSpec.components.schemas.putAll(cache)
|
||||
val requestType = typeOf<TReq>()
|
||||
val responseType = typeOf<TResp>()
|
||||
return block.invoke(requestType, responseType)
|
||||
val paramType = typeOf<TParam>()
|
||||
return block.invoke(paramType, requestType, responseType)
|
||||
}
|
||||
|
||||
// TODO These two lookin' real similar 👀 Combine?
|
||||
private fun KType.toSpec(requestInfo: RequestInfo?): OpenApiSpecRequest? = when (this) {
|
||||
private fun KType.toRequestSpec(requestInfo: RequestInfo?): OpenApiSpecRequest? = when (this) {
|
||||
Unit::class -> null
|
||||
else -> when (requestInfo) {
|
||||
null -> null
|
||||
@ -113,28 +130,62 @@ object Kompendium {
|
||||
}
|
||||
}
|
||||
|
||||
private fun KType.toSpec(responseInfo: ResponseInfo?): Pair<Int, OpenApiSpecResponse>? = when (this) {
|
||||
private fun KType.toResponseSpec(responseInfo: ResponseInfo?): Pair<Int, OpenApiSpecResponse>? = when (this) {
|
||||
Unit::class -> null // TODO Maybe not though? could be unit but 200 🤔
|
||||
else -> when (responseInfo) {
|
||||
null -> null // TODO again probably revisit this
|
||||
else -> {
|
||||
val specResponse = OpenApiSpecResponse(
|
||||
description = responseInfo.description,
|
||||
content = responseInfo.mediaTypes.associateWith {
|
||||
val content = responseInfo.mediaTypes.associateWith {
|
||||
val ref = getReferenceSlug()
|
||||
OpenApiSpecMediaType.Referenced(OpenApiSpecReferenceObject(ref))
|
||||
}
|
||||
val specResponse = OpenApiSpecResponse(
|
||||
description = responseInfo.description,
|
||||
content = content.ifEmpty { null }
|
||||
)
|
||||
Pair(responseInfo.status, specResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO God these annotations make this hideous... any way to improve?
|
||||
private fun KType.toParameterSpec(): List<OpenApiSpecParameter> {
|
||||
val clazz = classifier as KClass<*>
|
||||
return clazz.memberProperties.map { prop ->
|
||||
val field = prop.javaField?.type?.kotlin
|
||||
?: error("Unable to parse field type from $prop")
|
||||
val anny = prop.findAnnotation<PathParam>()
|
||||
?: prop.findAnnotation<QueryParam>()
|
||||
?: prop.findAnnotation<HeaderParam>()
|
||||
?: prop.findAnnotation<CookieParam>()
|
||||
?: error("Unable to find any relevant parameter specifier annotations on field ${prop.name}")
|
||||
OpenApiSpecParameter(
|
||||
name = prop.name,
|
||||
`in` = when (anny) {
|
||||
is PathParam -> "path"
|
||||
is QueryParam -> "query"
|
||||
is HeaderParam -> "header"
|
||||
is CookieParam -> "cookie"
|
||||
else -> error("should not be reachable")
|
||||
},
|
||||
schema = OpenApiSpecSchemaRef(field.getReferenceSlug(prop)),
|
||||
description = when (anny) {
|
||||
is PathParam -> anny.description.ifBlank { null }
|
||||
is QueryParam -> anny.description.ifBlank { null }
|
||||
is HeaderParam -> anny.description.ifBlank { null }
|
||||
is CookieParam -> anny.description.ifBlank { null }
|
||||
else -> error("should not be reachable")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun resetSchema() {
|
||||
openApiSpec = OpenApiSpec(
|
||||
info = OpenApiSpecInfo(),
|
||||
servers = mutableListOf(),
|
||||
paths = mutableMapOf()
|
||||
)
|
||||
cache = emptyMap()
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,15 @@ object Kontent {
|
||||
return generateKTypeKontent(kontentType, cache)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
inline fun <reified T> generateParameterKontent(
|
||||
cache: SchemaMap = emptyMap()
|
||||
): SchemaMap {
|
||||
val kontentType = typeOf<T>()
|
||||
return generateKTypeKontent(kontentType, cache)
|
||||
.filterNot { (slug, _) -> slug == (kontentType.classifier as KClass<*>).simpleName }
|
||||
}
|
||||
|
||||
fun generateKTypeKontent(
|
||||
type: KType,
|
||||
cache: SchemaMap = emptyMap()
|
||||
|
@ -0,0 +1,5 @@
|
||||
package org.leafygreens.kompendium.annotations
|
||||
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
annotation class CookieParam(val description: String = "")
|
@ -0,0 +1,5 @@
|
||||
package org.leafygreens.kompendium.annotations
|
||||
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
annotation class HeaderParam(val description: String = "")
|
@ -0,0 +1,5 @@
|
||||
package org.leafygreens.kompendium.annotations
|
||||
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
annotation class PathParam(val description: String = "")
|
@ -0,0 +1,5 @@
|
||||
package org.leafygreens.kompendium.annotations
|
||||
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
annotation class QueryParam(val description: String = "")
|
@ -24,13 +24,13 @@ data class OpenApiSpecHeader(
|
||||
data class OpenApiSpecParameter(
|
||||
val name: String,
|
||||
val `in`: String, // TODO Enum? "query", "header", "path" or "cookie"
|
||||
val description: String?,
|
||||
val schema: OpenApiSpecSchema,
|
||||
val description: String? = null,
|
||||
val required: Boolean = true,
|
||||
val deprecated: Boolean = false,
|
||||
val allowEmptyValue: Boolean = false,
|
||||
val allowEmptyValue: Boolean? = null,
|
||||
val style: String? = null,
|
||||
val explode: Boolean? = false,
|
||||
val schema: OpenApiSpecSchema? = null
|
||||
val explode: Boolean? = null
|
||||
) : OpenApiSpecReferencable()
|
||||
|
||||
data class OpenApiSpecRequest(
|
||||
|
@ -311,7 +311,7 @@ internal class KompendiumTest {
|
||||
private companion object {
|
||||
val testGetResponse = ResponseInfo(KompendiumHttpCodes.OK, "A Successful Endeavor")
|
||||
val testPostResponse = ResponseInfo(KompendiumHttpCodes.CREATED, "A Successful Endeavor")
|
||||
val testDeleteResponse = ResponseInfo(KompendiumHttpCodes.NO_CONTENT, "A Successful Endeavor")
|
||||
val testDeleteResponse = ResponseInfo(KompendiumHttpCodes.NO_CONTENT, "A Successful Endeavor", mediaTypes = emptyList())
|
||||
val testRequest = RequestInfo("A Test request")
|
||||
val testGetInfo = MethodInfo("Another get test", "testing more", testGetResponse)
|
||||
val testPostInfo = MethodInfo("Test post endpoint", "Post your tests here!", testPostResponse, testRequest)
|
||||
@ -351,7 +351,7 @@ internal class KompendiumTest {
|
||||
private fun Application.notarizedDeleteModule() {
|
||||
routing {
|
||||
route("/test") {
|
||||
notarizedDelete<TestParams, TestDeleteResponse>(testDeleteInfo) {
|
||||
notarizedDelete<TestParams, Unit>(testDeleteInfo) {
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,11 @@ import java.util.UUID
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertTrue
|
||||
import org.leafygreens.kompendium.Kontent.generateKontent
|
||||
import org.leafygreens.kompendium.Kontent.generateParameterKontent
|
||||
import org.leafygreens.kompendium.models.oas.DictionarySchema
|
||||
import org.leafygreens.kompendium.models.oas.FormatSchema
|
||||
import org.leafygreens.kompendium.models.oas.ObjectSchema
|
||||
@ -173,4 +175,15 @@ internal class KontentTest {
|
||||
assertEquals(ReferencedSchema("#/components/schemas/CrazyItem"), rs)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Parameter kontent filters out top level declaration`() {
|
||||
// do
|
||||
val result = generateParameterKontent<TestSimpleModel>()
|
||||
|
||||
// expect
|
||||
assertNotNull(result)
|
||||
assertEquals(2, result.count())
|
||||
assertFalse { result.containsKey(TestSimpleModel::class.simpleName) }
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package org.leafygreens.kompendium.util
|
||||
|
||||
import java.util.UUID
|
||||
import org.leafygreens.kompendium.annotations.KompendiumField
|
||||
import org.leafygreens.kompendium.annotations.PathParam
|
||||
import org.leafygreens.kompendium.annotations.QueryParam
|
||||
|
||||
data class TestSimpleModel(val a: String, val b: Int)
|
||||
|
||||
@ -17,7 +19,10 @@ data class TestSimpleWithEnumList(val a: Double, val b: List<SimpleEnum>)
|
||||
|
||||
data class TestInvalidMap(val a: Map<Int, TestSimpleModel>)
|
||||
|
||||
data class TestParams(val a: String, val aa: Int)
|
||||
data class TestParams(
|
||||
@PathParam val a: String,
|
||||
@QueryParam val aa: Int
|
||||
)
|
||||
|
||||
data class TestNested(val nesty: String)
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
"tags" : [ ],
|
||||
"summary" : "Test put endpoint",
|
||||
"description" : "Put your tests here!",
|
||||
"parameters" : [ ],
|
||||
"requestBody" : {
|
||||
"description" : "A Test request",
|
||||
"content" : {
|
||||
|
@ -28,16 +28,26 @@
|
||||
"tags" : [ ],
|
||||
"summary" : "Test delete endpoint",
|
||||
"description" : "testing my deletes",
|
||||
"parameters" : [ {
|
||||
"name" : "a",
|
||||
"in" : "path",
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/String"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
}, {
|
||||
"name" : "aa",
|
||||
"in" : "query",
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/Int"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
} ],
|
||||
"responses" : {
|
||||
"204" : {
|
||||
"description" : "A Successful Endeavor",
|
||||
"content" : {
|
||||
"application/json" : {
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/TestDeleteResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
"description" : "A Successful Endeavor"
|
||||
}
|
||||
},
|
||||
"deprecated" : false
|
||||
@ -46,9 +56,12 @@
|
||||
},
|
||||
"components" : {
|
||||
"schemas" : {
|
||||
"TestDeleteResponse" : {
|
||||
"properties" : { },
|
||||
"type" : "object"
|
||||
"String" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"Int" : {
|
||||
"format" : "int32",
|
||||
"type" : "integer"
|
||||
}
|
||||
},
|
||||
"securitySchemes" : { }
|
||||
|
@ -28,6 +28,23 @@
|
||||
"tags" : [ ],
|
||||
"summary" : "Another get test",
|
||||
"description" : "testing more",
|
||||
"parameters" : [ {
|
||||
"name" : "a",
|
||||
"in" : "path",
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/String"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
}, {
|
||||
"name" : "aa",
|
||||
"in" : "query",
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/Int"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
} ],
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"description" : "A Successful Endeavor",
|
||||
@ -56,6 +73,10 @@
|
||||
}
|
||||
},
|
||||
"type" : "object"
|
||||
},
|
||||
"Int" : {
|
||||
"format" : "int32",
|
||||
"type" : "integer"
|
||||
}
|
||||
},
|
||||
"securitySchemes" : { }
|
||||
|
@ -28,6 +28,23 @@
|
||||
"tags" : [ ],
|
||||
"summary" : "Test post endpoint",
|
||||
"description" : "Post your tests here!",
|
||||
"parameters" : [ {
|
||||
"name" : "a",
|
||||
"in" : "path",
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/String"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
}, {
|
||||
"name" : "aa",
|
||||
"in" : "query",
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/Int"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
} ],
|
||||
"requestBody" : {
|
||||
"description" : "A Test request",
|
||||
"content" : {
|
||||
|
@ -28,6 +28,7 @@
|
||||
"tags" : [ ],
|
||||
"summary" : "Test put endpoint",
|
||||
"description" : "Put your tests here!",
|
||||
"parameters" : [ ],
|
||||
"requestBody" : {
|
||||
"description" : "A Test request",
|
||||
"content" : {
|
||||
|
@ -28,6 +28,23 @@
|
||||
"tags" : [ ],
|
||||
"summary" : "Test put endpoint",
|
||||
"description" : "Put your tests here!",
|
||||
"parameters" : [ {
|
||||
"name" : "a",
|
||||
"in" : "path",
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/String"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
}, {
|
||||
"name" : "aa",
|
||||
"in" : "query",
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/Int"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
} ],
|
||||
"requestBody" : {
|
||||
"description" : "A Test request",
|
||||
"content" : {
|
||||
|
@ -28,6 +28,23 @@
|
||||
"tags" : [ ],
|
||||
"summary" : "Another get test",
|
||||
"description" : "testing more",
|
||||
"parameters" : [ {
|
||||
"name" : "a",
|
||||
"in" : "path",
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/String"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
}, {
|
||||
"name" : "aa",
|
||||
"in" : "query",
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/Int"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
} ],
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"description" : "A Successful Endeavor",
|
||||
@ -56,6 +73,10 @@
|
||||
}
|
||||
},
|
||||
"type" : "object"
|
||||
},
|
||||
"Int" : {
|
||||
"format" : "int32",
|
||||
"type" : "integer"
|
||||
}
|
||||
},
|
||||
"securitySchemes" : { }
|
||||
|
@ -103,12 +103,6 @@
|
||||
"parameters" : [ {
|
||||
"name" : "status",
|
||||
"in" : "query",
|
||||
"description" : "Status values that need to be considered for filter",
|
||||
"required" : true,
|
||||
"deprecated" : false,
|
||||
"allowEmptyValue" : false,
|
||||
"style" : "form",
|
||||
"explode" : true,
|
||||
"schema" : {
|
||||
"items" : {
|
||||
"default" : "available",
|
||||
@ -116,7 +110,12 @@
|
||||
"type" : "string"
|
||||
},
|
||||
"type" : "array"
|
||||
}
|
||||
},
|
||||
"description" : "Status values that need to be considered for filter",
|
||||
"required" : true,
|
||||
"deprecated" : false,
|
||||
"style" : "form",
|
||||
"explode" : true
|
||||
} ],
|
||||
"responses" : {
|
||||
"200" : {
|
||||
|
@ -28,6 +28,23 @@
|
||||
"tags" : [ ],
|
||||
"summary" : "Another get test",
|
||||
"description" : "testing more",
|
||||
"parameters" : [ {
|
||||
"name" : "a",
|
||||
"in" : "path",
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/String"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
}, {
|
||||
"name" : "aa",
|
||||
"in" : "query",
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/Int"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
} ],
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"description" : "A Successful Endeavor",
|
||||
@ -62,6 +79,10 @@
|
||||
"$ref" : "#/components/schemas/TestResponse"
|
||||
},
|
||||
"type" : "array"
|
||||
},
|
||||
"Int" : {
|
||||
"format" : "int32",
|
||||
"type" : "integer"
|
||||
}
|
||||
},
|
||||
"securitySchemes" : { }
|
||||
|
@ -28,6 +28,23 @@
|
||||
"tags" : [ ],
|
||||
"summary" : "Another get test",
|
||||
"description" : "testing more",
|
||||
"parameters" : [ {
|
||||
"name" : "a",
|
||||
"in" : "path",
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/String"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
}, {
|
||||
"name" : "aa",
|
||||
"in" : "query",
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/Int"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
} ],
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"description" : "A Successful Endeavor",
|
||||
@ -56,6 +73,10 @@
|
||||
}
|
||||
},
|
||||
"type" : "object"
|
||||
},
|
||||
"Int" : {
|
||||
"format" : "int32",
|
||||
"type" : "integer"
|
||||
}
|
||||
},
|
||||
"securitySchemes" : { }
|
||||
|
@ -28,6 +28,23 @@
|
||||
"tags" : [ ],
|
||||
"summary" : "Another get test",
|
||||
"description" : "testing more",
|
||||
"parameters" : [ {
|
||||
"name" : "a",
|
||||
"in" : "path",
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/String"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
}, {
|
||||
"name" : "aa",
|
||||
"in" : "query",
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/Int"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
} ],
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"description" : "A Successful Endeavor",
|
||||
@ -56,6 +73,10 @@
|
||||
}
|
||||
},
|
||||
"type" : "object"
|
||||
},
|
||||
"Int" : {
|
||||
"format" : "int32",
|
||||
"type" : "integer"
|
||||
}
|
||||
},
|
||||
"securitySchemes" : { }
|
||||
|
@ -31,6 +31,8 @@ import org.leafygreens.kompendium.Kompendium.notarizedPost
|
||||
import org.leafygreens.kompendium.Kompendium.notarizedPut
|
||||
import org.leafygreens.kompendium.Kompendium.openApiSpec
|
||||
import org.leafygreens.kompendium.annotations.KompendiumField
|
||||
import org.leafygreens.kompendium.annotations.PathParam
|
||||
import org.leafygreens.kompendium.annotations.QueryParam
|
||||
import org.leafygreens.kompendium.models.meta.MethodInfo
|
||||
import org.leafygreens.kompendium.models.meta.RequestInfo
|
||||
import org.leafygreens.kompendium.models.meta.ResponseInfo
|
||||
@ -70,16 +72,16 @@ fun Application.mainModule() {
|
||||
}
|
||||
}
|
||||
route("/single") {
|
||||
notarizedGet<ExampleRequest, ExampleResponse>(testSingleGetInfo) {
|
||||
notarizedGet<Unit, ExampleResponse>(testSingleGetInfo) {
|
||||
call.respondText("get single")
|
||||
}
|
||||
notarizedPost<ExampleParams, ExampleRequest, ExampleCreatedResponse>(testSinglePostInfo) {
|
||||
notarizedPost<Unit, ExampleRequest, ExampleCreatedResponse>(testSinglePostInfo) {
|
||||
call.respondText("test post")
|
||||
}
|
||||
notarizedPut<ExampleParams, ExampleRequest, ExampleCreatedResponse>(testSinglePutInfo) {
|
||||
notarizedPut<JustQuery, ExampleRequest, ExampleCreatedResponse>(testSinglePutInfo) {
|
||||
call.respondText { "hey" }
|
||||
}
|
||||
notarizedDelete<Unit, DeleteResponse>(testSingleDeleteInfo) {
|
||||
notarizedDelete<Unit, Unit>(testSingleDeleteInfo) {
|
||||
call.respondText { "heya" }
|
||||
}
|
||||
}
|
||||
@ -87,12 +89,18 @@ fun Application.mainModule() {
|
||||
}
|
||||
}
|
||||
|
||||
data class ExampleParams(val a: String, val aa: Int)
|
||||
data class ExampleParams(
|
||||
@PathParam val id: Int,
|
||||
@QueryParam val name: String
|
||||
)
|
||||
|
||||
data class JustQuery(
|
||||
@QueryParam val potato: Boolean,
|
||||
@QueryParam val tomato: String
|
||||
)
|
||||
|
||||
data class ExampleNested(val nesty: String)
|
||||
|
||||
object DeleteResponse
|
||||
|
||||
data class ExampleRequest(
|
||||
@KompendiumField(name = "field_name")
|
||||
val fieldName: ExampleNested,
|
||||
@ -150,7 +158,8 @@ object KompendiumTOC {
|
||||
description = "testing my deletes",
|
||||
responseInfo = ResponseInfo(
|
||||
status = KompendiumHttpCodes.NO_CONTENT,
|
||||
description = "Signifies that your item was deleted succesfully"
|
||||
description = "Signifies that your item was deleted successfully",
|
||||
mediaTypes = emptyList()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user