Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
dd780ad29d | |||
d2165d23bf | |||
d9d0f129b5 |
13
CHANGELOG.md
13
CHANGELOG.md
@ -1,5 +1,18 @@
|
||||
# Changelog
|
||||
|
||||
## [1.10.0] - November 25th, 2021
|
||||
|
||||
### Changed
|
||||
|
||||
- Added `operationId` parameter to `MethodInfo`
|
||||
|
||||
## [1.9.2] - October 24th, 2021
|
||||
|
||||
### Changed
|
||||
|
||||
- Jackson ObjectMapper passed by parameter to openapi module
|
||||
- Added serializable annotation to ExceptionResponse
|
||||
|
||||
## [1.9.1] - October 17th, 2021
|
||||
|
||||
### Changed
|
||||
|
116
README.md
116
README.md
@ -6,13 +6,15 @@
|
||||
|
||||
## What is Kompendium
|
||||
|
||||
Kompendium is intended to be a minimally invasive OpenApi Specification generator for [Ktor](https://ktor.io).
|
||||
Minimally invasive meaning that users will use only Ktor native functions when implementing their API, and will
|
||||
supplement with Kompendium code in order to generate the appropriate spec.
|
||||
### ⚠️ For info on V2 please see [here](#V2)
|
||||
|
||||
Kompendium is intended to be a minimally invasive OpenApi Specification generator for [Ktor](https://ktor.io).
|
||||
Minimally invasive meaning that users will use only Ktor native functions when implementing their API, and will
|
||||
supplement with Kompendium code in order to generate the appropriate spec.
|
||||
|
||||
## How to install
|
||||
|
||||
Kompendium publishes all releases to Maven Central. As such, using the stable version of `Kompendium` is as simple
|
||||
Kompendium publishes all releases to Maven Central. As such, using the stable version of `Kompendium` is as simple
|
||||
as declaring it as an implementation dependency in your `build.gradle.kts`
|
||||
|
||||
```kotlin
|
||||
@ -31,8 +33,8 @@ dependencies {
|
||||
|
||||
The last two dependencies are optional.
|
||||
|
||||
If you want to get a little spicy 🤠 every merge of Kompendium is published to the GitHub package registry. Pulling
|
||||
from GitHub is slightly more involved, but such is the price you pay for bleeding edge fake data generation.
|
||||
If you want to get a little spicy 🤠 every merge of Kompendium is published to the GitHub package registry. Pulling
|
||||
from GitHub is slightly more involved, but such is the price you pay for bleeding edge fake data generation.
|
||||
|
||||
```kotlin
|
||||
// 1 Setup a helper function to import any Github Repository Package
|
||||
@ -60,14 +62,14 @@ dependencies {
|
||||
|
||||
## Local Development
|
||||
|
||||
Kompendium should run locally right out of the box, no configuration necessary (assuming you have JDK 1.8+ installed). New features can be built locally and published to your local maven repository with the `./gradlew publishToMavenLocal` command!
|
||||
Kompendium should run locally right out of the box, no configuration necessary (assuming you have JDK 1.8+ installed). New features can be built locally and published to your local maven repository with the `./gradlew publishToMavenLocal` command!
|
||||
|
||||
## In depth
|
||||
|
||||
### Notarized Routes
|
||||
### Notarized Routes
|
||||
|
||||
Kompendium introduces the concept of `notarized` HTTP methods. That is, for all your `GET`, `POST`, `PUT`, and `DELETE`
|
||||
operations, there is a corresponding `notarized` method. These operations are strongly typed, and use reification for
|
||||
operations, there is a corresponding `notarized` method. These operations are strongly typed, and use reification for
|
||||
a lot of the class based reflection that powers Kompendium. Generally speaking the three types that a `notarized` method
|
||||
will consume are
|
||||
|
||||
@ -79,62 +81,85 @@ will consume are
|
||||
|
||||
|
||||
In addition to standard HTTP Methods, Kompendium also introduced the concept of `notarizedExceptions`. Using the `StatusPage`
|
||||
extension, users can notarize all handled exceptions, along with their respective HTTP codes and response types.
|
||||
extension, users can notarize all handled exceptions, along with their respective HTTP codes and response types.
|
||||
Exceptions that have been `notarized` require two types as supplemental information
|
||||
|
||||
- `TErr`: Used to notarize the exception being handled by this use case. Used for matching responses at the route level.
|
||||
- `TResp`: Same as above, this dictates the expected return type of the error response.
|
||||
- `TResp`: Same as above, this dictates the expected return type of the error response.
|
||||
|
||||
In keeping with minimal invasion, these extension methods all consume the same code block as a standard Ktor route method,
|
||||
meaning that swapping in a default Ktor route and a Kompendium `notarized` route is as simple as a single method change.
|
||||
|
||||
### Supplemental Annotations
|
||||
|
||||
In general, Kompendium tries to limit the number of annotations that developers need to use in order to get an app
|
||||
integrated.
|
||||
In general, Kompendium tries to limit the number of annotations that developers need to use in order to get an app
|
||||
integrated.
|
||||
|
||||
Currently, the annotations used by Kompendium are as follows
|
||||
Currently, the annotations used by Kompendium are as follows
|
||||
|
||||
- `KompendiumField`
|
||||
- `KompendiumParam`
|
||||
|
||||
The intended purpose of `KompendiumField` is to offer field level overrides such as naming conventions (ie snake instead of camel).
|
||||
|
||||
The purpose of `KompendiumParam` is to provide supplemental information needed to properly assign the type of parameter
|
||||
(cookie, header, query, path) as well as other parameter-level metadata.
|
||||
The purpose of `KompendiumParam` is to provide supplemental information needed to properly assign the type of parameter
|
||||
(cookie, header, query, path) as well as other parameter-level metadata.
|
||||
|
||||
### Undeclared Field
|
||||
|
||||
There is also a final `UndeclaredField` annotation. This should be used only in an absolutely emergency. This annotation
|
||||
will allow you to inject a _single_ undeclared field that will be included as part of the schema.
|
||||
will allow you to inject a _single_ undeclared field that will be included as part of the schema.
|
||||
|
||||
Due to limitations in using repeated annotations, this can only be used once per class
|
||||
|
||||
This is a complete hack, and is included for odd scenarios like kotlinx serialization polymorphic adapters that expect a
|
||||
`type` field in order to perform their analysis.
|
||||
This is a complete hack, and is included for odd scenarios like kotlinx serialization polymorphic adapters that expect a
|
||||
`type` field in order to perform their analysis.
|
||||
|
||||
Use this _only_ when **all** else fails
|
||||
|
||||
### Polymorphism
|
||||
|
||||
Speaking of polymorphism... out of the box, Kompendium has support for sealed classes and interfaces. At runtime, it will build a mapping of all available sub-classes
|
||||
and build a spec that takes `anyOf` the implementations. This is currently a weak point of the entire library, and
|
||||
and build a spec that takes `anyOf` the implementations. This is currently a weak point of the entire library, and
|
||||
suggestions on better implementations are welcome 🤠
|
||||
|
||||
### Serialization
|
||||
|
||||
Under the hood, Kompendium uses Jackson to serialize the final api spec. However, this implementation detail
|
||||
does not leak to the actual API, meaning that users are free to choose the serialization library of their choice.
|
||||
Under the hood, Kompendium uses Jackson to serialize the final api spec. However, this implementation detail
|
||||
does not leak to the actual API, meaning that users are free to choose the serialization library of their choice.
|
||||
|
||||
Added the possibility to add your own ObjectMapper for Jackson.
|
||||
|
||||
Added a default parameter with the following configuration:
|
||||
|
||||
```kotlin
|
||||
ObjectMapper()
|
||||
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
||||
.enable(SerializationFeature.INDENT_OUTPUT)
|
||||
```
|
||||
|
||||
If you want to change this default configuration and use your own ObjectMapper you only need to pass it as a second argument to the openApi module:
|
||||
|
||||
```kotlin
|
||||
routing {
|
||||
openApi(oas, objectMapper)
|
||||
route("/potato/spud") {
|
||||
notarizedGet(simpleGetInfo) {
|
||||
call.respond(HttpStatusCode.OK)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Route Handling
|
||||
|
||||
> ⚠️ Warning: Custom route handling is almost definitely an indication that either a new selector should be added to kompendium-core or that kompendium is in need of another module to handle a new ktor companion module. If you have encountered a route selector that is not already handled, please consider opening an [issue](https://github.com/bkbnio/kompendium/issues/new)
|
||||
|
||||
Kompendium does its best to handle all Ktor routes out of the gate. However, in keeping with the modular approach of
|
||||
Ktor and Kompendium, this is not always possible.
|
||||
Kompendium does its best to handle all Ktor routes out of the gate. However, in keeping with the modular approach of
|
||||
Ktor and Kompendium, this is not always possible.
|
||||
|
||||
Should you need to, custom route handlers can be registered via the
|
||||
`Kompendium.addCustomRouteHandler` function.
|
||||
Should you need to, custom route handlers can be registered via the
|
||||
`Kompendium.addCustomRouteHandler` function.
|
||||
|
||||
The handler signature is as follows
|
||||
|
||||
@ -146,7 +171,7 @@ fun <T : RouteSelector> addCustomRouteHandler(
|
||||
```
|
||||
|
||||
This function takes a selector, which _must_ be a KClass of the Ktor `RouteSelector` type. The handler is a function
|
||||
that extends the Kompendium `PathCalculator`. This is necessary because it gives you access to `PathCalculator.calculate`,
|
||||
that extends the Kompendium `PathCalculator`. This is necessary because it gives you access to `PathCalculator.calculate`,
|
||||
which you are going to want in order to recursively calculate the remainder of the route :)
|
||||
|
||||
Its parameters are the `Route` itself, along with the "tail" of the Path (the path that has been calculated thus far).
|
||||
@ -155,7 +180,7 @@ Working examples `init` blocks of the `PathCalculator` and `KompendiumAuth` obje
|
||||
|
||||
## Examples
|
||||
|
||||
The full source code can be found in the `kompendium-playground` module. Here is a simple get endpoint example
|
||||
The full source code can be found in the `kompendium-playground` module. Here is a simple get endpoint example
|
||||
|
||||
```kotlin
|
||||
// Minimal API Example
|
||||
@ -185,6 +210,7 @@ fun Application.mainModule() {
|
||||
val simpleGetInfo = GetInfo<Unit, ExampleResponse>(
|
||||
summary = "Example Parameters",
|
||||
description = "A test for setting parameter examples",
|
||||
operationId = "getExamples",
|
||||
responseInfo = ResponseInfo(
|
||||
status = 200,
|
||||
description = "nice",
|
||||
@ -196,7 +222,7 @@ val simpleGetInfo = GetInfo<Unit, ExampleResponse>(
|
||||
|
||||
### Kompendium Auth and security schemes
|
||||
|
||||
There is a separate library to handle security schemes: `kompendium-auth`.
|
||||
There is a separate library to handle security schemes: `kompendium-auth`.
|
||||
This needs to be added to your project as dependency.
|
||||
|
||||
At the moment, the basic and jwt authentication is only supported.
|
||||
@ -252,7 +278,7 @@ Minimal Example:
|
||||
```
|
||||
|
||||
### Enabling ReDoc
|
||||
Unlike swagger, redoc is provided (perhaps confusingly, in the `core` module). This means out of the box with `kompendium-core`, you can add
|
||||
Unlike swagger, redoc is provided (perhaps confusingly, in the `core` module). This means out of the box with `kompendium-core`, you can add
|
||||
[ReDoc](https://github.com/Redocly/redoc) as follows
|
||||
|
||||
```kotlin
|
||||
@ -264,20 +290,20 @@ routing {
|
||||
|
||||
## Custom Type Overrides
|
||||
|
||||
Kompendium does its best to analyze types and to generate an OpenAPI format accordingly. However, there are certain
|
||||
Kompendium does its best to analyze types and to generate an OpenAPI format accordingly. However, there are certain
|
||||
classes that just don't play nice with the standard reflection analysis that Kompendium performs.
|
||||
Should you encounter a data type that Kompendium cannot comprehend, you will need to
|
||||
add it explicitly. For example, adding the Joda Time `DateTime` object would be as simple as the following
|
||||
Should you encounter a data type that Kompendium cannot comprehend, you will need to
|
||||
add it explicitly. For example, adding the Joda Time `DateTime` object would be as simple as the following
|
||||
|
||||
```kotlin
|
||||
Kompendium.addCustomTypeSchema(DateTime::class, FormatSchema("date-time", "string"))
|
||||
```
|
||||
|
||||
Since `Kompendium` is an object, this needs to be declared once, ahead of the actual API instantiation. This way, this
|
||||
type override can be cached ahead of reflection. Kompendium will then match all instances of this type and return the
|
||||
specified schema.
|
||||
Since `Kompendium` is an object, this needs to be declared once, ahead of the actual API instantiation. This way, this
|
||||
type override can be cached ahead of reflection. Kompendium will then match all instances of this type and return the
|
||||
specified schema.
|
||||
|
||||
So how do you know a type can and cannot be inferred? The safe bet is that it can be. So go ahead and give it a shot.
|
||||
So how do you know a type can and cannot be inferred? The safe bet is that it can be. So go ahead and give it a shot.
|
||||
However, in the very odd scenario (almost always having to do with date/time libraries 😤) where it can't, you can rest
|
||||
safely knowing that you have the option to inject a custom override should you need to.
|
||||
|
||||
@ -287,18 +313,24 @@ safely knowing that you have the option to inject a custom override should you n
|
||||
|
||||
Currently, Kompendium exists as a Kotlin object. This comes with a couple perks, but a couple downsides. Primarily,
|
||||
it offers a seriously clean UX where the implementer doesn't need to worry about what instance to send data to. The main
|
||||
drawback, however, is that you are limited to a single API per classpath.
|
||||
drawback, however, is that you are limited to a single API per classpath.
|
||||
|
||||
If this is a blocker, please open a GitHub issue, and we can start to think out solutions!
|
||||
If this is a blocker, please open a GitHub issue, and we can start to think out solutions!
|
||||
|
||||
## Future Work
|
||||
Work on V1 of Kompendium has come to a close. This, however, does not mean it has achieved complete
|
||||
parity with the OpenAPI feature spec, nor does it have all-of-the nice to have features that a truly next-gen API spec
|
||||
parity with the OpenAPI feature spec, nor does it have all-of-the nice to have features that a truly next-gen API spec
|
||||
should have. There are several outstanding features that have been added to the
|
||||
[V2 Milestone](https://github.com/bkbnio/kompendium/milestone/2). Among others, this includes
|
||||
[V2 Milestone](https://github.com/bkbnio/kompendium/milestone/2). Among others, this includes
|
||||
|
||||
- AsyncAPI Integration
|
||||
- Field Validation
|
||||
|
||||
If you have a feature that you would like to see implemented that is not on this list, or discover a 🐞, please open
|
||||
If you have a feature that you would like to see implemented that is not on this list, or discover a 🐞, please open
|
||||
an issue [here](https://github.com/bkbnio/kompendium/issues/new)
|
||||
|
||||
### V2
|
||||
|
||||
Due to the large number of breaking changes that will be made in version 2, development is currently being done on the
|
||||
long-lived `v2` feature branch. If you are working on any feature in the `V2` milestone, please target that branch!
|
||||
If you are unsure where your changes should be, please open an issue first :)
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Kompendium
|
||||
project.version=1.9.1
|
||||
project.version=1.10.0
|
||||
# Kotlin
|
||||
kotlin.code.style=official
|
||||
# Gradle
|
||||
|
@ -49,6 +49,7 @@ object MethodParser {
|
||||
) = OpenApiSpecPathItemOperation(
|
||||
summary = info.summary,
|
||||
description = info.description,
|
||||
operationId = info.operationId,
|
||||
tags = info.tags,
|
||||
deprecated = info.deprecated,
|
||||
parameters = paramType.toParameterSpec(),
|
||||
|
@ -11,6 +11,7 @@ sealed class MethodInfo<TParam, TResp>(
|
||||
open val canThrow: Set<KClass<*>> = emptySet(),
|
||||
open val responseInfo: ResponseInfo<TResp>? = null,
|
||||
open val parameterExamples: Map<String, TParam> = emptyMap(),
|
||||
open val operationId: String? = null
|
||||
) {
|
||||
|
||||
data class GetInfo<TParam, TResp>(
|
||||
@ -21,7 +22,8 @@ sealed class MethodInfo<TParam, TResp>(
|
||||
override val deprecated: Boolean = false,
|
||||
override val securitySchemes: Set<String> = emptySet(),
|
||||
override val canThrow: Set<KClass<*>> = emptySet(),
|
||||
override val parameterExamples: Map<String, TParam> = emptyMap()
|
||||
override val parameterExamples: Map<String, TParam> = emptyMap(),
|
||||
override val operationId: String? = null
|
||||
) : MethodInfo<TParam, TResp>(
|
||||
summary = summary,
|
||||
description = description,
|
||||
@ -30,7 +32,8 @@ sealed class MethodInfo<TParam, TResp>(
|
||||
securitySchemes = securitySchemes,
|
||||
canThrow = canThrow,
|
||||
responseInfo = responseInfo,
|
||||
parameterExamples = parameterExamples
|
||||
parameterExamples = parameterExamples,
|
||||
operationId = operationId
|
||||
)
|
||||
|
||||
data class PostInfo<TParam, TReq, TResp>(
|
||||
@ -42,7 +45,8 @@ sealed class MethodInfo<TParam, TResp>(
|
||||
override val deprecated: Boolean = false,
|
||||
override val securitySchemes: Set<String> = emptySet(),
|
||||
override val canThrow: Set<KClass<*>> = emptySet(),
|
||||
override val parameterExamples: Map<String, TParam> = emptyMap()
|
||||
override val parameterExamples: Map<String, TParam> = emptyMap(),
|
||||
override val operationId: String? = null
|
||||
) : MethodInfo<TParam, TResp>(
|
||||
summary = summary,
|
||||
description = description,
|
||||
@ -51,7 +55,8 @@ sealed class MethodInfo<TParam, TResp>(
|
||||
securitySchemes = securitySchemes,
|
||||
canThrow = canThrow,
|
||||
responseInfo = responseInfo,
|
||||
parameterExamples = parameterExamples
|
||||
parameterExamples = parameterExamples,
|
||||
operationId = operationId
|
||||
)
|
||||
|
||||
data class PutInfo<TParam, TReq, TResp>(
|
||||
@ -63,7 +68,8 @@ sealed class MethodInfo<TParam, TResp>(
|
||||
override val deprecated: Boolean = false,
|
||||
override val securitySchemes: Set<String> = emptySet(),
|
||||
override val canThrow: Set<KClass<*>> = emptySet(),
|
||||
override val parameterExamples: Map<String, TParam> = emptyMap()
|
||||
override val parameterExamples: Map<String, TParam> = emptyMap(),
|
||||
override val operationId: String? = null
|
||||
) : MethodInfo<TParam, TResp>(
|
||||
summary = summary,
|
||||
description = description,
|
||||
@ -71,7 +77,8 @@ sealed class MethodInfo<TParam, TResp>(
|
||||
deprecated = deprecated,
|
||||
securitySchemes = securitySchemes,
|
||||
canThrow = canThrow,
|
||||
parameterExamples = parameterExamples
|
||||
parameterExamples = parameterExamples,
|
||||
operationId = operationId
|
||||
)
|
||||
|
||||
data class DeleteInfo<TParam, TResp>(
|
||||
@ -82,7 +89,8 @@ sealed class MethodInfo<TParam, TResp>(
|
||||
override val deprecated: Boolean = false,
|
||||
override val securitySchemes: Set<String> = emptySet(),
|
||||
override val canThrow: Set<KClass<*>> = emptySet(),
|
||||
override val parameterExamples: Map<String, TParam> = emptyMap()
|
||||
override val parameterExamples: Map<String, TParam> = emptyMap(),
|
||||
override val operationId: String? = null
|
||||
) : MethodInfo<TParam, TResp>(
|
||||
summary = summary,
|
||||
description = description,
|
||||
@ -90,6 +98,7 @@ sealed class MethodInfo<TParam, TResp>(
|
||||
deprecated = deprecated,
|
||||
securitySchemes = securitySchemes,
|
||||
canThrow = canThrow,
|
||||
parameterExamples = parameterExamples
|
||||
parameterExamples = parameterExamples,
|
||||
operationId = operationId
|
||||
)
|
||||
}
|
||||
|
@ -13,14 +13,19 @@ import io.ktor.routing.route
|
||||
/**
|
||||
* Provides an out-of-the-box route to return the generated [OpenApiSpec]
|
||||
* @param oas spec that is returned
|
||||
* @param om provider for Jackson
|
||||
*/
|
||||
fun Routing.openApi(oas: OpenApiSpec) {
|
||||
val om = ObjectMapper()
|
||||
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
||||
.enable(SerializationFeature.INDENT_OUTPUT)
|
||||
fun Routing.openApi(
|
||||
oas: OpenApiSpec,
|
||||
om: ObjectMapper = objectMapper
|
||||
) {
|
||||
route("/openapi.json") {
|
||||
get {
|
||||
call.respondText { om.writeValueAsString(oas) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val objectMapper = ObjectMapper()
|
||||
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
||||
.enable(SerializationFeature.INDENT_OUTPUT)
|
||||
|
@ -46,6 +46,7 @@ import io.bkbn.kompendium.util.trailingSlash
|
||||
import io.bkbn.kompendium.util.undeclaredType
|
||||
import io.bkbn.kompendium.util.withDefaultParameter
|
||||
import io.bkbn.kompendium.util.withExamples
|
||||
import io.bkbn.kompendium.util.withOperationId
|
||||
|
||||
internal class KompendiumTest {
|
||||
|
||||
@ -139,7 +140,6 @@ internal class KompendiumTest {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun `Notarized put does not interrupt the pipeline`() {
|
||||
withTestApplication({
|
||||
@ -363,6 +363,22 @@ internal class KompendiumTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Can add operationId`() {
|
||||
withTestApplication({
|
||||
jacksonConfigModule()
|
||||
docs()
|
||||
withOperationId()
|
||||
}) {
|
||||
// do
|
||||
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
|
||||
|
||||
// expect
|
||||
val expected = getFileSnapshot("notarized_get_with_operation_id.json").trim()
|
||||
assertEquals(expected, json, "The received json spec should match the expected content")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Generates the expected redoc`() {
|
||||
withTestApplication({
|
||||
@ -607,5 +623,4 @@ internal class KompendiumTest {
|
||||
redoc(oas)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -265,6 +265,18 @@ fun Application.withDefaultParameter() {
|
||||
}
|
||||
}
|
||||
|
||||
fun Application.withOperationId(){
|
||||
routing {
|
||||
route("/test") {
|
||||
notarizedGet(
|
||||
info = TestResponseInfo.testGetInfo.copy(operationId = "getTest")
|
||||
){
|
||||
call.respond(HttpStatusCode.OK)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Application.nonRequiredParamsGet() {
|
||||
routing {
|
||||
route("/test/optional") {
|
||||
|
@ -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" : {
|
||||
"get" : {
|
||||
"tags" : [ ],
|
||||
"summary" : "Another get test",
|
||||
"description" : "testing more",
|
||||
"operationId" : "getTest",
|
||||
"parameters" : [ {
|
||||
"name" : "a",
|
||||
"in" : "path",
|
||||
"schema" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
}, {
|
||||
"name" : "aa",
|
||||
"in" : "query",
|
||||
"schema" : {
|
||||
"type" : "integer",
|
||||
"format" : "int32"
|
||||
},
|
||||
"required" : true,
|
||||
"deprecated" : false
|
||||
} ],
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"description" : "A Successful Endeavor",
|
||||
"content" : {
|
||||
"application/json" : {
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/TestResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated" : false
|
||||
}
|
||||
}
|
||||
},
|
||||
"components" : {
|
||||
"schemas" : {
|
||||
"String" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"TestResponse" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"c" : {
|
||||
"$ref" : "#/components/schemas/String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Int" : {
|
||||
"type" : "integer",
|
||||
"format" : "int32"
|
||||
}
|
||||
},
|
||||
"securitySchemes" : { }
|
||||
},
|
||||
"security" : [ ],
|
||||
"tags" : [ ]
|
||||
}
|
@ -4,6 +4,7 @@ import io.bkbn.kompendium.annotations.KompendiumField
|
||||
import io.bkbn.kompendium.annotations.KompendiumParam
|
||||
import io.bkbn.kompendium.annotations.ParamType
|
||||
import io.bkbn.kompendium.annotations.UndeclaredField
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.joda.time.DateTime
|
||||
|
||||
data class ExampleParams(
|
||||
@ -27,6 +28,7 @@ data class ExampleRequest(
|
||||
val aaa: List<Long>
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ExampleResponse(val c: String)
|
||||
|
||||
data class ExceptionResponse(val message: String)
|
||||
|
Reference in New Issue
Block a user