feat: v3 locations (#292)

This commit is contained in:
Ryan Brink
2022-08-13 12:40:20 -07:00
committed by GitHub
parent 2007b1bb8c
commit 62080f3248
30 changed files with 616 additions and 1404 deletions

View File

@ -1,84 +0,0 @@
package io.bkbn.kompendium.locations
//import io.bkbn.kompendium.annotations.Param
//import io.bkbn.kompendium.core.Kompendium
//import io.bkbn.kompendium.core.metadata.method.MethodInfo
//import io.bkbn.kompendium.core.parser.IMethodParser
//import io.bkbn.kompendium.oas.path.Path
//import io.bkbn.kompendium.oas.path.PathOperation
//import io.bkbn.kompendium.oas.payload.Parameter
//import io.ktor.application.feature
//import io.ktor.locations.KtorExperimentalLocationsAPI
//import io.ktor.locations.Location
//import io.ktor.routing.Route
//import io.ktor.routing.application
//import kotlin.reflect.KAnnotatedElement
//import kotlin.reflect.KClass
//import kotlin.reflect.KClassifier
//import kotlin.reflect.KType
//import kotlin.reflect.full.createType
//import kotlin.reflect.full.findAnnotation
//import kotlin.reflect.full.hasAnnotation
//import kotlin.reflect.full.memberProperties
//
//@OptIn(KtorExperimentalLocationsAPI::class)
//object LocationMethodParser : IMethodParser {
// override fun KType.toParameterSpec(info: MethodInfo<*, *>, feature: Kompendium): List<Parameter> {
// val clazzList = determineLocationParents(classifier!!)
// return clazzList.associateWith { it.memberProperties }
// .flatMap { (clazz, memberProperties) -> memberProperties.associateWith { clazz }.toList() }
// .filter { (prop, _) -> prop.hasAnnotation<Param>() }
// .map { (prop, clazz) -> prop.toParameter(info, clazz.createType(), clazz, feature) }
// }
//
// private fun determineLocationParents(classifier: KClassifier): List<KClass<*>> {
// var clazz: KClass<*>? = classifier as KClass<*>
// val clazzList = mutableListOf<KClass<*>>()
// while (clazz != null) {
// clazzList.add(clazz)
// clazz = getLocationParent(clazz)
// }
// return clazzList
// }
//
// private fun getLocationParent(clazz: KClass<*>): KClass<*>? {
// val parent = clazz.memberProperties
// .find { (it.returnType.classifier as KAnnotatedElement).hasAnnotation<Location>() }
// return parent?.returnType?.classifier as? KClass<*>
// }
//
// fun KClass<*>.calculateLocationPath(suffix: String = ""): String {
// val locationAnnotation = this.findAnnotation<Location>()
// require(locationAnnotation != null) { "Location annotation must be present to leverage notarized location api" }
// val parent = this.java.declaringClass?.kotlin?.takeIf { it.hasAnnotation<Location>() }
// val newSuffix = locationAnnotation.path.plus(suffix)
// return when (parent) {
// null -> newSuffix
// else -> parent.calculateLocationPath(newSuffix)
// }
// }
//
// inline fun <reified TParam : Any> processBaseInfo(
// paramType: KType,
// requestType: KType,
// responseType: KType,
// info: MethodInfo<*, *>,
// route: Route
// ): LocationBaseInfo {
// val locationAnnotation = TParam::class.findAnnotation<Location>()
// require(locationAnnotation != null) { "Location annotation must be present to leverage notarized location api" }
// val path = route.calculateRoutePath()
// val locationPath = TParam::class.calculateLocationPath()
// val pathWithLocation = path.plus(locationPath)
// val feature = route.application.feature(Kompendium)
// feature.config.spec.paths.getOrPut(pathWithLocation) { Path() }
// val baseInfo = parseMethodInfo(info, paramType, requestType, responseType, feature)
// return LocationBaseInfo(baseInfo, feature, pathWithLocation)
// }
//
// data class LocationBaseInfo(
// val op: PathOperation,
// val feature: Kompendium,
// val path: String
// )
//}

View File

@ -1,110 +0,0 @@
package io.bkbn.kompendium.locations
//import io.bkbn.kompendium.core.KompendiumPreFlight.methodNotarizationPreFlight
//import io.bkbn.kompendium.core.metadata.method.DeleteInfo
//import io.bkbn.kompendium.core.metadata.method.GetInfo
//import io.bkbn.kompendium.core.metadata.method.PostInfo
//import io.bkbn.kompendium.core.metadata.method.PutInfo
//import io.bkbn.kompendium.oas.path.PathOperation
//import io.ktor.application.ApplicationCall
//import io.ktor.http.HttpMethod
//import io.ktor.locations.KtorExperimentalLocationsAPI
//import io.ktor.locations.handle
//import io.ktor.locations.location
//import io.ktor.routing.Route
//import io.ktor.routing.method
//import io.ktor.util.pipeline.PipelineContext
//
///**
// * This version of notarized routes leverages the Ktor [io.ktor.locations.Locations] plugin to provide type safe access
// * to all path and query parameters.
// */
//@KtorExperimentalLocationsAPI
//object NotarizedLocation {
//
// /**
// * Notarization for an HTTP GET request leveraging the Ktor [io.ktor.locations.Locations] plugin
// * @param TParam The class containing all parameter fields.
// * Each field must be annotated with @[io.bkbn.kompendium.annotations.Param].
// * Additionally, the class must be annotated with @[io.ktor.locations.Location].
// * @param TResp Class detailing the expected API response
// * @param info Route metadata
// * @param postProcess Adds an optional callback hook to perform manual overrides on the generated [PathOperation]
// */
// inline fun <reified TParam : Any, reified TResp : Any> Route.notarizedGet(
// info: GetInfo<TParam, TResp>,
// postProcess: (PathOperation) -> PathOperation = { p -> p },
// noinline body: suspend PipelineContext<Unit, ApplicationCall>.(TParam) -> Unit
// ): Route = methodNotarizationPreFlight<TParam, Unit, TResp>() { paramType, requestType, responseType ->
// val lbi = LocationMethodParser.processBaseInfo<TParam>(paramType, requestType, responseType, info, this)
// lbi.feature.config.spec.paths[lbi.path]?.get = postProcess(lbi.op)
// return location(TParam::class) {
// method(HttpMethod.Get) { handle(body) }
// }
// }
//
// /**
// * Notarization for an HTTP POST request leveraging the Ktor [io.ktor.locations.Locations] plugin
// * @param TParam The class containing all parameter fields.
// * Each field must be annotated with @[io.bkbn.kompendium.annotations.Param]
// * Additionally, the class must be annotated with @[io.ktor.locations.Location].
// * @param TReq Class detailing the expected API request body
// * @param TResp Class detailing the expected API response
// * @param info Route metadata
// * @param postProcess Adds an optional callback hook to perform manual overrides on the generated [PathOperation]
// */
// inline fun <reified TParam : Any, reified TReq : Any, reified TResp : Any> Route.notarizedPost(
// info: PostInfo<TParam, TReq, TResp>,
// postProcess: (PathOperation) -> PathOperation = { p -> p },
// noinline body: suspend PipelineContext<Unit, ApplicationCall>.(TParam) -> Unit
// ): Route = methodNotarizationPreFlight<TParam, TReq, TResp>() { paramType, requestType, responseType ->
// val lbi = LocationMethodParser.processBaseInfo<TParam>(paramType, requestType, responseType, info, this)
// lbi.feature.config.spec.paths[lbi.path]?.post = postProcess(lbi.op)
// return location(TParam::class) {
// method(HttpMethod.Post) { handle(body) }
// }
// }
//
// /**
// * Notarization for an HTTP Delete request leveraging the Ktor [io.ktor.locations.Locations] plugin
// * @param TParam The class containing all parameter fields.
// * Each field must be annotated with @[io.bkbn.kompendium.annotations.Param]
// * Additionally, the class must be annotated with @[io.ktor.locations.Location].
// * @param TReq Class detailing the expected API request body
// * @param TResp Class detailing the expected API response
// * @param info Route metadata
// * @param postProcess Adds an optional callback hook to perform manual overrides on the generated [PathOperation]
// */
// inline fun <reified TParam : Any, reified TReq : Any, reified TResp : Any> Route.notarizedPut(
// info: PutInfo<TParam, TReq, TResp>,
// postProcess: (PathOperation) -> PathOperation = { p -> p },
// noinline body: suspend PipelineContext<Unit, ApplicationCall>.(TParam) -> Unit
// ): Route = methodNotarizationPreFlight<TParam, TReq, TResp>() { paramType, requestType, responseType ->
// val lbi = LocationMethodParser.processBaseInfo<TParam>(paramType, requestType, responseType, info, this)
// lbi.feature.config.spec.paths[lbi.path]?.put = postProcess(lbi.op)
// return location(TParam::class) {
// method(HttpMethod.Put) { handle(body) }
// }
// }
//
// /**
// * Notarization for an HTTP POST request leveraging the Ktor [io.ktor.locations.Locations] plugin
// * @param TParam The class containing all parameter fields.
// * Each field must be annotated with @[io.bkbn.kompendium.annotations.Param]
// * Additionally, the class must be annotated with @[io.ktor.locations.Location].
// * @param TResp Class detailing the expected API response
// * @param info Route metadata
// * @param postProcess Adds an optional callback hook to perform manual overrides on the generated [PathOperation]
// */
// inline fun <reified TParam : Any, reified TResp : Any> Route.notarizedDelete(
// info: DeleteInfo<TParam, TResp>,
// postProcess: (PathOperation) -> PathOperation = { p -> p },
// noinline body: suspend PipelineContext<Unit, ApplicationCall>.(TParam) -> Unit
// ): Route = methodNotarizationPreFlight<TParam, Unit, TResp> { paramType, requestType, responseType ->
// val lbi = LocationMethodParser.processBaseInfo<TParam>(paramType, requestType, responseType, info, this)
// lbi.feature.config.spec.paths[lbi.path]?.delete = postProcess(lbi.op)
// return location(TParam::class) {
// method(HttpMethod.Delete) { handle(body) }
// }
// }
//}

View File

@ -0,0 +1,79 @@
package io.bkbn.kompendium.locations
import io.bkbn.kompendium.core.attribute.KompendiumAttributes
import io.bkbn.kompendium.core.metadata.DeleteInfo
import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.metadata.HeadInfo
import io.bkbn.kompendium.core.metadata.OptionsInfo
import io.bkbn.kompendium.core.metadata.PatchInfo
import io.bkbn.kompendium.core.metadata.PostInfo
import io.bkbn.kompendium.core.metadata.PutInfo
import io.bkbn.kompendium.core.util.Helpers.addToSpec
import io.bkbn.kompendium.core.util.SpecConfig
import io.bkbn.kompendium.oas.path.Path
import io.bkbn.kompendium.oas.payload.Parameter
import io.ktor.server.application.createApplicationPlugin
import io.ktor.server.locations.KtorExperimentalLocationsAPI
import io.ktor.server.locations.Location
import kotlin.reflect.KClass
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.hasAnnotation
import kotlin.reflect.full.memberProperties
object NotarizedLocations {
data class LocationMetadata(
override var tags: Set<String> = emptySet(),
override var parameters: List<Parameter> = emptyList(),
override var get: GetInfo? = null,
override var post: PostInfo? = null,
override var put: PutInfo? = null,
override var delete: DeleteInfo? = null,
override var patch: PatchInfo? = null,
override var head: HeadInfo? = null,
override var options: OptionsInfo? = null,
override var security: Map<String, List<String>>? = null,
) : SpecConfig
class Config {
lateinit var locations: Map<KClass<*>, LocationMetadata>
}
operator fun invoke() = createApplicationPlugin(
name = "NotarizedLocations",
createConfiguration = ::Config
) {
val spec = application.attributes[KompendiumAttributes.openApiSpec]
pluginConfig.locations.forEach { (k, v) ->
val path = Path()
path.parameters = v.parameters
v.get?.addToSpec(path, spec, v)
v.delete?.addToSpec(path, spec, v)
v.head?.addToSpec(path, spec, v)
v.options?.addToSpec(path, spec, v)
v.post?.addToSpec(path, spec, v)
v.put?.addToSpec(path, spec, v)
v.patch?.addToSpec(path, spec, v)
val location = k.getLocationFromClass()
spec.paths[location] = path
}
}
@OptIn(KtorExperimentalLocationsAPI::class)
private fun KClass<*>.getLocationFromClass(): String {
// todo if parent
val location = findAnnotation<Location>()
?: error("Cannot notarize a location without annotating with @Location")
val path = location.path
val parent = memberProperties.map { it.returnType.classifier as KClass<*> }.find { it.hasAnnotation<Location>() }
return if (parent == null) {
path
} else {
parent.getLocationFromClass() + path
}
}
}

View File

@ -1,82 +1,119 @@
package io.bkbn.kompendium.locations
//import io.bkbn.kompendium.core.fixtures.TestHelpers.openApiTestAllSerializers
//import io.bkbn.kompendium.locations.util.locationsConfig
//import io.bkbn.kompendium.locations.util.notarizedDeleteNestedLocation
//import io.bkbn.kompendium.locations.util.notarizedDeleteSimpleLocation
//import io.bkbn.kompendium.locations.util.notarizedGetNestedLocation
//import io.bkbn.kompendium.locations.util.notarizedGetNestedLocationFromNonLocationClass
//import io.bkbn.kompendium.locations.util.notarizedGetSimpleLocation
//import io.bkbn.kompendium.locations.util.notarizedPostNestedLocation
//import io.bkbn.kompendium.locations.util.notarizedPostSimpleLocation
//import io.bkbn.kompendium.locations.util.notarizedPutNestedLocation
//import io.bkbn.kompendium.locations.util.notarizedPutSimpleLocation
//import io.kotest.core.spec.style.DescribeSpec
//
//class KompendiumLocationsTest : DescribeSpec({
// describe("Locations") {
// it("Can notarize a get request with a simple location") {
// // act
// openApiTestAllSerializers("notarized_get_simple_location.json") {
// locationsConfig()
// notarizedGetSimpleLocation()
// }
// }
// it("Can notarize a get request with a nested location") {
// // act
// openApiTestAllSerializers("notarized_get_nested_location.json") {
// locationsConfig()
// notarizedGetNestedLocation()
// }
// }
// it("Can notarize a post with a simple location") {
// // act
// openApiTestAllSerializers("notarized_post_simple_location.json") {
// locationsConfig()
// notarizedPostSimpleLocation()
// }
// }
// it("Can notarize a post with a nested location") {
// // act
// openApiTestAllSerializers("notarized_post_nested_location.json") {
// locationsConfig()
// notarizedPostNestedLocation()
// }
// }
// it("Can notarize a put with a simple location") {
// // act
// openApiTestAllSerializers("notarized_put_simple_location.json") {
// locationsConfig()
// notarizedPutSimpleLocation()
// }
// }
// it("Can notarize a put with a nested location") {
// // act
// openApiTestAllSerializers("notarized_put_nested_location.json") {
// locationsConfig()
// notarizedPutNestedLocation()
// }
// }
// it("Can notarize a delete with a simple location") {
// // act
// openApiTestAllSerializers("notarized_delete_simple_location.json") {
// locationsConfig()
// notarizedDeleteSimpleLocation()
// }
// }
// it("Can notarize a delete with a nested location") {
// // act
// openApiTestAllSerializers("notarized_delete_nested_location.json") {
// locationsConfig()
// notarizedDeleteNestedLocation()
// }
// }
// it("Can notarize a get with a nested location nested in a non-location class") {
// // act
// openApiTestAllSerializers("notarized_get_nested_location_from_non_location_class.json") {
// locationsConfig()
// notarizedGetNestedLocationFromNonLocationClass()
// }
// }
// }
//})
import Listing
import io.bkbn.kompendium.core.fixtures.TestHelpers.openApiTestAllSerializers
import io.bkbn.kompendium.core.fixtures.TestResponse
import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.payload.Parameter
import io.kotest.core.spec.style.DescribeSpec
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.call
import io.ktor.server.application.install
import io.ktor.server.locations.Locations
import io.ktor.server.locations.get
import io.ktor.server.response.respondText
class KompendiumLocationsTest : DescribeSpec({
describe("Location Tests") {
it("Can notarize a simple location") {
openApiTestAllSerializers(
snapshotName = "T0001__simple_location.json",
applicationSetup = {
install(Locations)
install(NotarizedLocations()) {
locations = mapOf(
Listing::class to NotarizedLocations.LocationMetadata(
parameters = listOf(
Parameter(
name = "name",
`in` = Parameter.Location.path,
schema = TypeDefinition.STRING
),
Parameter(
name = "page",
`in` = Parameter.Location.path,
schema = TypeDefinition.INT
)
),
get = GetInfo.builder {
summary("Location")
description("example location")
response {
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
description("does great things")
}
}
),
)
}
}
) {
get<Listing> { listing ->
call.respondText("Listing ${listing.name}, page ${listing.page}")
}
}
}
it("Can notarize nested locations") {
openApiTestAllSerializers(
snapshotName = "T0002__nested_locations.json",
applicationSetup = {
install(Locations)
install(NotarizedLocations()) {
locations = mapOf(
Type.Edit::class to NotarizedLocations.LocationMetadata(
parameters = listOf(
Parameter(
name = "name",
`in` = Parameter.Location.path,
schema = TypeDefinition.STRING
)
),
get = GetInfo.builder {
summary("Edit")
description("example location")
response {
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
description("does great things")
}
}
),
Type.Other::class to NotarizedLocations.LocationMetadata(
parameters = listOf(
Parameter(
name = "name",
`in` = Parameter.Location.path,
schema = TypeDefinition.STRING
),
Parameter(
name = "page",
`in` = Parameter.Location.path,
schema = TypeDefinition.INT
)
),
get = GetInfo.builder {
summary("Other")
description("example location")
response {
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
description("does great things")
}
}
),
)
}
}
) {
get<Type.Edit> { edit ->
call.respondText("Listing ${edit.parent.name}")
}
get<Type.Other> { other ->
call.respondText("Listing ${other.parent.name}, page ${other.page}")
}
}
}
}
})

View File

@ -1,22 +1,12 @@
package io.bkbn.kompendium.locations.util
import io.ktor.server.locations.Location
//import io.bkbn.kompendium.annotations.Param
//import io.bkbn.kompendium.annotations.ParamType
//import io.ktor.locations.Location
//
//@Location("/test/{name}")
//data class SimpleLoc(@Param(ParamType.PATH) val name: String) {
// @Location("/nesty")
// data class NestedLoc(@Param(ParamType.QUERY) val isCool: Boolean, val parent: SimpleLoc)
//}
//
//object NonLocationObject {
// @Location("/test/{name}")
// data class SimpleLoc(@Param(ParamType.PATH) val name: String) {
// @Location("/nesty")
// data class NestedLoc(@Param(ParamType.QUERY) val isCool: Boolean, val parent: SimpleLoc)
// }
//}
//
//data class SimpleResponse(val result: Boolean)
//data class SimpleRequest(val input: String)
@Location("/list/{name}/page/{page}")
data class Listing(val name: String, val page: Int)
@Location("/type/{name}")
data class Type(val name: String) {
@Location("/edit")
data class Edit(val parent: Type)
@Location("/other/{page}")
data class Other(val parent: Type, val page: Int)
}

View File

@ -1,107 +0,0 @@
package io.bkbn.kompendium.locations.util
//import io.bkbn.kompendium.locations.NotarizedLocation.notarizedDelete
//import io.bkbn.kompendium.locations.NotarizedLocation.notarizedGet
//import io.bkbn.kompendium.locations.NotarizedLocation.notarizedPost
//import io.bkbn.kompendium.locations.NotarizedLocation.notarizedPut
//import io.ktor.application.Application
//import io.ktor.application.call
//import io.ktor.application.install
//import io.ktor.locations.Locations
//import io.ktor.response.respondText
//import io.ktor.routing.route
//import io.ktor.routing.routing
//
//fun Application.locationsConfig() {
// install(Locations)
//}
//
//fun Application.notarizedGetSimpleLocation() {
// routing {
// route("/test") {
// notarizedGet(TestResponseInfo.testGetSimpleLocation) {
// call.respondText { "hey dude ‼️ congratz on the get request" }
// }
// }
// }
//}
//
//fun Application.notarizedGetNestedLocation() {
// routing {
// route("/test") {
// notarizedGet(TestResponseInfo.testGetNestedLocation) {
// call.respondText { "hey dude ‼️ congratz on the get request" }
// }
// }
// }
//}
//
//fun Application.notarizedPostSimpleLocation() {
// routing {
// route("/test") {
// notarizedPost(TestResponseInfo.testPostSimpleLocation) {
// call.respondText { "hey dude ‼️ congratz on the get request" }
// }
// }
// }
//}
//
//fun Application.notarizedPostNestedLocation() {
// routing {
// route("/test") {
// notarizedPost(TestResponseInfo.testPostNestedLocation) {
// call.respondText { "hey dude ‼️ congratz on the get request" }
// }
// }
// }
//}
//
//fun Application.notarizedPutSimpleLocation() {
// routing {
// route("/test") {
// notarizedPut(TestResponseInfo.testPutSimpleLocation) {
// call.respondText { "hey dude ‼️ congratz on the get request" }
// }
// }
// }
//}
//
//fun Application.notarizedPutNestedLocation() {
// routing {
// route("/test") {
// notarizedPut(TestResponseInfo.testPutNestedLocation) {
// call.respondText { "hey dude ‼️ congratz on the get request" }
// }
// }
// }
//}
//
//fun Application.notarizedDeleteSimpleLocation() {
// routing {
// route("/test") {
// notarizedDelete(TestResponseInfo.testDeleteSimpleLocation) {
// call.respondText { "hey dude ‼️ congratz on the get request" }
// }
// }
// }
//}
//
//fun Application.notarizedDeleteNestedLocation() {
// routing {
// route("/test") {
// notarizedDelete(TestResponseInfo.testDeleteNestedLocation) {
// call.respondText { "hey dude ‼️ congratz on the get request" }
// }
// }
// }
//}
//
//fun Application.notarizedGetNestedLocationFromNonLocationClass() {
// routing {
// route("/test") {
// notarizedGet(TestResponseInfo.testGetNestedLocationFromNonLocationClass) {
// call.respondText { "hey dude ‼️ congratz on the get request" }
// }
// }
// }
//}

View File

@ -1,97 +0,0 @@
package io.bkbn.kompendium.locations.util
//import io.bkbn.kompendium.core.legacy.metadata.RequestInfo
//import io.bkbn.kompendium.core.legacy.metadata.ResponseInfo
//import io.bkbn.kompendium.core.legacy.metadata.method.DeleteInfo
//import io.bkbn.kompendium.core.legacy.metadata.method.GetInfo
//import io.bkbn.kompendium.core.legacy.metadata.method.PostInfo
//import io.bkbn.kompendium.core.legacy.metadata.method.PutInfo
//import io.ktor.http.HttpStatusCode
//
//object TestResponseInfo {
// val testGetSimpleLocation = GetInfo<SimpleLoc, SimpleResponse>(
// summary = "Location Test",
// description = "A cool test",
// responseInfo = ResponseInfo(
// status = HttpStatusCode.OK,
// description = "A successful endeavor"
// )
// )
// val testPostSimpleLocation = PostInfo<SimpleLoc, SimpleRequest, SimpleResponse>(
// summary = "Location Test",
// description = "A cool test",
// requestInfo = RequestInfo(
// description = "Cool stuff"
// ),
// responseInfo = ResponseInfo(
// status = HttpStatusCode.OK,
// description = "A successful endeavor"
// )
// )
// val testPutSimpleLocation = PutInfo<SimpleLoc, SimpleRequest, SimpleResponse>(
// summary = "Location Test",
// description = "A cool test",
// requestInfo = RequestInfo(
// description = "Cool stuff"
// ),
// responseInfo = ResponseInfo(
// status = HttpStatusCode.OK,
// description = "A successful endeavor"
// )
// )
// val testDeleteSimpleLocation = DeleteInfo<SimpleLoc, SimpleResponse>(
// summary = "Location Test",
// description = "A cool test",
// responseInfo = ResponseInfo(
// status = HttpStatusCode.OK,
// description = "A successful endeavor"
// )
// )
// val testGetNestedLocation = GetInfo<SimpleLoc.NestedLoc, SimpleResponse>(
// summary = "Location Test",
// description = "A cool test",
// responseInfo = ResponseInfo(
// status = HttpStatusCode.OK,
// description = "A successful endeavor"
// )
// )
// val testPostNestedLocation = PostInfo<SimpleLoc.NestedLoc, SimpleRequest, SimpleResponse>(
// summary = "Location Test",
// description = "A cool test",
// requestInfo = RequestInfo(
// description = "Cool stuff"
// ),
// responseInfo = ResponseInfo(
// status = HttpStatusCode.OK,
// description = "A successful endeavor"
// )
// )
// val testPutNestedLocation = PutInfo<SimpleLoc.NestedLoc, SimpleRequest, SimpleResponse>(
// summary = "Location Test",
// description = "A cool test",
// requestInfo = RequestInfo(
// description = "Cool stuff"
// ),
// responseInfo = ResponseInfo(
// status = HttpStatusCode.OK,
// description = "A successful endeavor"
// )
// )
// val testDeleteNestedLocation = DeleteInfo<SimpleLoc.NestedLoc, SimpleResponse>(
// summary = "Location Test",
// description = "A cool test",
// responseInfo = ResponseInfo(
// status = HttpStatusCode.OK,
// description = "A successful endeavor"
// )
// )
//
// val testGetNestedLocationFromNonLocationClass = GetInfo<NonLocationObject.SimpleLoc.NestedLoc, SimpleResponse>(
// summary = "Location Test",
// description = "A cool test",
// responseInfo = ResponseInfo(
// status = HttpStatusCode.OK,
// description = "A successful endeavor"
// )
// )
//}

View File

@ -1,5 +1,6 @@
{
"openapi": "3.0.3",
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
@ -26,59 +27,62 @@
}
],
"paths": {
"/test/test/{name}/nesty": {
"/list/{name}/page/{page}": {
"get": {
"tags": [],
"summary": "Location Test",
"description": "A cool test",
"parameters": [
{
"name": "isCool",
"in": "query",
"schema": {
"type": "boolean"
},
"required": true,
"deprecated": false
},
{
"name": "name",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
}
],
"summary": "Location",
"description": "example location",
"parameters": [],
"responses": {
"200": {
"description": "A successful endeavor",
"description": "does great things",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SimpleResponse"
"$ref": "#/components/schemas/TestResponse"
}
}
}
}
},
"deprecated": false
}
},
"parameters": [
{
"name": "name",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
},
{
"name": "page",
"in": "path",
"schema": {
"type": "number",
"format": "int32"
},
"required": true,
"deprecated": false
}
]
}
},
"webhooks": {},
"components": {
"schemas": {
"SimpleResponse": {
"TestResponse": {
"type": "object",
"properties": {
"result": {
"type": "boolean"
"c": {
"type": "string"
}
},
"required": [
"result"
],
"type": "object"
"c"
]
}
},
"securitySchemes": {}

View File

@ -0,0 +1,124 @@
{
"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": {
"/type/{name}/edit": {
"get": {
"tags": [],
"summary": "Edit",
"description": "example location",
"parameters": [],
"responses": {
"200": {
"description": "does great things",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestResponse"
}
}
}
}
},
"deprecated": false
},
"parameters": [
{
"name": "name",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
}
]
},
"/type/{name}/other/{page}": {
"get": {
"tags": [],
"summary": "Other",
"description": "example location",
"parameters": [],
"responses": {
"200": {
"description": "does great things",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestResponse"
}
}
}
}
},
"deprecated": false
},
"parameters": [
{
"name": "name",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
},
{
"name": "page",
"in": "path",
"schema": {
"type": "number",
"format": "int32"
},
"required": true,
"deprecated": false
}
]
}
},
"webhooks": {},
"components": {
"schemas": {
"TestResponse": {
"type": "object",
"properties": {
"c": {
"type": "string"
}
},
"required": [
"c"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -1,88 +0,0 @@
{
"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/test/{name}/nesty": {
"delete": {
"tags": [],
"summary": "Location Test",
"description": "A cool test",
"parameters": [
{
"name": "isCool",
"in": "query",
"schema": {
"type": "boolean"
},
"required": true,
"deprecated": false
},
{
"name": "name",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
}
],
"responses": {
"200": {
"description": "A successful endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SimpleResponse"
}
}
}
}
},
"deprecated": false
}
}
},
"components": {
"schemas": {
"SimpleResponse": {
"properties": {
"result": {
"type": "boolean"
}
},
"required": [
"result"
],
"type": "object"
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -1,79 +0,0 @@
{
"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/test/{name}": {
"delete": {
"tags": [],
"summary": "Location Test",
"description": "A cool test",
"parameters": [
{
"name": "name",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
}
],
"responses": {
"200": {
"description": "A successful endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SimpleResponse"
}
}
}
}
},
"deprecated": false
}
}
},
"components": {
"schemas": {
"SimpleResponse": {
"properties": {
"result": {
"type": "boolean"
}
},
"required": [
"result"
],
"type": "object"
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -1,88 +0,0 @@
{
"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/test/{name}/nesty": {
"get": {
"tags": [],
"summary": "Location Test",
"description": "A cool test",
"parameters": [
{
"name": "isCool",
"in": "query",
"schema": {
"type": "boolean"
},
"required": true,
"deprecated": false
},
{
"name": "name",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
}
],
"responses": {
"200": {
"description": "A successful endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SimpleResponse"
}
}
}
}
},
"deprecated": false
}
}
},
"components": {
"schemas": {
"SimpleResponse": {
"properties": {
"result": {
"type": "boolean"
}
},
"required": [
"result"
],
"type": "object"
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -1,79 +0,0 @@
{
"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/test/{name}": {
"get": {
"tags": [],
"summary": "Location Test",
"description": "A cool test",
"parameters": [
{
"name": "name",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
}
],
"responses": {
"200": {
"description": "A successful endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SimpleResponse"
}
}
}
}
},
"deprecated": false
}
}
},
"components": {
"schemas": {
"SimpleResponse": {
"properties": {
"result": {
"type": "boolean"
}
},
"required": [
"result"
],
"type": "object"
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -1,110 +0,0 @@
{
"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/test/{name}/nesty": {
"post": {
"tags": [],
"summary": "Location Test",
"description": "A cool test",
"parameters": [
{
"name": "isCool",
"in": "query",
"schema": {
"type": "boolean"
},
"required": true,
"deprecated": false
},
{
"name": "name",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
}
],
"requestBody": {
"description": "Cool stuff",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SimpleRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "A successful endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SimpleResponse"
}
}
}
}
},
"deprecated": false
}
}
},
"components": {
"schemas": {
"SimpleRequest": {
"properties": {
"input": {
"type": "string"
}
},
"required": [
"input"
],
"type": "object"
},
"SimpleResponse": {
"properties": {
"result": {
"type": "boolean"
}
},
"required": [
"result"
],
"type": "object"
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -1,101 +0,0 @@
{
"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/test/{name}": {
"post": {
"tags": [],
"summary": "Location Test",
"description": "A cool test",
"parameters": [
{
"name": "name",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
}
],
"requestBody": {
"description": "Cool stuff",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SimpleRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "A successful endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SimpleResponse"
}
}
}
}
},
"deprecated": false
}
}
},
"components": {
"schemas": {
"SimpleRequest": {
"properties": {
"input": {
"type": "string"
}
},
"required": [
"input"
],
"type": "object"
},
"SimpleResponse": {
"properties": {
"result": {
"type": "boolean"
}
},
"required": [
"result"
],
"type": "object"
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -1,110 +0,0 @@
{
"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/test/{name}/nesty": {
"put": {
"tags": [],
"summary": "Location Test",
"description": "A cool test",
"parameters": [
{
"name": "isCool",
"in": "query",
"schema": {
"type": "boolean"
},
"required": true,
"deprecated": false
},
{
"name": "name",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
}
],
"requestBody": {
"description": "Cool stuff",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SimpleRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "A successful endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SimpleResponse"
}
}
}
}
},
"deprecated": false
}
}
},
"components": {
"schemas": {
"SimpleRequest": {
"properties": {
"input": {
"type": "string"
}
},
"required": [
"input"
],
"type": "object"
},
"SimpleResponse": {
"properties": {
"result": {
"type": "boolean"
}
},
"required": [
"result"
],
"type": "object"
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -1,101 +0,0 @@
{
"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/test/{name}": {
"put": {
"tags": [],
"summary": "Location Test",
"description": "A cool test",
"parameters": [
{
"name": "name",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
}
],
"requestBody": {
"description": "Cool stuff",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SimpleRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "A successful endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SimpleResponse"
}
}
}
}
},
"deprecated": false
}
}
},
"components": {
"schemas": {
"SimpleRequest": {
"properties": {
"input": {
"type": "string"
}
},
"required": [
"input"
],
"type": "object"
},
"SimpleResponse": {
"properties": {
"result": {
"type": "boolean"
}
},
"required": [
"result"
],
"type": "object"
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}