fix: (#194) to support Location classes located in other non-location classes (e.g. inside Object) (#207)
* Safely stop Location path calculation on first non-location parent * added a test * changelog * added result file and renamed test models Co-authored-by: Gennadi Kudrjavtsev <gennadi@agrello.org>
This commit is contained in:

committed by
GitHub

parent
019b2cf4db
commit
f919a6a4b1
@ -1,6 +1,7 @@
|
||||
# Changelog
|
||||
|
||||
## Unreleased
|
||||
- Fixed support Location classes located in other non-location classes
|
||||
|
||||
### Added
|
||||
|
||||
|
@ -50,7 +50,7 @@ object LocationMethodParser : IMethodParser {
|
||||
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
|
||||
val parent = this.java.declaringClass?.kotlin?.takeIf { it.hasAnnotation<Location>() }
|
||||
val newSuffix = locationAnnotation.path.plus(suffix)
|
||||
return when (parent) {
|
||||
null -> newSuffix
|
||||
|
@ -5,6 +5,7 @@ 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
|
||||
@ -70,5 +71,12 @@ class KompendiumLocationsTest : DescribeSpec({
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -10,5 +10,13 @@ data class SimpleLoc(@Param(ParamType.PATH) val name: String) {
|
||||
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)
|
||||
|
@ -95,3 +95,13 @@ fun Application.notarizedDeleteNestedLocation() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Application.notarizedGetNestedLocationFromNonLocationClass() {
|
||||
routing {
|
||||
route("/test") {
|
||||
notarizedGet(TestResponseInfo.testGetNestedLocationFromNonLocationClass) {
|
||||
call.respondText { "hey dude ‼️ congratz on the get request" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package io.bkbn.kompendium.locations.util
|
||||
|
||||
import io.bkbn.kompendium.core.metadata.method.MethodInfo
|
||||
import io.bkbn.kompendium.core.metadata.RequestInfo
|
||||
import io.bkbn.kompendium.core.metadata.ResponseInfo
|
||||
import io.bkbn.kompendium.core.metadata.method.DeleteInfo
|
||||
@ -86,4 +85,13 @@ object TestResponseInfo {
|
||||
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"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -0,0 +1,88 @@
|
||||
{
|
||||
"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": []
|
||||
}
|
@ -69,7 +69,7 @@ private fun Application.mainModule() {
|
||||
}
|
||||
|
||||
private object LocationsToC {
|
||||
val testLocation = GetInfo<TestLocations, LocationModels.ExampleResponse>(
|
||||
val testLocation = GetInfo<TestLocationsParent.TestLocations, LocationModels.ExampleResponse>(
|
||||
summary = "Shallow",
|
||||
description = "Ez Pz Lemon Squeezy",
|
||||
responseInfo = ResponseInfo(
|
||||
@ -77,7 +77,7 @@ private object LocationsToC {
|
||||
description = "Great!"
|
||||
)
|
||||
)
|
||||
val testNestLocation = GetInfo<TestLocations.NestedTestLocations, LocationModels.ExampleResponse>(
|
||||
val testNestLocation = GetInfo<TestLocationsParent.TestLocations.NestedTestLocations, LocationModels.ExampleResponse>(
|
||||
summary = "Nested",
|
||||
description = "Gettin' scary",
|
||||
responseInfo = ResponseInfo(
|
||||
@ -85,7 +85,7 @@ private object LocationsToC {
|
||||
description = "Hmmm"
|
||||
)
|
||||
)
|
||||
val ohBoiUCrazy = GetInfo<TestLocations.NestedTestLocations.OhBoiUCrazy, LocationModels.ExampleResponse>(
|
||||
val ohBoiUCrazy = GetInfo<TestLocationsParent.TestLocations.NestedTestLocations.OhBoiUCrazy, LocationModels.ExampleResponse>(
|
||||
summary = "Example Deeply Nested",
|
||||
description = "We deep now",
|
||||
responseInfo = ResponseInfo(
|
||||
@ -99,17 +99,21 @@ private object LocationsToC {
|
||||
// For more info make sure to read through the Ktor location docs
|
||||
// Additionally, make sure to note that even though we define the locations here, we still must annotate fields
|
||||
// with KompendiumParam!!!
|
||||
@Location("test/{name}")
|
||||
data class TestLocations(
|
||||
object TestLocationsParent {
|
||||
|
||||
@Location("test/{name}")
|
||||
data class TestLocations(
|
||||
@Param(ParamType.PATH)
|
||||
val name: String,
|
||||
) {
|
||||
) {
|
||||
|
||||
@Location("/spaghetti")
|
||||
data class NestedTestLocations(
|
||||
@Param(ParamType.QUERY)
|
||||
val idk: Int,
|
||||
val parent: TestLocations
|
||||
) {
|
||||
|
||||
@Location("/hehe/{madness}")
|
||||
data class OhBoiUCrazy(
|
||||
@Param(ParamType.PATH)
|
||||
@ -117,6 +121,7 @@ data class TestLocations(
|
||||
val parent: NestedTestLocations
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object LocationModels {
|
||||
|
Reference in New Issue
Block a user