breaking change: V3 alpha (#256)
This commit is contained in:
@ -1,8 +1,8 @@
|
|||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "1.6.21" apply false
|
kotlin("jvm") version "1.7.10" apply false
|
||||||
kotlin("plugin.serialization") version "1.6.21" apply false
|
kotlin("plugin.serialization") version "1.7.10" apply false
|
||||||
id("io.bkbn.sourdough.library.jvm") version "0.6.0" apply false
|
id("io.bkbn.sourdough.library.jvm") version "0.9.0" apply false
|
||||||
id("io.bkbn.sourdough.application.jvm") version "0.6.0" apply false
|
id("io.bkbn.sourdough.application.jvm") version "0.9.0" apply false
|
||||||
id("io.bkbn.sourdough.root") version "0.9.0"
|
id("io.bkbn.sourdough.root") version "0.9.0"
|
||||||
id("com.github.jakemarsden.git-hooks") version "0.0.2"
|
id("com.github.jakemarsden.git-hooks") version "0.0.2"
|
||||||
id("org.jetbrains.dokka") version "1.7.10"
|
id("org.jetbrains.dokka") version "1.7.10"
|
||||||
|
62
core/build.gradle.kts
Normal file
62
core/build.gradle.kts
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
kotlin("plugin.serialization")
|
||||||
|
id("io.bkbn.sourdough.library.jvm")
|
||||||
|
id("io.gitlab.arturbosch.detekt")
|
||||||
|
id("com.adarshr.test-logger")
|
||||||
|
id("org.jetbrains.dokka")
|
||||||
|
id("maven-publish")
|
||||||
|
id("java-library")
|
||||||
|
id("signing")
|
||||||
|
id("java-test-fixtures")
|
||||||
|
}
|
||||||
|
|
||||||
|
sourdoughLibrary {
|
||||||
|
libraryName.set("Kompendium Core")
|
||||||
|
libraryDescription.set("Core functionality for the Kompendium library")
|
||||||
|
compilerArgs.set(listOf("-opt-in=kotlin.RequiresOptIn"))
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// VERSIONS
|
||||||
|
val kotestVersion: String by project
|
||||||
|
val ktorVersion: String by project
|
||||||
|
|
||||||
|
// IMPLEMENTATION
|
||||||
|
|
||||||
|
api(projects.kompendiumOas)
|
||||||
|
api(projects.kompendiumJsonSchema)
|
||||||
|
|
||||||
|
implementation("io.ktor:ktor-server-core:$ktorVersion")
|
||||||
|
implementation("io.ktor:ktor-server-cio:$ktorVersion")
|
||||||
|
implementation("io.ktor:ktor-server-html-builder:$ktorVersion")
|
||||||
|
implementation("io.ktor:ktor-server-content-negotiation:$ktorVersion")
|
||||||
|
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
|
||||||
|
implementation("ch.qos.logback:logback-classic:1.2.11")
|
||||||
|
|
||||||
|
// TEST FIXTURES
|
||||||
|
|
||||||
|
testFixturesApi("io.kotest:kotest-runner-junit5-jvm:$kotestVersion")
|
||||||
|
testFixturesApi("io.kotest:kotest-assertions-core-jvm:$kotestVersion")
|
||||||
|
testFixturesApi("io.kotest:kotest-property-jvm:$kotestVersion")
|
||||||
|
testFixturesApi("io.kotest:kotest-assertions-json-jvm:$kotestVersion")
|
||||||
|
testFixturesApi("io.kotest:kotest-assertions-ktor-jvm:4.4.3")
|
||||||
|
|
||||||
|
testFixturesApi("io.ktor:ktor-server-core:$ktorVersion")
|
||||||
|
testFixturesApi("io.ktor:ktor-server-test-host:$ktorVersion")
|
||||||
|
testFixturesApi("io.ktor:ktor-serialization:$ktorVersion")
|
||||||
|
testFixturesApi("io.ktor:ktor-serialization-jackson:$ktorVersion")
|
||||||
|
testFixturesApi("io.ktor:ktor-serialization-gson:$ktorVersion")
|
||||||
|
testFixturesApi("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
|
||||||
|
testFixturesApi("io.ktor:ktor-server-content-negotiation:$ktorVersion")
|
||||||
|
|
||||||
|
testFixturesApi("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.3")
|
||||||
|
}
|
||||||
|
|
||||||
|
testing {
|
||||||
|
suites {
|
||||||
|
named("test", JvmTestSuite::class) {
|
||||||
|
useJUnitJupiter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package io.bkbn.kompendium.core.attribute
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.oas.OpenApiSpec
|
||||||
|
import io.ktor.util.AttributeKey
|
||||||
|
|
||||||
|
object KompendiumAttributes {
|
||||||
|
val openApiSpec = AttributeKey<OpenApiSpec>("OpenApiSpec")
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package io.bkbn.kompendium.core.metadata
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||||
|
import io.bkbn.kompendium.oas.payload.Parameter
|
||||||
|
|
||||||
|
class DeleteInfo private constructor(
|
||||||
|
override val response: ResponseInfo,
|
||||||
|
override val errors: MutableList<ResponseInfo>,
|
||||||
|
override val tags: Set<String>,
|
||||||
|
override val summary: String,
|
||||||
|
override val description: String,
|
||||||
|
override val externalDocumentation: ExternalDocumentation?,
|
||||||
|
override val operationId: String?,
|
||||||
|
override val deprecated: Boolean,
|
||||||
|
override val parameters: List<Parameter>
|
||||||
|
): MethodInfo {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun builder(init: Builder.() -> Unit): DeleteInfo {
|
||||||
|
val builder = Builder()
|
||||||
|
builder.init()
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Builder : MethodInfo.Builder<DeleteInfo>() {
|
||||||
|
override fun build() = DeleteInfo(
|
||||||
|
response = response!!,
|
||||||
|
errors = errors,
|
||||||
|
tags = tags,
|
||||||
|
summary = summary!!,
|
||||||
|
description = description!!,
|
||||||
|
externalDocumentation = externalDocumentation,
|
||||||
|
operationId = operationId,
|
||||||
|
deprecated = deprecated,
|
||||||
|
parameters = parameters
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package io.bkbn.kompendium.core.metadata
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||||
|
import io.bkbn.kompendium.oas.payload.Parameter
|
||||||
|
|
||||||
|
class GetInfo private constructor(
|
||||||
|
override val response: ResponseInfo,
|
||||||
|
override val errors: MutableList<ResponseInfo>,
|
||||||
|
override val tags: Set<String>,
|
||||||
|
override val summary: String,
|
||||||
|
override val description: String,
|
||||||
|
override val externalDocumentation: ExternalDocumentation?,
|
||||||
|
override val operationId: String?,
|
||||||
|
override val deprecated: Boolean,
|
||||||
|
override val parameters: List<Parameter>
|
||||||
|
): MethodInfo {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun builder(init: Builder.() -> Unit): GetInfo {
|
||||||
|
val builder = Builder()
|
||||||
|
builder.init()
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Builder : MethodInfo.Builder<GetInfo>() {
|
||||||
|
override fun build() = GetInfo(
|
||||||
|
response = response ?: error("You must provide a response in order to notarize a GET"),
|
||||||
|
errors = errors,
|
||||||
|
tags = tags,
|
||||||
|
summary = summary ?: error("You must provide a summary in order to notarize a GET"),
|
||||||
|
description = description ?: error("You must provide a description in order to notarize a GET"),
|
||||||
|
externalDocumentation = externalDocumentation,
|
||||||
|
operationId = operationId,
|
||||||
|
deprecated = deprecated,
|
||||||
|
parameters = parameters
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package io.bkbn.kompendium.core.metadata
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||||
|
import io.bkbn.kompendium.oas.payload.Parameter
|
||||||
|
|
||||||
|
class HeadInfo private constructor(
|
||||||
|
override val response: ResponseInfo,
|
||||||
|
override val errors: MutableList<ResponseInfo>,
|
||||||
|
override val tags: Set<String>,
|
||||||
|
override val summary: String,
|
||||||
|
override val description: String,
|
||||||
|
override val externalDocumentation: ExternalDocumentation?,
|
||||||
|
override val operationId: String?,
|
||||||
|
override val deprecated: Boolean,
|
||||||
|
override val parameters: List<Parameter>
|
||||||
|
): MethodInfo {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun builder(init: Builder.() -> Unit): HeadInfo {
|
||||||
|
val builder = Builder()
|
||||||
|
builder.init()
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Builder : MethodInfo.Builder<HeadInfo>() {
|
||||||
|
override fun build() = HeadInfo(
|
||||||
|
response = response!!,
|
||||||
|
errors = errors,
|
||||||
|
tags = tags,
|
||||||
|
summary = summary!!,
|
||||||
|
description = description!!,
|
||||||
|
externalDocumentation = externalDocumentation,
|
||||||
|
operationId = operationId,
|
||||||
|
deprecated = deprecated,
|
||||||
|
parameters = parameters
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package io.bkbn.kompendium.core.metadata
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||||
|
import io.bkbn.kompendium.oas.payload.Parameter
|
||||||
|
|
||||||
|
sealed interface MethodInfo {
|
||||||
|
val response: ResponseInfo
|
||||||
|
val errors: List<ResponseInfo>
|
||||||
|
val tags: Set<String>
|
||||||
|
val summary: String
|
||||||
|
val description: String
|
||||||
|
val externalDocumentation: ExternalDocumentation?
|
||||||
|
get() = null
|
||||||
|
val operationId: String?
|
||||||
|
get() = null
|
||||||
|
val deprecated: Boolean
|
||||||
|
get() = false
|
||||||
|
val parameters: List<Parameter>
|
||||||
|
get() = emptyList()
|
||||||
|
|
||||||
|
abstract class Builder<T : MethodInfo> {
|
||||||
|
internal var response: ResponseInfo? = null
|
||||||
|
internal var summary: String? = null
|
||||||
|
internal var description: String? = null
|
||||||
|
internal var externalDocumentation: ExternalDocumentation? = null
|
||||||
|
internal var operationId: String? = null
|
||||||
|
internal var deprecated: Boolean = false
|
||||||
|
internal var tags: Set<String> = emptySet()
|
||||||
|
internal var parameters: List<Parameter> = emptyList()
|
||||||
|
internal var errors: MutableList<ResponseInfo> = mutableListOf()
|
||||||
|
|
||||||
|
fun response(init: ResponseInfo.Builder.() -> Unit) = apply {
|
||||||
|
val builder = ResponseInfo.Builder()
|
||||||
|
builder.init()
|
||||||
|
this.response = builder.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun canRespond(init: ResponseInfo.Builder.() -> Unit) = apply {
|
||||||
|
val builder = ResponseInfo.Builder()
|
||||||
|
builder.init()
|
||||||
|
errors.add(builder.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun canRespond(responses: List<ResponseInfo>) = apply {
|
||||||
|
errors.addAll(responses)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun summary(s: String) = apply { this.summary = s }
|
||||||
|
|
||||||
|
fun description(s: String) = apply { this.description = s }
|
||||||
|
|
||||||
|
fun externalDocumentation(docs: ExternalDocumentation) = apply { this.externalDocumentation = docs }
|
||||||
|
|
||||||
|
fun operationId(id: String) = apply { this.operationId = id }
|
||||||
|
|
||||||
|
fun isDeprecated() = apply { this.deprecated = true }
|
||||||
|
|
||||||
|
fun tags(vararg tags: String) = apply { this.tags = tags.toSet() }
|
||||||
|
|
||||||
|
fun parameters(vararg parameters: Parameter) = apply { this.parameters = parameters.toList() }
|
||||||
|
|
||||||
|
abstract fun build(): T
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package io.bkbn.kompendium.core.metadata
|
||||||
|
|
||||||
|
sealed interface MethodInfoWithRequest : MethodInfo {
|
||||||
|
val request: RequestInfo
|
||||||
|
|
||||||
|
abstract class Builder<T: MethodInfoWithRequest> : MethodInfo.Builder<T>() {
|
||||||
|
internal var request: RequestInfo? = null
|
||||||
|
|
||||||
|
fun request(init: RequestInfo.Builder.() -> Unit) = apply {
|
||||||
|
val builder = RequestInfo.Builder()
|
||||||
|
builder.init()
|
||||||
|
this.request = builder.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package io.bkbn.kompendium.core.metadata
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||||
|
import io.bkbn.kompendium.oas.payload.Parameter
|
||||||
|
|
||||||
|
class OptionsInfo private constructor(
|
||||||
|
override val response: ResponseInfo,
|
||||||
|
override val errors: MutableList<ResponseInfo>,
|
||||||
|
override val tags: Set<String>,
|
||||||
|
override val summary: String,
|
||||||
|
override val description: String,
|
||||||
|
override val externalDocumentation: ExternalDocumentation?,
|
||||||
|
override val operationId: String?,
|
||||||
|
override val deprecated: Boolean,
|
||||||
|
override val parameters: List<Parameter>
|
||||||
|
): MethodInfo {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun builder(init: Builder.() -> Unit): OptionsInfo {
|
||||||
|
val builder = Builder()
|
||||||
|
builder.init()
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Builder : MethodInfo.Builder<OptionsInfo>() {
|
||||||
|
override fun build() = OptionsInfo(
|
||||||
|
response = response!!,
|
||||||
|
errors = errors,
|
||||||
|
tags = tags,
|
||||||
|
summary = summary!!,
|
||||||
|
description = description!!,
|
||||||
|
externalDocumentation = externalDocumentation,
|
||||||
|
operationId = operationId,
|
||||||
|
deprecated = deprecated,
|
||||||
|
parameters = parameters
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package io.bkbn.kompendium.core.metadata
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||||
|
import io.bkbn.kompendium.oas.payload.Parameter
|
||||||
|
|
||||||
|
class PatchInfo private constructor(
|
||||||
|
override val request: RequestInfo,
|
||||||
|
override val errors: MutableList<ResponseInfo>,
|
||||||
|
override val response: ResponseInfo,
|
||||||
|
override val tags: Set<String>,
|
||||||
|
override val summary: String,
|
||||||
|
override val description: String,
|
||||||
|
override val externalDocumentation: ExternalDocumentation?,
|
||||||
|
override val operationId: String?,
|
||||||
|
override val deprecated: Boolean,
|
||||||
|
override val parameters: List<Parameter>
|
||||||
|
): MethodInfoWithRequest {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun builder(init: Builder.() -> Unit): PatchInfo {
|
||||||
|
val builder = Builder()
|
||||||
|
builder.init()
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Builder : MethodInfoWithRequest.Builder<PatchInfo>() {
|
||||||
|
override fun build() = PatchInfo(
|
||||||
|
request = request!!,
|
||||||
|
errors = errors,
|
||||||
|
response = response!!,
|
||||||
|
tags = tags,
|
||||||
|
summary = summary!!,
|
||||||
|
description = description!!,
|
||||||
|
externalDocumentation = externalDocumentation,
|
||||||
|
operationId = operationId,
|
||||||
|
deprecated = deprecated,
|
||||||
|
parameters = parameters
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package io.bkbn.kompendium.core.metadata
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||||
|
import io.bkbn.kompendium.oas.payload.Parameter
|
||||||
|
|
||||||
|
class PostInfo private constructor(
|
||||||
|
override val request: RequestInfo,
|
||||||
|
override val errors: MutableList<ResponseInfo>,
|
||||||
|
override val response: ResponseInfo,
|
||||||
|
override val tags: Set<String>,
|
||||||
|
override val summary: String,
|
||||||
|
override val description: String,
|
||||||
|
override val externalDocumentation: ExternalDocumentation?,
|
||||||
|
override val operationId: String?,
|
||||||
|
override val deprecated: Boolean,
|
||||||
|
override val parameters: List<Parameter>
|
||||||
|
): MethodInfoWithRequest {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun builder(init: Builder.() -> Unit): PostInfo {
|
||||||
|
val builder = Builder()
|
||||||
|
builder.init()
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Builder : MethodInfoWithRequest.Builder<PostInfo>() {
|
||||||
|
override fun build() = PostInfo(
|
||||||
|
request = request!!,
|
||||||
|
errors = errors,
|
||||||
|
response = response!!,
|
||||||
|
tags = tags,
|
||||||
|
summary = summary!!,
|
||||||
|
description = description!!,
|
||||||
|
externalDocumentation = externalDocumentation,
|
||||||
|
operationId = operationId,
|
||||||
|
deprecated = deprecated,
|
||||||
|
parameters = parameters
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package io.bkbn.kompendium.core.metadata
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||||
|
import io.bkbn.kompendium.oas.payload.Parameter
|
||||||
|
|
||||||
|
class PutInfo private constructor(
|
||||||
|
override val request: RequestInfo,
|
||||||
|
override val errors: MutableList<ResponseInfo>,
|
||||||
|
override val response: ResponseInfo,
|
||||||
|
override val tags: Set<String>,
|
||||||
|
override val summary: String,
|
||||||
|
override val description: String,
|
||||||
|
override val externalDocumentation: ExternalDocumentation?,
|
||||||
|
override val operationId: String?,
|
||||||
|
override val deprecated: Boolean,
|
||||||
|
override val parameters: List<Parameter>
|
||||||
|
): MethodInfoWithRequest {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun builder(init: Builder.() -> Unit): PutInfo {
|
||||||
|
val builder = Builder()
|
||||||
|
builder.init()
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Builder : MethodInfoWithRequest.Builder<PutInfo>() {
|
||||||
|
override fun build() = PutInfo(
|
||||||
|
request = request!!,
|
||||||
|
errors = errors,
|
||||||
|
response = response!!,
|
||||||
|
tags = tags,
|
||||||
|
summary = summary!!,
|
||||||
|
description = description!!,
|
||||||
|
externalDocumentation = externalDocumentation,
|
||||||
|
operationId = operationId,
|
||||||
|
deprecated = deprecated,
|
||||||
|
parameters = parameters
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package io.bkbn.kompendium.core.metadata
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.oas.payload.MediaType
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
import kotlin.reflect.typeOf
|
||||||
|
|
||||||
|
class RequestInfo private constructor(
|
||||||
|
val requestType: KType,
|
||||||
|
val description: String,
|
||||||
|
val examples: Map<String, MediaType.Example>?
|
||||||
|
) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun builder(init: Builder.() -> Unit): RequestInfo {
|
||||||
|
val builder = Builder()
|
||||||
|
builder.init()
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Builder {
|
||||||
|
private var requestType: KType? = null
|
||||||
|
private var description: String? = null
|
||||||
|
private var examples: Map<String, MediaType.Example>? = null
|
||||||
|
|
||||||
|
fun requestType(t: KType) = apply {
|
||||||
|
this.requestType = t
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T> requestType() = apply { requestType(typeOf<T>()) }
|
||||||
|
|
||||||
|
fun description(s: String) = apply { this.description = s }
|
||||||
|
|
||||||
|
fun examples(vararg e: Pair<String, Any>) = apply {
|
||||||
|
this.examples = e.toMap().mapValues { (_, v) -> MediaType.Example(v) }
|
||||||
|
println(this.examples)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun build() = RequestInfo(
|
||||||
|
requestType = requestType!!,
|
||||||
|
description = description!!,
|
||||||
|
examples = examples
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package io.bkbn.kompendium.core.metadata
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.oas.payload.MediaType
|
||||||
|
import io.ktor.http.HttpStatusCode
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
import kotlin.reflect.typeOf
|
||||||
|
|
||||||
|
class ResponseInfo private constructor(
|
||||||
|
val responseCode: HttpStatusCode,
|
||||||
|
val responseType: KType,
|
||||||
|
val description: String,
|
||||||
|
val examples: Map<String, MediaType.Example>?
|
||||||
|
) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun builder(init: Builder.() -> Unit): ResponseInfo {
|
||||||
|
val builder = Builder()
|
||||||
|
builder.init()
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Builder {
|
||||||
|
private var responseCode: HttpStatusCode? = null
|
||||||
|
private var responseType: KType? = null
|
||||||
|
private var description: String? = null
|
||||||
|
private var examples: Map<String, MediaType.Example>? = null
|
||||||
|
|
||||||
|
fun responseCode(code: HttpStatusCode) = apply {
|
||||||
|
this.responseCode = code
|
||||||
|
}
|
||||||
|
|
||||||
|
fun responseType(t: KType) = apply {
|
||||||
|
this.responseType = t
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T> responseType() = apply { responseType(typeOf<T>()) }
|
||||||
|
|
||||||
|
fun description(s: String) = apply { this.description = s }
|
||||||
|
|
||||||
|
fun examples(vararg e: Pair<String, Any>) = apply {
|
||||||
|
this.examples = e.toMap().mapValues { (_, v) -> MediaType.Example(v) }
|
||||||
|
println(this.examples)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun build() = ResponseInfo(
|
||||||
|
responseCode = responseCode ?: error("You must provide a response code in order to build a Response!"),
|
||||||
|
responseType = responseType ?: error("You must provide a response type in order to build a Response!"),
|
||||||
|
description = description ?: error("You must provide a description in order to build a Response!"),
|
||||||
|
examples = examples
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package io.bkbn.kompendium.core.plugin
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.core.attribute.KompendiumAttributes
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||||
|
import io.bkbn.kompendium.json.schema.util.Helpers.getSimpleSlug
|
||||||
|
import io.bkbn.kompendium.oas.OpenApiSpec
|
||||||
|
import io.ktor.http.HttpStatusCode
|
||||||
|
import io.ktor.server.application.call
|
||||||
|
import io.ktor.server.application.createApplicationPlugin
|
||||||
|
import io.ktor.server.response.respond
|
||||||
|
import io.ktor.server.routing.Routing
|
||||||
|
import io.ktor.server.routing.application
|
||||||
|
import io.ktor.server.routing.get
|
||||||
|
import io.ktor.server.routing.route
|
||||||
|
import io.ktor.server.routing.routing
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
|
||||||
|
object NotarizedApplication {
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
lateinit var spec: OpenApiSpec
|
||||||
|
var openApiJson: Routing.() -> Unit = {
|
||||||
|
route("/openapi.json") {
|
||||||
|
get {
|
||||||
|
call.respond(HttpStatusCode.OK, this@route.application.attributes[KompendiumAttributes.openApiSpec])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var customTypes: Map<KType, JsonSchema> = emptyMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun invoke() = createApplicationPlugin(
|
||||||
|
name = "NotarizedApplication",
|
||||||
|
createConfiguration = ::Config
|
||||||
|
) {
|
||||||
|
val spec = pluginConfig.spec
|
||||||
|
val routing = application.routing { }
|
||||||
|
pluginConfig.openApiJson(routing)
|
||||||
|
pluginConfig.customTypes.forEach { (type, schema) ->
|
||||||
|
spec.components.schemas[type.getSimpleSlug()] = schema
|
||||||
|
}
|
||||||
|
application.attributes.put(KompendiumAttributes.openApiSpec, spec)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,171 @@
|
|||||||
|
package io.bkbn.kompendium.core.plugin
|
||||||
|
|
||||||
|
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.MethodInfo
|
||||||
|
import io.bkbn.kompendium.core.metadata.MethodInfoWithRequest
|
||||||
|
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.metadata.ResponseInfo
|
||||||
|
import io.bkbn.kompendium.core.util.Helpers.getReferenceSlug
|
||||||
|
import io.bkbn.kompendium.core.util.Helpers.getSimpleSlug
|
||||||
|
import io.bkbn.kompendium.json.schema.SchemaGenerator
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.ReferenceDefinition
|
||||||
|
import io.bkbn.kompendium.oas.OpenApiSpec
|
||||||
|
import io.bkbn.kompendium.oas.path.Path
|
||||||
|
import io.bkbn.kompendium.oas.path.PathOperation
|
||||||
|
import io.bkbn.kompendium.oas.payload.MediaType
|
||||||
|
import io.bkbn.kompendium.oas.payload.Parameter
|
||||||
|
import io.bkbn.kompendium.oas.payload.Request
|
||||||
|
import io.bkbn.kompendium.oas.payload.Response
|
||||||
|
import io.ktor.server.application.ApplicationCallPipeline
|
||||||
|
import io.ktor.server.application.Hook
|
||||||
|
import io.ktor.server.application.createRouteScopedPlugin
|
||||||
|
import io.ktor.server.routing.Route
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
|
||||||
|
object NotarizedRoute {
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
var tags: Set<String> = emptySet()
|
||||||
|
var parameters: List<Parameter> = emptyList()
|
||||||
|
var get: GetInfo? = null
|
||||||
|
var post: PostInfo? = null
|
||||||
|
var put: PutInfo? = null
|
||||||
|
var delete: DeleteInfo? = null
|
||||||
|
var patch: PatchInfo? = null
|
||||||
|
var head: HeadInfo? = null
|
||||||
|
var options: OptionsInfo? = null
|
||||||
|
var security: Map<String, List<String>>? = null
|
||||||
|
internal var path: Path? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
private object InstallHook : Hook<(ApplicationCallPipeline) -> Unit> {
|
||||||
|
override fun install(pipeline: ApplicationCallPipeline, handler: (ApplicationCallPipeline) -> Unit) {
|
||||||
|
handler(pipeline)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun invoke() = createRouteScopedPlugin(
|
||||||
|
name = "NotarizedRoute",
|
||||||
|
createConfiguration = ::Config
|
||||||
|
) {
|
||||||
|
|
||||||
|
// This is required in order to introspect the route path
|
||||||
|
on(InstallHook) {
|
||||||
|
val route = it as? Route ?: return@on
|
||||||
|
val spec = application.attributes[KompendiumAttributes.openApiSpec]
|
||||||
|
val routePath = route.calculateRoutePath()
|
||||||
|
require(spec.paths[routePath] == null) {
|
||||||
|
"""
|
||||||
|
The specified path ${Parameter.Location.path} has already been documented!
|
||||||
|
Please make sure that all notarized paths are unique
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
spec.paths[routePath] = pluginConfig.path!!
|
||||||
|
}
|
||||||
|
|
||||||
|
val spec = application.attributes[KompendiumAttributes.openApiSpec]
|
||||||
|
|
||||||
|
val path = Path()
|
||||||
|
path.parameters = pluginConfig.parameters
|
||||||
|
|
||||||
|
pluginConfig.get?.addToSpec(path, spec, pluginConfig)
|
||||||
|
pluginConfig.delete?.addToSpec(path, spec, pluginConfig)
|
||||||
|
pluginConfig.head?.addToSpec(path, spec, pluginConfig)
|
||||||
|
pluginConfig.options?.addToSpec(path, spec, pluginConfig)
|
||||||
|
pluginConfig.post?.addToSpec(path, spec, pluginConfig)
|
||||||
|
pluginConfig.put?.addToSpec(path, spec, pluginConfig)
|
||||||
|
pluginConfig.patch?.addToSpec(path, spec, pluginConfig)
|
||||||
|
|
||||||
|
pluginConfig.path = path
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun MethodInfo.addToSpec(path: Path, spec: OpenApiSpec, config: Config) {
|
||||||
|
SchemaGenerator.fromTypeOrUnit(this.response.responseType, spec.components.schemas)?.let { schema ->
|
||||||
|
spec.components.schemas[this.response.responseType.getSimpleSlug()] = schema
|
||||||
|
}
|
||||||
|
|
||||||
|
errors.forEach { error ->
|
||||||
|
SchemaGenerator.fromTypeOrUnit(error.responseType, spec.components.schemas)?.let { schema ->
|
||||||
|
spec.components.schemas[error.responseType.getSimpleSlug()] = schema
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when (this) {
|
||||||
|
is MethodInfoWithRequest -> {
|
||||||
|
SchemaGenerator.fromTypeOrUnit(this.request.requestType, spec.components.schemas)?.let { schema ->
|
||||||
|
spec.components.schemas[this.request.requestType.getSimpleSlug()] = schema
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
val operations = this.toPathOperation(config)
|
||||||
|
|
||||||
|
when (this) {
|
||||||
|
is DeleteInfo -> path.delete = operations
|
||||||
|
is GetInfo -> path.get = operations
|
||||||
|
is HeadInfo -> path.head = operations
|
||||||
|
is PatchInfo -> path.patch = operations
|
||||||
|
is PostInfo -> path.post = operations
|
||||||
|
is PutInfo -> path.put = operations
|
||||||
|
is OptionsInfo -> path.options = operations
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun MethodInfo.toPathOperation(config: Config) = PathOperation(
|
||||||
|
tags = config.tags.plus(this.tags),
|
||||||
|
summary = this.summary,
|
||||||
|
description = this.description,
|
||||||
|
externalDocs = this.externalDocumentation,
|
||||||
|
operationId = this.operationId,
|
||||||
|
deprecated = this.deprecated,
|
||||||
|
parameters = this.parameters,
|
||||||
|
security = config.security
|
||||||
|
?.map { (k, v) -> k to v }
|
||||||
|
?.map { listOf(it).toMap() }
|
||||||
|
?.toList(),
|
||||||
|
requestBody = when (this) {
|
||||||
|
is MethodInfoWithRequest -> Request(
|
||||||
|
description = this.request.description,
|
||||||
|
content = this.request.requestType.toReferenceContent(this.request.examples),
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> null
|
||||||
|
},
|
||||||
|
responses = mapOf(
|
||||||
|
this.response.responseCode.value to Response(
|
||||||
|
description = this.response.description,
|
||||||
|
content = this.response.responseType.toReferenceContent(this.response.examples)
|
||||||
|
)
|
||||||
|
).plus(this.errors.toResponseMap())
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun List<ResponseInfo>.toResponseMap(): Map<Int, Response> = associate { error ->
|
||||||
|
error.responseCode.value to Response(
|
||||||
|
description = error.description,
|
||||||
|
content = error.responseType.toReferenceContent(error.examples)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KType.toReferenceContent(examples: Map<String, MediaType.Example>?): Map<String, MediaType>? =
|
||||||
|
when (this.classifier as KClass<*>) {
|
||||||
|
Unit::class -> null
|
||||||
|
else -> mapOf(
|
||||||
|
"application/json" to MediaType(
|
||||||
|
schema = ReferenceDefinition(this.getReferenceSlug()),
|
||||||
|
examples = examples
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Route.calculateRoutePath() = toString().replace(Regex("/\\(.+\\)"), "")
|
||||||
|
}
|
@ -1,10 +1,11 @@
|
|||||||
package io.bkbn.kompendium.core.routes
|
package io.bkbn.kompendium.core.routes
|
||||||
|
|
||||||
import io.ktor.application.call
|
import io.ktor.http.HttpStatusCode
|
||||||
import io.ktor.html.respondHtml
|
import io.ktor.server.application.call
|
||||||
import io.ktor.routing.Routing
|
import io.ktor.server.html.respondHtml
|
||||||
import io.ktor.routing.get
|
import io.ktor.server.routing.Routing
|
||||||
import io.ktor.routing.route
|
import io.ktor.server.routing.get
|
||||||
|
import io.ktor.server.routing.route
|
||||||
import kotlinx.html.body
|
import kotlinx.html.body
|
||||||
import kotlinx.html.head
|
import kotlinx.html.head
|
||||||
import kotlinx.html.link
|
import kotlinx.html.link
|
||||||
@ -22,7 +23,7 @@ import kotlinx.html.unsafe
|
|||||||
fun Routing.redoc(pageTitle: String = "Docs", specUrl: String = "/openapi.json") {
|
fun Routing.redoc(pageTitle: String = "Docs", specUrl: String = "/openapi.json") {
|
||||||
route("/docs") {
|
route("/docs") {
|
||||||
get {
|
get {
|
||||||
call.respondHtml {
|
call.respondHtml(HttpStatusCode.OK) {
|
||||||
head {
|
head {
|
||||||
title {
|
title {
|
||||||
+pageTitle
|
+pageTitle
|
35
core/src/main/kotlin/io/bkbn/kompendium/core/util/Helpers.kt
Normal file
35
core/src/main/kotlin/io/bkbn/kompendium/core/util/Helpers.kt
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package io.bkbn.kompendium.core.util
|
||||||
|
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
import kotlin.reflect.full.createType
|
||||||
|
import kotlin.reflect.jvm.javaField
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import java.lang.reflect.ParameterizedType
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
object Helpers {
|
||||||
|
|
||||||
|
private const val COMPONENT_SLUG = "#/components/schemas"
|
||||||
|
|
||||||
|
fun KType.getSimpleSlug(): String = when {
|
||||||
|
this.arguments.isNotEmpty() -> genericNameAdapter(this, classifier as KClass<*>)
|
||||||
|
else -> (classifier as KClass<*>).simpleName ?: error("Could not determine simple name for $this")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KType.getReferenceSlug(): String = when {
|
||||||
|
arguments.isNotEmpty() -> "$COMPONENT_SLUG/${genericNameAdapter(this, classifier as KClass<*>)}"
|
||||||
|
else -> "$COMPONENT_SLUG/${(classifier as KClass<*>).simpleName}"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapts a class with type parameters into a reference friendly string
|
||||||
|
*/
|
||||||
|
private fun genericNameAdapter(type: KType, clazz: KClass<*>): String {
|
||||||
|
val classNames = type.arguments
|
||||||
|
.map { it.type?.classifier as KClass<*> }
|
||||||
|
.map { it.simpleName }
|
||||||
|
return classNames.joinToString(separator = "-", prefix = "${clazz.simpleName}-")
|
||||||
|
}
|
||||||
|
}
|
201
core/src/test/kotlin/io/bkbn/kompendium/core/KompendiumTest.kt
Normal file
201
core/src/test/kotlin/io/bkbn/kompendium/core/KompendiumTest.kt
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
package io.bkbn.kompendium.core
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.core.fixtures.TestHelpers.openApiTestAllSerializers
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.complexRequest
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.dateTimeString
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.defaultField
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.defaultParameter
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.exampleParams
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.nestedUnderRoot
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.nonRequiredParams
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.notarizedDelete
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.notarizedGet
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.singleException
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.genericException
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.genericPolymorphicResponse
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.genericPolymorphicResponseMultipleImpls
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.headerParameter
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.multipleExceptions
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.nestedGenericResponse
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.nonRequiredParam
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.polymorphicException
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.notarizedHead
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.notarizedOptions
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.notarizedPatch
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.notarizedPost
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.notarizedPut
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.nullableEnumField
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.nullableField
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.nullableNestedObject
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.polymorphicCollectionResponse
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.polymorphicMapResponse
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.polymorphicResponse
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.primitives
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.reqRespExamples
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.requiredParams
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.returnsList
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.rootRoute
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.simpleGenericResponse
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.simplePathParsing
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.trailingSlash
|
||||||
|
import io.bkbn.kompendium.core.util.TestModules.withOperationId
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
|
||||||
|
import io.kotest.core.spec.style.DescribeSpec
|
||||||
|
import kotlin.reflect.typeOf
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
class KompendiumTest : DescribeSpec({
|
||||||
|
describe("Notarized Open API Metadata Tests") {
|
||||||
|
it("Can notarize a get request") {
|
||||||
|
openApiTestAllSerializers("T0001__notarized_get.json") { notarizedGet() }
|
||||||
|
}
|
||||||
|
it("Can notarize a post request") {
|
||||||
|
openApiTestAllSerializers("T0002__notarized_post.json") { notarizedPost() }
|
||||||
|
}
|
||||||
|
it("Can notarize a put request") {
|
||||||
|
openApiTestAllSerializers("T0003__notarized_put.json") { notarizedPut() }
|
||||||
|
}
|
||||||
|
it("Can notarize a delete request") {
|
||||||
|
openApiTestAllSerializers("T0004__notarized_delete.json") { notarizedDelete() }
|
||||||
|
}
|
||||||
|
it("Can notarize a patch request") {
|
||||||
|
openApiTestAllSerializers("T0005__notarized_patch.json") { notarizedPatch() }
|
||||||
|
}
|
||||||
|
it("Can notarize a head request") {
|
||||||
|
openApiTestAllSerializers("T0006__notarized_head.json") { notarizedHead() }
|
||||||
|
}
|
||||||
|
it("Can notarize an options request") {
|
||||||
|
openApiTestAllSerializers("T0007__notarized_options.json") { notarizedOptions() }
|
||||||
|
}
|
||||||
|
it("Can notarize a complex type") {
|
||||||
|
openApiTestAllSerializers("T0008__complex_type.json") { complexRequest() }
|
||||||
|
}
|
||||||
|
it("Can notarize primitives") {
|
||||||
|
openApiTestAllSerializers("T0009__notarized_primitives.json") { primitives() }
|
||||||
|
}
|
||||||
|
it("Can notarize a top level list response") {
|
||||||
|
openApiTestAllSerializers("T0010__response_list.json") { returnsList() }
|
||||||
|
}
|
||||||
|
it("Can notarize a route with non-required params") {
|
||||||
|
openApiTestAllSerializers("T0011__non_required_params.json") { nonRequiredParams() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
describe("Route Parsing") {
|
||||||
|
it("Can parse a simple path and store it under the expected route") {
|
||||||
|
openApiTestAllSerializers("T0012__path_parser.json") { simplePathParsing() }
|
||||||
|
}
|
||||||
|
it("Can notarize the root route") {
|
||||||
|
openApiTestAllSerializers("T0013__root_route.json") { rootRoute() }
|
||||||
|
}
|
||||||
|
it("Can notarize a route under the root module without appending trailing slash") {
|
||||||
|
openApiTestAllSerializers("T0014__nested_under_root.json") { nestedUnderRoot() }
|
||||||
|
}
|
||||||
|
it("Can notarize a route with a trailing slash") {
|
||||||
|
openApiTestAllSerializers("T0015__trailing_slash.json") { trailingSlash() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
describe("Exceptions") {
|
||||||
|
it("Can add an exception status code to a response") {
|
||||||
|
openApiTestAllSerializers("T0016__notarized_get_with_exception_response.json") { singleException() }
|
||||||
|
}
|
||||||
|
it("Can support multiple response codes") {
|
||||||
|
openApiTestAllSerializers("T0017__notarized_get_with_multiple_exception_responses.json") { multipleExceptions() }
|
||||||
|
}
|
||||||
|
it("Can add a polymorphic exception response") {
|
||||||
|
openApiTestAllSerializers("T0018__polymorphic_error_status_codes.json") { polymorphicException() }
|
||||||
|
}
|
||||||
|
it("Can add a generic exception response") {
|
||||||
|
openApiTestAllSerializers("T0019__generic_exception.json") { genericException() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
describe("Examples") {
|
||||||
|
it("Can generate example response and request bodies") {
|
||||||
|
openApiTestAllSerializers("T0020__example_req_and_resp.json") { reqRespExamples() }
|
||||||
|
}
|
||||||
|
it("Can describe example parameters") {
|
||||||
|
openApiTestAllSerializers("T0021__example_parameters.json") { exampleParams() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
describe("Defaults") {
|
||||||
|
it("Can generate a default parameter value") {
|
||||||
|
openApiTestAllSerializers("T0022__query_with_default_parameter.json") { defaultParameter() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
describe("Required Fields") {
|
||||||
|
it("Marks a parameter as required if there is no default and it is not marked nullable") {
|
||||||
|
openApiTestAllSerializers("T0023__required_param.json") { requiredParams() }
|
||||||
|
}
|
||||||
|
it("Can mark a parameter as not required") {
|
||||||
|
openApiTestAllSerializers("T0024__non_required_param.json") { nonRequiredParam() }
|
||||||
|
}
|
||||||
|
it("Does not mark a field as required if a default value is provided") {
|
||||||
|
openApiTestAllSerializers("T0025__default_field.json") { defaultField() }
|
||||||
|
}
|
||||||
|
it("Does not mark a nullable field as required") {
|
||||||
|
openApiTestAllSerializers("T0026__nullable_field.json") { nullableField() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
describe("Polymorphism and Generics") {
|
||||||
|
it("can generate a polymorphic response type") {
|
||||||
|
openApiTestAllSerializers("T0027__polymorphic_response.json") { polymorphicResponse() }
|
||||||
|
}
|
||||||
|
it("Can generate a collection with polymorphic response type") {
|
||||||
|
openApiTestAllSerializers("T0028__polymorphic_list_response.json") { polymorphicCollectionResponse() }
|
||||||
|
}
|
||||||
|
it("Can generate a map with a polymorphic response type") {
|
||||||
|
openApiTestAllSerializers("T0029__polymorphic_map_response.json") { polymorphicMapResponse() }
|
||||||
|
}
|
||||||
|
it("Can generate a response type with a generic type") {
|
||||||
|
openApiTestAllSerializers("T0030__simple_generic_response.json") { simpleGenericResponse() }
|
||||||
|
}
|
||||||
|
it("Can generate a response type with a nested generic type") {
|
||||||
|
openApiTestAllSerializers("T0031__nested_generic_response.json") { nestedGenericResponse() }
|
||||||
|
}
|
||||||
|
it("Can generate a polymorphic response type with generics") {
|
||||||
|
openApiTestAllSerializers("T0032__polymorphic_response_with_generics.json") { genericPolymorphicResponse() }
|
||||||
|
}
|
||||||
|
it("Can handle an absolutely psycho inheritance test") {
|
||||||
|
openApiTestAllSerializers("T0033__crazy_polymorphic_example.json") { genericPolymorphicResponseMultipleImpls() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
describe("Miscellaneous") {
|
||||||
|
xit("Can generate the necessary ReDoc home page") {
|
||||||
|
// TODO apiFunctionalityTest(getFileSnapshot("redoc.html"), "/docs") { returnsList() }
|
||||||
|
}
|
||||||
|
it("Can add an operation id to a notarized route") {
|
||||||
|
openApiTestAllSerializers("T0034__notarized_get_with_operation_id.json") { withOperationId() }
|
||||||
|
}
|
||||||
|
xit("Can add an undeclared field") {
|
||||||
|
// TODO openApiTestAllSerializers("undeclared_field.json") { undeclaredType() }
|
||||||
|
}
|
||||||
|
it("Can add a custom header parameter with a name override") {
|
||||||
|
openApiTestAllSerializers("T0035__override_parameter_name.json") { headerParameter() }
|
||||||
|
}
|
||||||
|
xit("Can override field name") {
|
||||||
|
// TODO Assess strategies here
|
||||||
|
}
|
||||||
|
xit("Can serialize a recursive type") {
|
||||||
|
// TODO openApiTestAllSerializers("simple_recursive.json") { simpleRecursive() }
|
||||||
|
}
|
||||||
|
it("Nullable fields do not lead to doom") {
|
||||||
|
openApiTestAllSerializers("T0036__nullable_fields.json") { nullableNestedObject() }
|
||||||
|
}
|
||||||
|
it("Can have a nullable enum as a member field") {
|
||||||
|
openApiTestAllSerializers("T0037__nullable_enum_field.json") { nullableEnumField() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
describe("Constraints") {
|
||||||
|
// TODO Assess strategies here
|
||||||
|
}
|
||||||
|
describe("Formats") {
|
||||||
|
it("Can set a format for a simple type schema") {
|
||||||
|
openApiTestAllSerializers(
|
||||||
|
snapshotName = "T0038__formatted_date_time_string.json",
|
||||||
|
customTypes = mapOf(typeOf<Instant>() to TypeDefinition(type = "string", format = "date"))
|
||||||
|
) { dateTimeString() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
describe("Free Form") {
|
||||||
|
// todo Assess strategies here
|
||||||
|
}
|
||||||
|
})
|
609
core/src/test/kotlin/io/bkbn/kompendium/core/util/TestModules.kt
Normal file
609
core/src/test/kotlin/io/bkbn/kompendium/core/util/TestModules.kt
Normal file
@ -0,0 +1,609 @@
|
|||||||
|
package io.bkbn.kompendium.core.util
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.core.fixtures.ColumnSchema
|
||||||
|
import io.bkbn.kompendium.core.fixtures.ComplexRequest
|
||||||
|
import io.bkbn.kompendium.core.fixtures.DateTimeString
|
||||||
|
import io.bkbn.kompendium.core.fixtures.DefaultField
|
||||||
|
import io.bkbn.kompendium.core.fixtures.ExceptionResponse
|
||||||
|
import io.bkbn.kompendium.core.fixtures.Flibbity
|
||||||
|
import io.bkbn.kompendium.core.fixtures.FlibbityGibbit
|
||||||
|
import io.bkbn.kompendium.core.fixtures.Gibbity
|
||||||
|
import io.bkbn.kompendium.core.fixtures.NullableEnum
|
||||||
|
import io.bkbn.kompendium.core.fixtures.NullableField
|
||||||
|
import io.bkbn.kompendium.core.fixtures.ProfileUpdateRequest
|
||||||
|
import io.bkbn.kompendium.core.fixtures.TestCreatedResponse
|
||||||
|
import io.bkbn.kompendium.core.fixtures.TestNested
|
||||||
|
import io.bkbn.kompendium.core.fixtures.TestRequest
|
||||||
|
import io.bkbn.kompendium.core.fixtures.TestResponse
|
||||||
|
import io.bkbn.kompendium.core.fixtures.TestSimpleRequest
|
||||||
|
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.plugin.NotarizedRoute
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
|
||||||
|
import io.bkbn.kompendium.oas.payload.Parameter
|
||||||
|
import io.ktor.http.HttpStatusCode
|
||||||
|
import io.ktor.server.application.call
|
||||||
|
import io.ktor.server.application.install
|
||||||
|
import io.ktor.server.response.respond
|
||||||
|
import io.ktor.server.response.respondText
|
||||||
|
import io.ktor.server.routing.Routing
|
||||||
|
import io.ktor.server.routing.delete
|
||||||
|
import io.ktor.server.routing.get
|
||||||
|
import io.ktor.server.routing.head
|
||||||
|
import io.ktor.server.routing.options
|
||||||
|
import io.ktor.server.routing.patch
|
||||||
|
import io.ktor.server.routing.post
|
||||||
|
import io.ktor.server.routing.put
|
||||||
|
import io.ktor.server.routing.route
|
||||||
|
|
||||||
|
object TestModules {
|
||||||
|
private const val defaultPath = "/test/{a}"
|
||||||
|
private const val rootPath = "/"
|
||||||
|
private const val defaultResponseDescription = "A Successful Endeavor"
|
||||||
|
private const val defaultRequestDescription = "You gotta send it"
|
||||||
|
private const val defaultPathSummary = "Great Summary!"
|
||||||
|
private const val defaultPathDescription = "testing more"
|
||||||
|
|
||||||
|
private val defaultParams = listOf(
|
||||||
|
Parameter(
|
||||||
|
name = "a",
|
||||||
|
`in` = Parameter.Location.path,
|
||||||
|
schema = TypeDefinition.STRING,
|
||||||
|
),
|
||||||
|
Parameter(
|
||||||
|
name = "aa",
|
||||||
|
`in` = Parameter.Location.query,
|
||||||
|
schema = TypeDefinition.INT
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fun Routing.notarizedGet() {
|
||||||
|
route(defaultPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
parameters = defaultParams
|
||||||
|
get = GetInfo.builder {
|
||||||
|
response {
|
||||||
|
responseCode(HttpStatusCode.OK)
|
||||||
|
responseType<TestResponse>()
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
}
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get {
|
||||||
|
call.respondText { "hey dude ‼️ congrats on the get request" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.notarizedPost() {
|
||||||
|
route(defaultPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
parameters = defaultParams
|
||||||
|
post = PostInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
request {
|
||||||
|
requestType<TestSimpleRequest>()
|
||||||
|
description("A Test request")
|
||||||
|
}
|
||||||
|
response {
|
||||||
|
responseCode(HttpStatusCode.Created)
|
||||||
|
responseType<TestCreatedResponse>()
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
call.respondText { "hey dude ‼️ congrats on the post request" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.notarizedPut() {
|
||||||
|
route(defaultPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
parameters = defaultParams
|
||||||
|
put = PutInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
request {
|
||||||
|
requestType<TestSimpleRequest>()
|
||||||
|
description("A Test request")
|
||||||
|
}
|
||||||
|
response {
|
||||||
|
responseCode(HttpStatusCode.Created)
|
||||||
|
responseType<TestCreatedResponse>()
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
put {
|
||||||
|
call.respondText { "hey dude ‼️ congrats on the post request" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.notarizedDelete() {
|
||||||
|
route(defaultPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
parameters = defaultParams
|
||||||
|
delete = DeleteInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
response {
|
||||||
|
responseCode(HttpStatusCode.NoContent)
|
||||||
|
responseType<Unit>()
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete {
|
||||||
|
call.respond(HttpStatusCode.NoContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.notarizedPatch() {
|
||||||
|
route(defaultPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
parameters = defaultParams
|
||||||
|
patch = PatchInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
request {
|
||||||
|
description("A Test request")
|
||||||
|
requestType<TestSimpleRequest>()
|
||||||
|
}
|
||||||
|
response {
|
||||||
|
responseCode(HttpStatusCode.Created)
|
||||||
|
responseType<TestCreatedResponse>()
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
patch {
|
||||||
|
call.respond(HttpStatusCode.Created) { TestCreatedResponse(123, "Nice!") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.notarizedHead() {
|
||||||
|
route(defaultPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
parameters = defaultParams
|
||||||
|
head = HeadInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
|
||||||
|
response {
|
||||||
|
description("great!")
|
||||||
|
responseCode(HttpStatusCode.Created)
|
||||||
|
responseType<Unit>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
head {
|
||||||
|
call.respond(HttpStatusCode.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.notarizedOptions() {
|
||||||
|
route(defaultPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
parameters = defaultParams
|
||||||
|
options = OptionsInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
response {
|
||||||
|
responseCode(HttpStatusCode.OK)
|
||||||
|
responseType<TestResponse>()
|
||||||
|
description("nice")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
options {
|
||||||
|
call.respond(HttpStatusCode.NoContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.complexRequest() {
|
||||||
|
route(rootPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
put = PutInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
request {
|
||||||
|
requestType<ComplexRequest>()
|
||||||
|
description("A Complex request")
|
||||||
|
}
|
||||||
|
response {
|
||||||
|
responseCode(HttpStatusCode.Created)
|
||||||
|
responseType<TestCreatedResponse>()
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
patch {
|
||||||
|
call.respond(HttpStatusCode.Created, TestCreatedResponse(123, "nice!"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.primitives() {
|
||||||
|
route(rootPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
put = PutInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
request {
|
||||||
|
requestType<Int>()
|
||||||
|
description("A Test Request")
|
||||||
|
}
|
||||||
|
response {
|
||||||
|
responseCode(HttpStatusCode.Created)
|
||||||
|
responseType<Boolean>()
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.returnsList() {
|
||||||
|
route(defaultPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
parameters = defaultParams
|
||||||
|
get = GetInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
response {
|
||||||
|
description("A Successful List-y Endeavor")
|
||||||
|
responseCode(HttpStatusCode.OK)
|
||||||
|
responseType<List<TestResponse>>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.nonRequiredParams() {
|
||||||
|
route("/optional") {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
parameters = listOf(
|
||||||
|
Parameter(
|
||||||
|
name = "notRequired",
|
||||||
|
`in` = Parameter.Location.query,
|
||||||
|
schema = TypeDefinition.STRING,
|
||||||
|
required = false,
|
||||||
|
),
|
||||||
|
Parameter(
|
||||||
|
name = "required",
|
||||||
|
`in` = Parameter.Location.query,
|
||||||
|
schema = TypeDefinition.STRING
|
||||||
|
)
|
||||||
|
)
|
||||||
|
get = GetInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
response {
|
||||||
|
responseType<Unit>()
|
||||||
|
description("Empty")
|
||||||
|
responseCode(HttpStatusCode.NoContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.simplePathParsing() {
|
||||||
|
route("/this") {
|
||||||
|
route("/is") {
|
||||||
|
route("/a") {
|
||||||
|
route("/complex") {
|
||||||
|
route("path") {
|
||||||
|
route("with/an/{id}") {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
get = GetInfo.builder {
|
||||||
|
parameters = listOf(
|
||||||
|
Parameter(
|
||||||
|
name = "id",
|
||||||
|
`in` = Parameter.Location.path,
|
||||||
|
schema = TypeDefinition.STRING
|
||||||
|
)
|
||||||
|
)
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
response {
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
responseCode(HttpStatusCode.OK)
|
||||||
|
responseType<TestResponse>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.rootRoute() {
|
||||||
|
route(rootPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
parameters = listOf(defaultParams.last())
|
||||||
|
get = GetInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
response {
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
responseCode(HttpStatusCode.OK)
|
||||||
|
responseType<TestResponse>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.nestedUnderRoot() {
|
||||||
|
route("/") {
|
||||||
|
route("/testerino") {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
get = GetInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
response {
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
responseCode(HttpStatusCode.OK)
|
||||||
|
responseType<TestResponse>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.trailingSlash() {
|
||||||
|
route("/test") {
|
||||||
|
route("/") {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
get = GetInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
response {
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
responseCode(HttpStatusCode.OK)
|
||||||
|
responseType<TestResponse>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.singleException() {
|
||||||
|
route(rootPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
get = GetInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
response {
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
responseCode(HttpStatusCode.OK)
|
||||||
|
responseType<TestResponse>()
|
||||||
|
}
|
||||||
|
canRespond {
|
||||||
|
description("Bad Things Happened")
|
||||||
|
responseCode(HttpStatusCode.BadRequest)
|
||||||
|
responseType<ExceptionResponse>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.multipleExceptions() {
|
||||||
|
route(rootPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
get = GetInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
response {
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
responseCode(HttpStatusCode.OK)
|
||||||
|
responseType<TestResponse>()
|
||||||
|
}
|
||||||
|
canRespond {
|
||||||
|
description("Bad Things Happened")
|
||||||
|
responseCode(HttpStatusCode.BadRequest)
|
||||||
|
responseType<ExceptionResponse>()
|
||||||
|
}
|
||||||
|
canRespond {
|
||||||
|
description("Access Denied")
|
||||||
|
responseCode(HttpStatusCode.Forbidden)
|
||||||
|
responseType<ExceptionResponse>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.polymorphicException() {
|
||||||
|
route(rootPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
get = GetInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
response {
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
responseCode(HttpStatusCode.OK)
|
||||||
|
responseType<TestResponse>()
|
||||||
|
}
|
||||||
|
canRespond {
|
||||||
|
description("Bad Things Happened")
|
||||||
|
responseCode(HttpStatusCode.InternalServerError)
|
||||||
|
responseType<FlibbityGibbit>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.genericException() {
|
||||||
|
route(rootPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
get = GetInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
response {
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
responseCode(HttpStatusCode.OK)
|
||||||
|
responseType<TestResponse>()
|
||||||
|
}
|
||||||
|
canRespond {
|
||||||
|
description("Bad Things Happened")
|
||||||
|
responseCode(HttpStatusCode.BadRequest)
|
||||||
|
responseType<Flibbity<String>>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.reqRespExamples() {
|
||||||
|
route(rootPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
post = PostInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
request {
|
||||||
|
description(defaultRequestDescription)
|
||||||
|
requestType<TestRequest>()
|
||||||
|
examples(
|
||||||
|
"Testerina" to TestRequest(TestNested("asdf"), 1.5, emptyList())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
response {
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
responseCode(HttpStatusCode.OK)
|
||||||
|
responseType<TestResponse>()
|
||||||
|
examples(
|
||||||
|
"Testerino" to TestResponse("Heya")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Routing.exampleParams() = basicGetGenerator<TestResponse>(
|
||||||
|
params = listOf(
|
||||||
|
Parameter(
|
||||||
|
name = "id",
|
||||||
|
`in` = Parameter.Location.path,
|
||||||
|
schema = TypeDefinition.STRING,
|
||||||
|
examples = mapOf(
|
||||||
|
"foo" to Parameter.Example("testing")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fun Routing.defaultParameter() = basicGetGenerator<TestResponse>(
|
||||||
|
params = listOf(
|
||||||
|
Parameter(
|
||||||
|
name = "id",
|
||||||
|
`in` = Parameter.Location.path,
|
||||||
|
schema = TypeDefinition.STRING.withDefault("IDK")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fun Routing.requiredParams() = basicGetGenerator<TestResponse>(
|
||||||
|
params = listOf(
|
||||||
|
Parameter(
|
||||||
|
name = "id",
|
||||||
|
`in` = Parameter.Location.path,
|
||||||
|
schema = TypeDefinition.STRING
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fun Routing.nonRequiredParam() = basicGetGenerator<TestResponse>(
|
||||||
|
params = listOf(
|
||||||
|
Parameter(
|
||||||
|
name = "id",
|
||||||
|
`in` = Parameter.Location.query,
|
||||||
|
schema = TypeDefinition.STRING,
|
||||||
|
required = false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fun Routing.defaultField() = basicGetGenerator<DefaultField>()
|
||||||
|
|
||||||
|
fun Routing.nullableField() = basicGetGenerator<NullableField>()
|
||||||
|
|
||||||
|
fun Routing.polymorphicResponse() = basicGetGenerator<FlibbityGibbit>()
|
||||||
|
|
||||||
|
fun Routing.polymorphicCollectionResponse() = basicGetGenerator<List<FlibbityGibbit>>()
|
||||||
|
|
||||||
|
fun Routing.polymorphicMapResponse() = basicGetGenerator<Map<String, FlibbityGibbit>>()
|
||||||
|
|
||||||
|
fun Routing.simpleGenericResponse() = basicGetGenerator<Gibbity<String>>()
|
||||||
|
|
||||||
|
fun Routing.nestedGenericResponse() = basicGetGenerator<Gibbity<Map<String, String>>>()
|
||||||
|
|
||||||
|
fun Routing.genericPolymorphicResponse() = basicGetGenerator<Flibbity<Double>>()
|
||||||
|
|
||||||
|
fun Routing.genericPolymorphicResponseMultipleImpls() = basicGetGenerator<Flibbity<FlibbityGibbit>>()
|
||||||
|
|
||||||
|
fun Routing.withOperationId() = basicGetGenerator<TestResponse>(operationId = "getThisDude")
|
||||||
|
|
||||||
|
fun Routing.nullableNestedObject() = basicGetGenerator<ProfileUpdateRequest>()
|
||||||
|
|
||||||
|
fun Routing.nullableEnumField() = basicGetGenerator<NullableEnum>()
|
||||||
|
|
||||||
|
fun Routing.dateTimeString() = basicGetGenerator<DateTimeString>()
|
||||||
|
|
||||||
|
fun Routing.headerParameter() = basicGetGenerator<TestResponse>( params = listOf(
|
||||||
|
Parameter(
|
||||||
|
name = "X-User-Email",
|
||||||
|
`in` = Parameter.Location.header,
|
||||||
|
schema = TypeDefinition.STRING,
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
))
|
||||||
|
|
||||||
|
fun Routing.simpleRecursive() = basicGetGenerator<ColumnSchema>()
|
||||||
|
|
||||||
|
private inline fun <reified T> Routing.basicGetGenerator(
|
||||||
|
params: List<Parameter> = emptyList(),
|
||||||
|
operationId: String? = null
|
||||||
|
) {
|
||||||
|
route(rootPath) {
|
||||||
|
install(NotarizedRoute()) {
|
||||||
|
get = GetInfo.builder {
|
||||||
|
summary(defaultPathSummary)
|
||||||
|
description(defaultPathDescription)
|
||||||
|
operationId?.let { operationId(it) }
|
||||||
|
parameters = params
|
||||||
|
response {
|
||||||
|
description(defaultResponseDescription)
|
||||||
|
responseCode(HttpStatusCode.OK)
|
||||||
|
responseType<T>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,33 +27,12 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test": {
|
"/test/{a}": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Another get test",
|
"summary": "Great Summary!",
|
||||||
"description": "testing more",
|
"description": "testing more",
|
||||||
"operationId": "getTest",
|
"parameters": [],
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "a",
|
|
||||||
"in": "path",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "aa",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"format": "int32",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A Successful Endeavor",
|
"description": "A Successful Endeavor",
|
||||||
@ -66,12 +46,35 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "a",
|
||||||
|
"in": "path",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "aa",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -79,8 +82,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,38 +27,18 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test": {
|
"/test/{a}": {
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Test post endpoint",
|
"summary": "Great Summary!",
|
||||||
"description": "Post your tests here!",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [],
|
||||||
{
|
|
||||||
"name": "a",
|
|
||||||
"in": "path",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "aa",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"format": "int32",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
"description": "A Test request",
|
"description": "A Test request",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/components/schemas/TestRequest"
|
"$ref": "#/components/schemas/TestSimpleRequest"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -76,61 +57,64 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "a",
|
||||||
|
"in": "path",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "aa",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestRequest": {
|
|
||||||
"properties": {
|
|
||||||
"aaa": {
|
|
||||||
"items": {
|
|
||||||
"format": "int64",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"type": "array"
|
|
||||||
},
|
|
||||||
"b": {
|
|
||||||
"format": "double",
|
|
||||||
"type": "number"
|
|
||||||
},
|
|
||||||
"field_name": {
|
|
||||||
"$ref": "#/components/schemas/TestNested"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"field_name",
|
|
||||||
"b",
|
|
||||||
"aaa"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"TestNested": {
|
|
||||||
"properties": {
|
|
||||||
"nesty": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"nesty"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"TestCreatedResponse": {
|
"TestCreatedResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"id": {
|
"id": {
|
||||||
"format": "int32",
|
"type": "number",
|
||||||
"type": "integer"
|
"format": "int32"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"c",
|
||||||
"c"
|
"id"
|
||||||
],
|
]
|
||||||
"type": "object"
|
},
|
||||||
|
"TestSimpleRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"a": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"b": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"a",
|
||||||
|
"b"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,38 +27,18 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test": {
|
"/test/{a}": {
|
||||||
"put": {
|
"put": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Test put endpoint",
|
"summary": "Great Summary!",
|
||||||
"description": "Put your tests here!",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [],
|
||||||
{
|
|
||||||
"name": "a",
|
|
||||||
"in": "path",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "aa",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"format": "int32",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
"description": "A Test request",
|
"description": "A Test request",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/components/schemas/TestRequest"
|
"$ref": "#/components/schemas/TestSimpleRequest"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -76,61 +57,64 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "a",
|
||||||
|
"in": "path",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "aa",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestRequest": {
|
|
||||||
"properties": {
|
|
||||||
"aaa": {
|
|
||||||
"items": {
|
|
||||||
"format": "int64",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"type": "array"
|
|
||||||
},
|
|
||||||
"b": {
|
|
||||||
"format": "double",
|
|
||||||
"type": "number"
|
|
||||||
},
|
|
||||||
"field_name": {
|
|
||||||
"$ref": "#/components/schemas/TestNested"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"field_name",
|
|
||||||
"b",
|
|
||||||
"aaa"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"TestNested": {
|
|
||||||
"properties": {
|
|
||||||
"nesty": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"nesty"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"TestCreatedResponse": {
|
"TestCreatedResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"id": {
|
"id": {
|
||||||
"format": "int32",
|
"type": "number",
|
||||||
"type": "integer"
|
"format": "int32"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"c",
|
||||||
"c"
|
"id"
|
||||||
],
|
]
|
||||||
"type": "object"
|
},
|
||||||
|
"TestSimpleRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"a": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"b": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"a",
|
||||||
|
"b"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,47 +27,45 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/polymorphic": {
|
"/test/{a}": {
|
||||||
"get": {
|
"delete": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Single Generic",
|
"summary": "Great Summary!",
|
||||||
"description": "Simple generic data class",
|
"description": "testing more",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"204": {
|
||||||
"description": "A successful endeavor",
|
"description": "A Successful Endeavor"
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/TestGeneric-Int"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
}
|
"parameters": [
|
||||||
},
|
{
|
||||||
"components": {
|
"name": "a",
|
||||||
"schemas": {
|
"in": "path",
|
||||||
"TestGeneric-Int": {
|
"schema": {
|
||||||
"properties": {
|
|
||||||
"messy": {
|
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"potato": {
|
"required": true,
|
||||||
"format": "int32",
|
"deprecated": false
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"required": [
|
{
|
||||||
"messy",
|
"name": "aa",
|
||||||
"potato"
|
"in": "query",
|
||||||
],
|
"schema": {
|
||||||
"type": "object"
|
"type": "number",
|
||||||
}
|
"format": "int32"
|
||||||
},
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"webhooks": {},
|
||||||
|
"components": {
|
||||||
|
"schemas": {},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
||||||
},
|
},
|
||||||
"security": [],
|
"security": [],
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,18 +27,18 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test": {
|
"/test/{a}": {
|
||||||
"patch": {
|
"patch": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Test patch endpoint",
|
"summary": "Great Summary!",
|
||||||
"description": "patch your tests here!",
|
"description": "testing more",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
"description": "A Test request",
|
"description": "A Test request",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/components/schemas/TestRequest"
|
"$ref": "#/components/schemas/TestSimpleRequest"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -49,63 +50,71 @@
|
|||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/components/schemas/TestResponse"
|
"$ref": "#/components/schemas/TestCreatedResponse"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "a",
|
||||||
|
"in": "path",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "aa",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestRequest": {
|
"TestCreatedResponse": {
|
||||||
"properties": {
|
"type": "object",
|
||||||
"aaa": {
|
|
||||||
"items": {
|
|
||||||
"format": "int64",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"type": "array"
|
|
||||||
},
|
|
||||||
"b": {
|
|
||||||
"format": "double",
|
|
||||||
"type": "number"
|
|
||||||
},
|
|
||||||
"field_name": {
|
|
||||||
"$ref": "#/components/schemas/TestNested"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"field_name",
|
|
||||||
"b",
|
|
||||||
"aaa"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"TestNested": {
|
|
||||||
"properties": {
|
|
||||||
"nesty": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"nesty"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"TestResponse": {
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c",
|
||||||
],
|
"id"
|
||||||
"type": "object"
|
]
|
||||||
|
},
|
||||||
|
"TestSimpleRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"a": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"b": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"a",
|
||||||
|
"b"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,21 +27,43 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test": {
|
"/test/{a}": {
|
||||||
"head": {
|
"head": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Test head endpoint",
|
"summary": "Great Summary!",
|
||||||
"description": "head test 💀",
|
"description": "testing more",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"201": {
|
||||||
"description": "great!"
|
"description": "great!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "a",
|
||||||
|
"in": "path",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "aa",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {},
|
"schemas": {},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,32 +27,12 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test": {
|
"/test/{a}": {
|
||||||
"options": {
|
"options": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Test options",
|
"summary": "Great Summary!",
|
||||||
"description": "endpoint of options",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [],
|
||||||
{
|
|
||||||
"name": "a",
|
|
||||||
"in": "path",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "aa",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"format": "int32",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "nice",
|
"description": "nice",
|
||||||
@ -65,12 +46,35 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "a",
|
||||||
|
"in": "path",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "aa",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -78,8 +82,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,11 +27,11 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test": {
|
"/": {
|
||||||
"put": {
|
"put": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Test put endpoint",
|
"summary": "Great Summary!",
|
||||||
"description": "Put your tests here!",
|
"description": "testing more",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
"description": "A Complex request",
|
"description": "A Complex request",
|
||||||
@ -56,14 +57,33 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"ComplexRequest": {
|
"TestCreatedResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"amazing_field": {
|
"c": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"c",
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ComplexRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"amazingField": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"org": {
|
"org": {
|
||||||
@ -77,13 +97,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
"amazingField",
|
||||||
"org",
|
"org",
|
||||||
"amazing_field",
|
|
||||||
"tables"
|
"tables"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
},
|
},
|
||||||
"NestedComplexItem": {
|
"NestedComplexItem": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"alias": {
|
"alias": {
|
||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
@ -96,44 +116,23 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"name",
|
"alias",
|
||||||
"alias"
|
"name"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
},
|
},
|
||||||
"CrazyItem": {
|
"CrazyItem": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"enumeration": {
|
"enumeration": {
|
||||||
"$ref": "#/components/schemas/SimpleEnum"
|
"enum": [
|
||||||
|
"ONE",
|
||||||
|
"TWO"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"enumeration"
|
"enumeration"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"SimpleEnum": {
|
|
||||||
"enum": [
|
|
||||||
"ONE",
|
|
||||||
"TWO"
|
|
||||||
],
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"TestCreatedResponse": {
|
|
||||||
"properties": {
|
|
||||||
"c": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"id": {
|
|
||||||
"format": "int32",
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"id",
|
|
||||||
"c"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,19 +27,18 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test": {
|
"/": {
|
||||||
"put": {
|
"put": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Test put endpoint",
|
"summary": "Great Summary!",
|
||||||
"description": "Put your tests here!",
|
"description": "testing more",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
"description": "A Test request",
|
"description": "A Test Request",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"format": "int32",
|
"$ref": "#/components/schemas/Int"
|
||||||
"type": "integer"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -50,18 +50,28 @@
|
|||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "boolean"
|
"$ref": "#/components/schemas/Boolean"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {},
|
"schemas": {
|
||||||
|
"Boolean": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"Int": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
||||||
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
||||||
},
|
},
|
||||||
"security": [],
|
"security": [],
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,54 +27,54 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test": {
|
"/test/{a}": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Another get test",
|
"summary": "Great Summary!",
|
||||||
"description": "testing more",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [],
|
||||||
{
|
|
||||||
"name": "a",
|
|
||||||
"in": "path",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "aa",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"format": "int32",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A Successful List-y Endeavor",
|
"description": "A Successful List-y Endeavor",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"items": {
|
"$ref": "#/components/schemas/List-TestResponse"
|
||||||
"$ref": "#/components/schemas/TestResponse"
|
|
||||||
},
|
|
||||||
"type": "array"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "a",
|
||||||
|
"in": "path",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "aa",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -81,8 +82,13 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
},
|
||||||
|
"List-TestResponse": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/TestResponse"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,41 +27,42 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/optional": {
|
"/optional": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "No request params and response body",
|
"summary": "Great Summary!",
|
||||||
"description": "testing more",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [],
|
||||||
{
|
|
||||||
"name": "notRequired",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"type": "string",
|
|
||||||
"nullable": true
|
|
||||||
},
|
|
||||||
"required": false,
|
|
||||||
"deprecated": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "required",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
"responses": {
|
||||||
"204": {
|
"204": {
|
||||||
"description": "Empty"
|
"description": "Empty"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "notRequired",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"required": false,
|
||||||
|
"deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "required",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {},
|
"schemas": {},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -29,27 +30,17 @@
|
|||||||
"/this/is/a/complex/path/with/an/{id}": {
|
"/this/is/a/complex/path/with/an/{id}": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Another get test",
|
"summary": "Great Summary!",
|
||||||
"description": "testing more",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"name": "a",
|
"name": "id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"required": true,
|
"required": true,
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "aa",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"format": "int32",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@ -65,12 +56,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -78,8 +72,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,32 +27,12 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/testerino": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Another get test",
|
"summary": "Great Summary!",
|
||||||
"description": "testing more",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [],
|
||||||
{
|
|
||||||
"name": "a",
|
|
||||||
"in": "path",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "aa",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"format": "int32",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A Successful Endeavor",
|
"description": "A Successful Endeavor",
|
||||||
@ -65,12 +46,26 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "aa",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"deprecated": false
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -78,8 +73,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,26 +27,15 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/required_param": {
|
"/testerino": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "default param",
|
"summary": "Great Summary!",
|
||||||
"description": "Cool stuff",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [],
|
||||||
{
|
|
||||||
"name": "b",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"type": "string",
|
|
||||||
"default": "heyo"
|
|
||||||
},
|
|
||||||
"required": false,
|
|
||||||
"deprecated": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A successful endeavor",
|
"description": "A Successful Endeavor",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
@ -56,12 +46,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -69,8 +62,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
72
core/src/test/resources/T0015__trailing_slash.json
Normal file
72
core/src/test/resources/T0015__trailing_slash.json
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"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": {
|
||||||
|
"/test/": {
|
||||||
|
"get": {
|
||||||
|
"tags": [],
|
||||||
|
"summary": "Great Summary!",
|
||||||
|
"description": "testing more",
|
||||||
|
"parameters": [],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A Successful Endeavor",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/TestResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deprecated": false
|
||||||
|
},
|
||||||
|
"parameters": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"webhooks": {},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"c": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"securitySchemes": {}
|
||||||
|
},
|
||||||
|
"security": [],
|
||||||
|
"tags": []
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,32 +27,12 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Another get test",
|
"summary": "Great Summary!",
|
||||||
"description": "testing more",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [],
|
||||||
{
|
|
||||||
"name": "a",
|
|
||||||
"in": "path",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "aa",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"format": "int32",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A Successful Endeavor",
|
"description": "A Successful Endeavor",
|
||||||
@ -75,12 +56,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -88,10 +72,10 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
},
|
},
|
||||||
"ExceptionResponse": {
|
"ExceptionResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"message": {
|
"message": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -99,8 +83,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"message"
|
"message"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,32 +27,12 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Another get test",
|
"summary": "Great Summary!",
|
||||||
"description": "testing more",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [],
|
||||||
{
|
|
||||||
"name": "a",
|
|
||||||
"in": "path",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "aa",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"format": "int32",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A Successful Endeavor",
|
"description": "A Successful Endeavor",
|
||||||
@ -63,16 +44,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"403": {
|
|
||||||
"description": "Access Denied",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/ExceptionResponse"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"400": {
|
"400": {
|
||||||
"description": "Bad Things Happened",
|
"description": "Bad Things Happened",
|
||||||
"content": {
|
"content": {
|
||||||
@ -82,15 +53,28 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"403": {
|
||||||
|
"description": "Access Denied",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ExceptionResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -98,10 +82,10 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
},
|
},
|
||||||
"ExceptionResponse": {
|
"ExceptionResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"message": {
|
"message": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -109,8 +93,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"message"
|
"message"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,32 +27,12 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Another get test",
|
"summary": "Great Summary!",
|
||||||
"description": "testing more",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [],
|
||||||
{
|
|
||||||
"name": "a",
|
|
||||||
"in": "path",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "aa",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"format": "int32",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A Successful Endeavor",
|
"description": "A Successful Endeavor",
|
||||||
@ -63,31 +44,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"501": {
|
"500": {
|
||||||
"description": "The Gibbits are ANGRY",
|
"description": "Bad Things Happened",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"anyOf": [
|
"$ref": "#/components/schemas/FlibbityGibbit"
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/SimpleGibbit"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/ComplexGibbit"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -95,10 +72,30 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
},
|
||||||
|
"ComplexGibbit": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"b": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"c": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"z": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"b",
|
||||||
|
"c",
|
||||||
|
"z"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"SimpleGibbit": {
|
"SimpleGibbit": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"a": {
|
"a": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -109,27 +106,17 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"a"
|
"a"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
},
|
},
|
||||||
"ComplexGibbit": {
|
"FlibbityGibbit": {
|
||||||
"properties": {
|
"anyOf": [
|
||||||
"b": {
|
{
|
||||||
"type": "string"
|
"$ref": "#/components/schemas/ComplexGibbit"
|
||||||
},
|
},
|
||||||
"c": {
|
{
|
||||||
"format": "int32",
|
"$ref": "#/components/schemas/SimpleGibbit"
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"z": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
}
|
||||||
},
|
]
|
||||||
"required": [
|
|
||||||
"b",
|
|
||||||
"c"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,32 +27,12 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Another get test",
|
"summary": "Great Summary!",
|
||||||
"description": "testing more",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [],
|
||||||
{
|
|
||||||
"name": "a",
|
|
||||||
"in": "path",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "aa",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"format": "int32",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A Successful Endeavor",
|
"description": "A Successful Endeavor",
|
||||||
@ -64,30 +45,26 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
"description": "Wow serious things went wrong",
|
"description": "Bad Things Happened",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"anyOf": [
|
"$ref": "#/components/schemas/Flibbity-String"
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/Gibbity-String"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/Bibbity-String"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -95,21 +72,10 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"Gibbity-String": {
|
|
||||||
"properties": {
|
|
||||||
"a": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"a"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
},
|
||||||
"Bibbity-String": {
|
"Bibbity-String": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"b": {
|
"b": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -121,8 +87,28 @@
|
|||||||
"required": [
|
"required": [
|
||||||
"b",
|
"b",
|
||||||
"f"
|
"f"
|
||||||
],
|
]
|
||||||
"type": "object"
|
},
|
||||||
|
"Gibbity-String": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"a": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"a"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Flibbity-String": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Bibbity-String"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Gibbity-String"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,39 +27,28 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/examples": {
|
"/": {
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Example Parameters",
|
"summary": "Great Summary!",
|
||||||
"description": "A test for setting parameter examples",
|
"description": "testing more",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
"description": "Test",
|
"description": "You gotta send it",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/components/schemas/TestRequest"
|
"$ref": "#/components/schemas/TestRequest"
|
||||||
},
|
},
|
||||||
"examples": {
|
"examples": {
|
||||||
"one": {
|
"Testerina": {
|
||||||
"value": {
|
"value": {
|
||||||
"fieldName": {
|
"fieldName": {
|
||||||
"nesty": "hey"
|
"nesty": "asdf"
|
||||||
},
|
},
|
||||||
"b": 4.0,
|
"b": 1.5,
|
||||||
"aaa": []
|
"aaa": []
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"two": {
|
|
||||||
"value": {
|
|
||||||
"fieldName": {
|
|
||||||
"nesty": "hello"
|
|
||||||
},
|
|
||||||
"b": 3.8,
|
|
||||||
"aaa": [
|
|
||||||
31324234
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,17 +56,17 @@
|
|||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
"responses": {
|
"responses": {
|
||||||
"201": {
|
"200": {
|
||||||
"description": "nice",
|
"description": "A Successful Endeavor",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/components/schemas/TestResponse"
|
"$ref": "#/components/schemas/TestResponse"
|
||||||
},
|
},
|
||||||
"examples": {
|
"examples": {
|
||||||
"test": {
|
"Testerino": {
|
||||||
"value": {
|
"value": {
|
||||||
"c": "spud"
|
"c": "Heya"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,47 +75,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestRequest": {
|
|
||||||
"properties": {
|
|
||||||
"aaa": {
|
|
||||||
"items": {
|
|
||||||
"format": "int64",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"type": "array"
|
|
||||||
},
|
|
||||||
"b": {
|
|
||||||
"format": "double",
|
|
||||||
"type": "number"
|
|
||||||
},
|
|
||||||
"field_name": {
|
|
||||||
"$ref": "#/components/schemas/TestNested"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"field_name",
|
|
||||||
"b",
|
|
||||||
"aaa"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"TestNested": {
|
|
||||||
"properties": {
|
|
||||||
"nesty": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"nesty"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -133,8 +91,42 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
},
|
||||||
|
"TestRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"aaa": {
|
||||||
|
"items": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"b": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
},
|
||||||
|
"fieldName": {
|
||||||
|
"$ref": "#/components/schemas/TestNested"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"aaa",
|
||||||
|
"b",
|
||||||
|
"fieldName"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"TestNested": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"nesty": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"nesty"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,30 +27,25 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Another get test",
|
"summary": "Great Summary!",
|
||||||
"description": "testing more",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"name": "a",
|
"name": "id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"required": true,
|
"required": true,
|
||||||
"deprecated": false
|
"deprecated": false,
|
||||||
},
|
"examples": {
|
||||||
{
|
"foo": {
|
||||||
"name": "aa",
|
"value": "testing"
|
||||||
"in": "query",
|
}
|
||||||
"schema": {
|
}
|
||||||
"format": "int32",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@ -65,12 +61,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -78,8 +77,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,27 +27,18 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Another get test",
|
"summary": "Great Summary!",
|
||||||
"description": "testing more",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"name": "a",
|
"name": "id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
},
|
"default": "IDK"
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "aa",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"format": "int32",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
},
|
||||||
"required": true,
|
"required": true,
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
@ -65,12 +57,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -78,8 +73,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -29,27 +30,17 @@
|
|||||||
"/": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Another get test",
|
"summary": "Great Summary!",
|
||||||
"description": "testing more",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"name": "a",
|
"name": "id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"required": true,
|
"required": true,
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "aa",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"format": "int32",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@ -65,12 +56,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -78,8 +72,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,25 +27,25 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/required_param": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "required param",
|
"summary": "Great Summary!",
|
||||||
"description": "Cool stuff",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"name": "a",
|
"name": "id",
|
||||||
"in": "query",
|
"in": "query",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"required": true,
|
"required": false,
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A successful endeavor",
|
"description": "A Successful Endeavor",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
@ -55,12 +56,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -68,8 +72,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,45 +27,46 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/constrained_int": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Constrained int field",
|
"summary": "Great Summary!",
|
||||||
"description": "Cool stuff",
|
"description": "testing more",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A successful endeavor",
|
"description": "A Successful Endeavor",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/components/schemas/MinMaxDouble"
|
"$ref": "#/components/schemas/DefaultField"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"MinMaxDouble": {
|
"DefaultField": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"a": {
|
"a": {
|
||||||
"format": "double",
|
"type": "string"
|
||||||
|
},
|
||||||
|
"b": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"minimum": 5.5,
|
"format": "int32"
|
||||||
"maximum": 13.37,
|
|
||||||
"exclusiveMinimum": false,
|
|
||||||
"exclusiveMaximum": false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"a"
|
"b"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,45 +27,47 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/constrained_int": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Constrained int field",
|
"summary": "Great Summary!",
|
||||||
"description": "Cool stuff",
|
"description": "testing more",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A successful endeavor",
|
"description": "A Successful Endeavor",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/components/schemas/ExclusiveMinMax"
|
"$ref": "#/components/schemas/NullableField"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"ExclusiveMinMax": {
|
"NullableField": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"a": {
|
"a": {
|
||||||
"format": "int32",
|
"oneOf": [
|
||||||
"type": "integer",
|
{
|
||||||
"minimum": 5,
|
"type": "null"
|
||||||
"maximum": 100,
|
},
|
||||||
"exclusiveMinimum": true,
|
{
|
||||||
"exclusiveMaximum": true
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": []
|
||||||
"a"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,41 +27,54 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/polymorphiclist": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Oh so many gibbits",
|
"summary": "Great Summary!",
|
||||||
"description": "Polymorphic list response",
|
"description": "testing more",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A successful endeavor",
|
"description": "A Successful Endeavor",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"items": {
|
"$ref": "#/components/schemas/FlibbityGibbit"
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/SimpleGibbit"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/ComplexGibbit"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"type": "array"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
|
"ComplexGibbit": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"b": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"c": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"z": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"b",
|
||||||
|
"c",
|
||||||
|
"z"
|
||||||
|
]
|
||||||
|
},
|
||||||
"SimpleGibbit": {
|
"SimpleGibbit": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"a": {
|
"a": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -71,27 +85,17 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"a"
|
"a"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
},
|
},
|
||||||
"ComplexGibbit": {
|
"FlibbityGibbit": {
|
||||||
"properties": {
|
"anyOf": [
|
||||||
"b": {
|
{
|
||||||
"type": "string"
|
"$ref": "#/components/schemas/ComplexGibbit"
|
||||||
},
|
},
|
||||||
"c": {
|
{
|
||||||
"format": "int32",
|
"$ref": "#/components/schemas/SimpleGibbit"
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"z": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
}
|
||||||
},
|
]
|
||||||
"required": [
|
|
||||||
"b",
|
|
||||||
"c"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,41 +27,54 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/polymorphicmap": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "By gawd that's a lot of gibbits",
|
"summary": "Great Summary!",
|
||||||
"description": "Polymorphic list response",
|
"description": "testing more",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A successful endeavor",
|
"description": "A Successful Endeavor",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"additionalProperties": {
|
"$ref": "#/components/schemas/List-FlibbityGibbit"
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/SimpleGibbit"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/ComplexGibbit"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
|
"ComplexGibbit": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"b": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"c": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"z": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"b",
|
||||||
|
"c",
|
||||||
|
"z"
|
||||||
|
]
|
||||||
|
},
|
||||||
"SimpleGibbit": {
|
"SimpleGibbit": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"a": {
|
"a": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -71,27 +85,20 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"a"
|
"a"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
},
|
},
|
||||||
"ComplexGibbit": {
|
"List-FlibbityGibbit": {
|
||||||
"properties": {
|
"items": {
|
||||||
"b": {
|
"anyOf": [
|
||||||
"type": "string"
|
{
|
||||||
},
|
"$ref": "#/components/schemas/ComplexGibbit"
|
||||||
"c": {
|
},
|
||||||
"format": "int32",
|
{
|
||||||
"type": "integer"
|
"$ref": "#/components/schemas/SimpleGibbit"
|
||||||
},
|
}
|
||||||
"z": {
|
]
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"required": [
|
"type": "array"
|
||||||
"b",
|
|
||||||
"c"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,38 +27,54 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/polymorphic": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "All the gibbits",
|
"summary": "Great Summary!",
|
||||||
"description": "Polymorphic response",
|
"description": "testing more",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A successful endeavor",
|
"description": "A Successful Endeavor",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"anyOf": [
|
"$ref": "#/components/schemas/Map-String-FlibbityGibbit"
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/SimpleGibbit"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/ComplexGibbit"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
|
"ComplexGibbit": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"b": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"c": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"z": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"b",
|
||||||
|
"c",
|
||||||
|
"z"
|
||||||
|
]
|
||||||
|
},
|
||||||
"SimpleGibbit": {
|
"SimpleGibbit": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"a": {
|
"a": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -68,26 +85,19 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"a"
|
"a"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
},
|
},
|
||||||
"ComplexGibbit": {
|
"Map-String-FlibbityGibbit": {
|
||||||
"properties": {
|
"additionalProperties": {
|
||||||
"b": {
|
"anyOf": [
|
||||||
"type": "string"
|
{
|
||||||
},
|
"$ref": "#/components/schemas/ComplexGibbit"
|
||||||
"c": {
|
},
|
||||||
"format": "int32",
|
{
|
||||||
"type": "integer"
|
"$ref": "#/components/schemas/SimpleGibbit"
|
||||||
},
|
}
|
||||||
"z": {
|
]
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"required": [
|
|
||||||
"b",
|
|
||||||
"c"
|
|
||||||
],
|
|
||||||
"type": "object"
|
"type": "object"
|
||||||
}
|
}
|
||||||
},
|
},
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,31 +27,34 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/date_time_format": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Date time string test",
|
"summary": "Great Summary!",
|
||||||
"description": "Cool stuff",
|
"description": "testing more",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A successful endeavor",
|
"description": "A Successful Endeavor",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/components/schemas/DateTimeString"
|
"$ref": "#/components/schemas/Gibbity-String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"DateTimeString": {
|
"Gibbity-String": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"a": {
|
"a": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -58,8 +62,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"a"
|
"a"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,45 +27,45 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/required_param": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "required param",
|
"summary": "Great Summary!",
|
||||||
"description": "Cool stuff",
|
"description": "testing more",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A successful endeavor",
|
"description": "A Successful Endeavor",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/components/schemas/MinMaxArray"
|
"$ref": "#/components/schemas/Gibbity-Map"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"MinMaxArray": {
|
"Gibbity-Map": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"a": {
|
"a": {
|
||||||
"items": {
|
"additionalProperties": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"minItems": 1,
|
"type": "object"
|
||||||
"maxItems": 10,
|
|
||||||
"type": "array"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"a"
|
"a"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,73 +27,69 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/polymorphic": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "More flibbity",
|
"summary": "Great Summary!",
|
||||||
"description": "Polymorphic with generics",
|
"description": "testing more",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A successful endeavor",
|
"description": "A Successful Endeavor",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"anyOf": [
|
"$ref": "#/components/schemas/Flibbity-Double"
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/Gibbity-TestNested"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/Bibbity-TestNested"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"Gibbity-TestNested": {
|
"Bibbity-Double": {
|
||||||
"properties": {
|
"type": "object",
|
||||||
"a": {
|
|
||||||
"$ref": "#/components/schemas/TestNested"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"a"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"TestNested": {
|
|
||||||
"properties": {
|
|
||||||
"nesty": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"nesty"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"Bibbity-TestNested": {
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"b": {
|
"b": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"f": {
|
"f": {
|
||||||
"$ref": "#/components/schemas/TestNested"
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"b",
|
"b",
|
||||||
"f"
|
"f"
|
||||||
],
|
]
|
||||||
"type": "object"
|
},
|
||||||
|
"Gibbity-Double": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"a": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "double"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"a"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Flibbity-Double": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Bibbity-Double"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Gibbity-Double"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
145
core/src/test/resources/T0033__crazy_polymorphic_example.json
Normal file
145
core/src/test/resources/T0033__crazy_polymorphic_example.json
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
{
|
||||||
|
"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": {
|
||||||
|
"/": {
|
||||||
|
"get": {
|
||||||
|
"tags": [],
|
||||||
|
"summary": "Great Summary!",
|
||||||
|
"description": "testing more",
|
||||||
|
"parameters": [],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A Successful Endeavor",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Flibbity-FlibbityGibbit"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deprecated": false
|
||||||
|
},
|
||||||
|
"parameters": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"webhooks": {},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"ComplexGibbit": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"b": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"c": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"z": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"b",
|
||||||
|
"c",
|
||||||
|
"z"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"SimpleGibbit": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"a": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"z": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"a"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Bibbity-FlibbityGibbit": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"b": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"f": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/ComplexGibbit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/SimpleGibbit"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"b",
|
||||||
|
"f"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Gibbity-FlibbityGibbit": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"a": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/ComplexGibbit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/SimpleGibbit"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"a"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Flibbity-FlibbityGibbit": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Bibbity-FlibbityGibbit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Gibbity-FlibbityGibbit"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"securitySchemes": {}
|
||||||
|
},
|
||||||
|
"security": [],
|
||||||
|
"tags": []
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,26 +27,16 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/required_param": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "required param",
|
"summary": "Great Summary!",
|
||||||
"description": "Cool stuff",
|
"description": "testing more",
|
||||||
"parameters": [
|
"operationId": "getThisDude",
|
||||||
{
|
"parameters": [],
|
||||||
"name": "a",
|
|
||||||
"in": "query",
|
|
||||||
"schema": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "password"
|
|
||||||
},
|
|
||||||
"required": true,
|
|
||||||
"deprecated": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A successful endeavor",
|
"description": "A Successful Endeavor",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
@ -56,12 +47,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -69,8 +63,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,14 +27,14 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/with_header": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "testing header stuffs",
|
"summary": "Great Summary!",
|
||||||
"description": "Good for many things",
|
"description": "testing more",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"name": "X-UserEmail",
|
"name": "X-User-Email",
|
||||||
"in": "header",
|
"in": "header",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -44,7 +45,7 @@
|
|||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A successful endeavor",
|
"description": "A Successful Endeavor",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
@ -55,12 +56,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"TestResponse": {
|
"TestResponse": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"c": {
|
"c": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -68,8 +72,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"c"
|
"c"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
121
core/src/test/resources/T0036__nullable_fields.json
Normal file
121
core/src/test/resources/T0036__nullable_fields.json
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
{
|
||||||
|
"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": {
|
||||||
|
"/": {
|
||||||
|
"get": {
|
||||||
|
"tags": [],
|
||||||
|
"summary": "Great Summary!",
|
||||||
|
"description": "testing more",
|
||||||
|
"parameters": [],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A Successful Endeavor",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ProfileUpdateRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deprecated": false
|
||||||
|
},
|
||||||
|
"parameters": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"webhooks": {},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"ProfileUpdateRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"metadata": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"isPrivate": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"otherThing": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"mood": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"viewCount": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"securitySchemes": {}
|
||||||
|
},
|
||||||
|
"security": [],
|
||||||
|
"tags": []
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,15 +27,15 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/nullable/enum": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Has a nullable enum field",
|
"summary": "Great Summary!",
|
||||||
"description": "should still work!",
|
"description": "testing more",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A successful endeavor",
|
"description": "A Successful Endeavor",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
@ -45,25 +46,31 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"NullableEnum": {
|
"NullableEnum": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"a": {
|
"a": {
|
||||||
"$ref": "#/components/schemas/TestEnum"
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enum": [
|
||||||
|
"YES",
|
||||||
|
"NO"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object"
|
"required": []
|
||||||
},
|
|
||||||
"TestEnum": {
|
|
||||||
"enum": [
|
|
||||||
"YES",
|
|
||||||
"NO"
|
|
||||||
],
|
|
||||||
"type": "string"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"openapi": "3.0.3",
|
"openapi": "3.1.0",
|
||||||
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Test API",
|
"title": "Test API",
|
||||||
"version": "1.33.7",
|
"version": "1.33.7",
|
||||||
@ -26,15 +27,15 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"/test/date_time_format": {
|
"/": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"summary": "Date time string test",
|
"summary": "Great Summary!",
|
||||||
"description": "Cool stuff",
|
"description": "testing more",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A successful endeavor",
|
"description": "A Successful Endeavor",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
@ -45,22 +46,28 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deprecated": false
|
"deprecated": false
|
||||||
}
|
},
|
||||||
|
"parameters": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webhooks": {},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
|
"Instant": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date"
|
||||||
|
},
|
||||||
"DateTimeString": {
|
"DateTimeString": {
|
||||||
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"a": {
|
"a": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"a"
|
"a"
|
||||||
],
|
]
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {}
|
"securitySchemes": {}
|
@ -0,0 +1,104 @@
|
|||||||
|
package io.bkbn.kompendium.core.fixtures
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude
|
||||||
|
import com.fasterxml.jackson.databind.SerializationFeature
|
||||||
|
import io.bkbn.kompendium.core.fixtures.TestSpecs.defaultSpec
|
||||||
|
import io.bkbn.kompendium.core.plugin.NotarizedApplication
|
||||||
|
import io.bkbn.kompendium.core.routes.redoc
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||||
|
import io.bkbn.kompendium.oas.OpenApiSpec
|
||||||
|
import io.bkbn.kompendium.oas.info.Contact
|
||||||
|
import io.bkbn.kompendium.oas.info.Info
|
||||||
|
import io.bkbn.kompendium.oas.info.License
|
||||||
|
import io.bkbn.kompendium.oas.serialization.KompendiumSerializersModule
|
||||||
|
import io.bkbn.kompendium.oas.server.Server
|
||||||
|
import io.kotest.assertions.json.shouldEqualJson
|
||||||
|
import io.kotest.assertions.ktor.client.shouldHaveStatus
|
||||||
|
import io.kotest.matchers.shouldNot
|
||||||
|
import io.kotest.matchers.string.beBlank
|
||||||
|
import io.ktor.client.request.get
|
||||||
|
import io.ktor.client.statement.bodyAsText
|
||||||
|
import io.ktor.http.ContentType
|
||||||
|
import io.ktor.http.HttpStatusCode
|
||||||
|
import io.ktor.serialization.gson.gson
|
||||||
|
import io.ktor.serialization.jackson.jackson
|
||||||
|
import io.ktor.serialization.kotlinx.json.json
|
||||||
|
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
|
||||||
|
import io.ktor.server.routing.Routing
|
||||||
|
import io.ktor.server.testing.ApplicationTestBuilder
|
||||||
|
import io.ktor.server.testing.testApplication
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import java.io.File
|
||||||
|
import java.net.URI
|
||||||
|
|
||||||
|
object TestHelpers {
|
||||||
|
private const val OPEN_API_ENDPOINT = "/openapi.json"
|
||||||
|
|
||||||
|
fun getFileSnapshot(fileName: String): String {
|
||||||
|
val snapshotPath = "src/test/resources"
|
||||||
|
val file = File("$snapshotPath/$fileName")
|
||||||
|
return file.readText()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the baseline expected tests on an OpenAPI result. Confirms that the endpoint
|
||||||
|
* exists as expected, and that the content matches the expected blob found in the specified file
|
||||||
|
* @param snapshotName The snapshot file to retrieve from the resources folder
|
||||||
|
*/
|
||||||
|
private suspend fun ApplicationTestBuilder.compareOpenAPISpec(snapshotName: String) {
|
||||||
|
val response = client.get(OPEN_API_ENDPOINT)
|
||||||
|
response shouldHaveStatus HttpStatusCode.OK
|
||||||
|
response.bodyAsText() shouldNot beBlank()
|
||||||
|
response.bodyAsText() shouldEqualJson getFileSnapshot(snapshotName)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will take a provided JSON snapshot file, retrieve it from the resource folder,
|
||||||
|
* and build a test ktor server to compare the expected output with the output found in the default
|
||||||
|
* OpenAPI json endpoint. By default, this will run the same test with Gson, Kotlinx, and Jackson serializers
|
||||||
|
* @param snapshotName The snapshot file to retrieve from the resources folder
|
||||||
|
* @param moduleFunction Initializer for the application to allow tests to pass the required Ktor modules
|
||||||
|
*/
|
||||||
|
fun openApiTestAllSerializers(
|
||||||
|
snapshotName: String,
|
||||||
|
customTypes: Map<KType, JsonSchema> = emptyMap(),
|
||||||
|
routeUnderTest: Routing.() -> Unit
|
||||||
|
) {
|
||||||
|
openApiTest(snapshotName, SupportedSerializer.KOTLINX, routeUnderTest, customTypes)
|
||||||
|
openApiTest(snapshotName, SupportedSerializer.JACKSON, routeUnderTest, customTypes)
|
||||||
|
openApiTest(snapshotName, SupportedSerializer.GSON, routeUnderTest, customTypes)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openApiTest(
|
||||||
|
snapshotName: String,
|
||||||
|
serializer: SupportedSerializer,
|
||||||
|
routeUnderTest: Routing.() -> Unit,
|
||||||
|
typeOverrides: Map<KType, JsonSchema> = emptyMap()
|
||||||
|
) = testApplication {
|
||||||
|
install(NotarizedApplication()) {
|
||||||
|
customTypes = typeOverrides
|
||||||
|
spec = defaultSpec()
|
||||||
|
}
|
||||||
|
install(ContentNegotiation) {
|
||||||
|
when (serializer) {
|
||||||
|
SupportedSerializer.KOTLINX -> json(Json {
|
||||||
|
encodeDefaults = true
|
||||||
|
explicitNulls = false
|
||||||
|
serializersModule = KompendiumSerializersModule.module
|
||||||
|
})
|
||||||
|
|
||||||
|
SupportedSerializer.GSON -> gson()
|
||||||
|
SupportedSerializer.JACKSON -> jackson(ContentType.Application.Json) {
|
||||||
|
enable(SerializationFeature.INDENT_OUTPUT)
|
||||||
|
setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
routing {
|
||||||
|
redoc()
|
||||||
|
routeUnderTest()
|
||||||
|
}
|
||||||
|
compareOpenAPISpec(snapshotName)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
package io.bkbn.kompendium.core.fixtures
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TestNested(val nesty: String)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TestRequest(
|
||||||
|
val fieldName: TestNested,
|
||||||
|
val b: Double,
|
||||||
|
val aaa: List<Long>
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TestSimpleRequest(
|
||||||
|
val a: String,
|
||||||
|
val b: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TestResponse(val c: String)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
enum class TestEnum {
|
||||||
|
YES,
|
||||||
|
NO
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class NullableEnum(val a: TestEnum? = null)
|
||||||
|
|
||||||
|
data class TestCreatedResponse(val id: Int, val c: String)
|
||||||
|
|
||||||
|
data class DateTimeString(
|
||||||
|
val a: Instant
|
||||||
|
)
|
||||||
|
|
||||||
|
data class DefaultField(
|
||||||
|
val a: String = "hi",
|
||||||
|
val b: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
data class NullableField(
|
||||||
|
val a: String?
|
||||||
|
)
|
||||||
|
|
||||||
|
data class ComplexRequest(
|
||||||
|
val org: String,
|
||||||
|
val amazingField: String,
|
||||||
|
val tables: List<NestedComplexItem>
|
||||||
|
)
|
||||||
|
|
||||||
|
data class NestedComplexItem(
|
||||||
|
val name: String,
|
||||||
|
val alias: CustomAlias
|
||||||
|
)
|
||||||
|
|
||||||
|
typealias CustomAlias = Map<String, CrazyItem>
|
||||||
|
|
||||||
|
data class CrazyItem(val enumeration: SimpleEnum)
|
||||||
|
|
||||||
|
enum class SimpleEnum {
|
||||||
|
ONE,
|
||||||
|
TWO
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ExceptionResponse(val message: String)
|
||||||
|
|
||||||
|
sealed class FlibbityGibbit {
|
||||||
|
abstract val z: String
|
||||||
|
}
|
||||||
|
|
||||||
|
data class SimpleGibbit(val a: String, override val z: String = "z") : FlibbityGibbit()
|
||||||
|
data class ComplexGibbit(val b: String, val c: Int, override val z: String) : FlibbityGibbit()
|
||||||
|
|
||||||
|
sealed interface SlammaJamma
|
||||||
|
|
||||||
|
data class OneJamma(val a: Int) : SlammaJamma
|
||||||
|
data class AnothaJamma(val b: Float) : SlammaJamma
|
||||||
|
|
||||||
|
data class InsaneJamma(val c: SlammaJamma) : SlammaJamma
|
||||||
|
|
||||||
|
sealed interface Flibbity<T>
|
||||||
|
|
||||||
|
data class Gibbity<T>(val a: T) : Flibbity<T>
|
||||||
|
data class Bibbity<T>(val b: String, val f: T) : Flibbity<T>
|
||||||
|
|
||||||
|
data class NestedFlibbity<T>(
|
||||||
|
val flibbity: Flibbity<T>
|
||||||
|
)
|
||||||
|
|
||||||
|
enum class ColumnMode {
|
||||||
|
NULLABLE,
|
||||||
|
REQUIRED,
|
||||||
|
REPEATED
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ColumnSchema(
|
||||||
|
val name: String,
|
||||||
|
val type: String,
|
||||||
|
val description: String,
|
||||||
|
val mode: ColumnMode,
|
||||||
|
val subColumns: List<ColumnSchema> = emptyList()
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
public data class ProfileUpdateRequest(
|
||||||
|
public val mood: String?,
|
||||||
|
public val viewCount: Long?,
|
||||||
|
public val metadata: ProfileMetadataUpdateRequest?
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
public data class ProfileMetadataUpdateRequest(
|
||||||
|
public val isPrivate: Boolean?,
|
||||||
|
public val otherThing: String?
|
||||||
|
)
|
@ -13,7 +13,7 @@ object TestSpecs {
|
|||||||
info = Info(
|
info = Info(
|
||||||
title = "Test API",
|
title = "Test API",
|
||||||
version = "1.33.7",
|
version = "1.33.7",
|
||||||
description = "An amazing, fully-ish 😉 generated API spec",
|
description = "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
||||||
termsOfService = URI("https://example.com"),
|
termsOfService = URI("https://example.com"),
|
||||||
contact = Contact(
|
contact = Contact(
|
||||||
name = "Homer Simpson",
|
name = "Homer Simpson",
|
@ -4,17 +4,15 @@ complexity:
|
|||||||
LongParameterList:
|
LongParameterList:
|
||||||
active: true
|
active: true
|
||||||
functionThreshold: 10
|
functionThreshold: 10
|
||||||
constructorThreshold: 10
|
constructorThreshold: 15
|
||||||
ComplexMethod:
|
ComplexMethod:
|
||||||
threshold: 20
|
threshold: 20
|
||||||
formatting:
|
|
||||||
ParameterListWrapping:
|
|
||||||
active: false
|
|
||||||
style:
|
style:
|
||||||
MaxLineLength:
|
MaxLineLength:
|
||||||
excludes: ['**/test/**/*']
|
excludes: ['**/test/**/*']
|
||||||
active: true
|
active: true
|
||||||
maxLineLength: 120
|
maxLineLength: 120
|
||||||
|
excludeCommentStatements: true
|
||||||
MagicNumber:
|
MagicNumber:
|
||||||
excludes: ['**/kompendium-playground/**/*', '**/test/**/*']
|
excludes: ['**/kompendium-playground/**/*', '**/test/**/*']
|
||||||
naming:
|
naming:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Kompendium
|
# Kompendium
|
||||||
project.version=2.3.5
|
project.version=3.0.0-alpha
|
||||||
# Kotlin
|
# Kotlin
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
# Gradle
|
# Gradle
|
||||||
@ -8,5 +8,5 @@ org.gradle.vfs.verbose=true
|
|||||||
org.gradle.jvmargs=-Xmx2000m
|
org.gradle.jvmargs=-Xmx2000m
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
ktorVersion=1.6.8
|
ktorVersion=2.1.0
|
||||||
kotestVersion=5.4.2
|
kotestVersion=5.4.2
|
||||||
|
32
json-schema/build.gradle.kts
Normal file
32
json-schema/build.gradle.kts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
kotlin("plugin.serialization")
|
||||||
|
id("io.bkbn.sourdough.library.jvm")
|
||||||
|
id("io.gitlab.arturbosch.detekt")
|
||||||
|
id("com.adarshr.test-logger")
|
||||||
|
id("org.jetbrains.dokka")
|
||||||
|
id("maven-publish")
|
||||||
|
id("java-library")
|
||||||
|
id("signing")
|
||||||
|
}
|
||||||
|
|
||||||
|
sourdoughLibrary {
|
||||||
|
libraryName.set("Kompendium JSON Schema")
|
||||||
|
libraryDescription.set("Json Schema Generator")
|
||||||
|
compilerArgs.set(listOf("-opt-in=kotlin.RequiresOptIn"))
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("org.jetbrains.kotlin:kotlin-reflect:1.7.10")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.3")
|
||||||
|
|
||||||
|
testImplementation(testFixtures(projects.kompendiumCore))
|
||||||
|
}
|
||||||
|
|
||||||
|
testing {
|
||||||
|
suites {
|
||||||
|
named("test", JvmTestSuite::class) {
|
||||||
|
useJUnitJupiter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.NullableDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.OneOfDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.handler.CollectionHandler
|
||||||
|
import io.bkbn.kompendium.json.schema.handler.EnumHandler
|
||||||
|
import io.bkbn.kompendium.json.schema.handler.MapHandler
|
||||||
|
import io.bkbn.kompendium.json.schema.handler.SimpleObjectHandler
|
||||||
|
import io.bkbn.kompendium.json.schema.handler.SealedObjectHandler
|
||||||
|
import io.bkbn.kompendium.json.schema.util.Helpers.getSimpleSlug
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
import kotlin.reflect.full.isSubclassOf
|
||||||
|
import kotlin.reflect.typeOf
|
||||||
|
|
||||||
|
object SchemaGenerator {
|
||||||
|
inline fun <reified T : Any?> fromTypeToSchema(cache: MutableMap<String, JsonSchema> = mutableMapOf()) =
|
||||||
|
fromTypeToSchema(typeOf<T>(), cache)
|
||||||
|
|
||||||
|
fun fromTypeToSchema(type: KType, cache: MutableMap<String, JsonSchema>): JsonSchema {
|
||||||
|
cache[type.getSimpleSlug()]?.let {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
return when (val clazz = type.classifier as KClass<*>) {
|
||||||
|
Unit::class -> error(
|
||||||
|
"""
|
||||||
|
Unit cannot be converted to JsonSchema.
|
||||||
|
If you are looking for a method will return null when called with Unit,
|
||||||
|
please call SchemaGenerator.fromTypeOrUnit()
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
Int::class -> checkForNull(type, TypeDefinition.INT)
|
||||||
|
Long::class -> checkForNull(type, TypeDefinition.LONG)
|
||||||
|
Double::class -> checkForNull(type, TypeDefinition.DOUBLE)
|
||||||
|
Float::class -> checkForNull(type, TypeDefinition.FLOAT)
|
||||||
|
String::class -> checkForNull(type, TypeDefinition.STRING)
|
||||||
|
Boolean::class -> checkForNull(type, TypeDefinition.BOOLEAN)
|
||||||
|
else -> when {
|
||||||
|
clazz.isSubclassOf(Enum::class) -> EnumHandler.handle(type, clazz)
|
||||||
|
clazz.isSubclassOf(Collection::class) -> CollectionHandler.handle(type, cache)
|
||||||
|
clazz.isSubclassOf(Map::class) -> MapHandler.handle(type, cache)
|
||||||
|
else -> {
|
||||||
|
if (clazz.isSealed) {
|
||||||
|
SealedObjectHandler.handle(type, clazz, cache)
|
||||||
|
} else {
|
||||||
|
SimpleObjectHandler.handle(type, clazz, cache)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fromTypeOrUnit(type: KType, cache: MutableMap<String, JsonSchema> = mutableMapOf()): JsonSchema? =
|
||||||
|
when (type.classifier as KClass<*>) {
|
||||||
|
Unit::class -> null
|
||||||
|
else -> fromTypeToSchema(type, cache)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkForNull(type: KType, schema: JsonSchema): JsonSchema = when (type.isMarkedNullable) {
|
||||||
|
true -> OneOfDefinition(NullableDefinition(), schema)
|
||||||
|
false -> schema
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema.definition
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class AnyOfDefinition(val anyOf: Set<JsonSchema>) : JsonSchema
|
@ -0,0 +1,10 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema.definition
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ArrayDefinition(
|
||||||
|
val items: JsonSchema
|
||||||
|
) : JsonSchema {
|
||||||
|
val type: String = "array"
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema.definition
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class EnumDefinition(
|
||||||
|
val enum: Set<String>
|
||||||
|
) : JsonSchema
|
@ -0,0 +1,33 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema.definition
|
||||||
|
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||||
|
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
||||||
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
|
import kotlinx.serialization.encoding.Decoder
|
||||||
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
|
||||||
|
@Serializable(with = JsonSchema.Serializer::class)
|
||||||
|
sealed interface JsonSchema {
|
||||||
|
|
||||||
|
object Serializer : KSerializer<JsonSchema> {
|
||||||
|
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("JsonSchema", PrimitiveKind.STRING)
|
||||||
|
override fun deserialize(decoder: Decoder): JsonSchema {
|
||||||
|
error("Abandon all hope ye who enter 💀")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, value: JsonSchema) {
|
||||||
|
when (value) {
|
||||||
|
is ReferenceDefinition -> ReferenceDefinition.serializer().serialize(encoder, value)
|
||||||
|
is TypeDefinition -> TypeDefinition.serializer().serialize(encoder, value)
|
||||||
|
is EnumDefinition -> EnumDefinition.serializer().serialize(encoder, value)
|
||||||
|
is ArrayDefinition -> ArrayDefinition.serializer().serialize(encoder, value)
|
||||||
|
is MapDefinition -> MapDefinition.serializer().serialize(encoder, value)
|
||||||
|
is NullableDefinition -> NullableDefinition.serializer().serialize(encoder, value)
|
||||||
|
is OneOfDefinition -> OneOfDefinition.serializer().serialize(encoder, value)
|
||||||
|
is AnyOfDefinition -> AnyOfDefinition.serializer().serialize(encoder, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema.definition
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class MapDefinition(
|
||||||
|
val additionalProperties: JsonSchema
|
||||||
|
) : JsonSchema {
|
||||||
|
val type: String = "object"
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema.definition
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class NullableDefinition(val type: String = "null") : JsonSchema
|
@ -0,0 +1,8 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema.definition
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class OneOfDefinition(val oneOf: Set<JsonSchema>) : JsonSchema {
|
||||||
|
constructor(vararg types: JsonSchema) : this(types.toSet())
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema.definition
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ReferenceDefinition(val `$ref`: String) : JsonSchema
|
@ -0,0 +1,47 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema.definition
|
||||||
|
|
||||||
|
import kotlinx.serialization.Contextual
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TypeDefinition(
|
||||||
|
val type: String,
|
||||||
|
val format: String? = null,
|
||||||
|
val description: String? = null,
|
||||||
|
val properties: Map<String, JsonSchema>? = null,
|
||||||
|
val required: Set<String>? = null,
|
||||||
|
@Contextual val default: Any? = null,
|
||||||
|
) : JsonSchema {
|
||||||
|
|
||||||
|
fun withDefault(default: Any): TypeDefinition = this.copy(default = default)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val INT = TypeDefinition(
|
||||||
|
type = "number",
|
||||||
|
format = "int32"
|
||||||
|
)
|
||||||
|
|
||||||
|
val LONG = TypeDefinition(
|
||||||
|
type = "number",
|
||||||
|
format = "int64"
|
||||||
|
)
|
||||||
|
|
||||||
|
val DOUBLE = TypeDefinition(
|
||||||
|
type = "number",
|
||||||
|
format = "double"
|
||||||
|
)
|
||||||
|
|
||||||
|
val FLOAT = TypeDefinition(
|
||||||
|
type = "number",
|
||||||
|
format = "float"
|
||||||
|
)
|
||||||
|
|
||||||
|
val STRING = TypeDefinition(
|
||||||
|
type = "string"
|
||||||
|
)
|
||||||
|
|
||||||
|
val BOOLEAN = TypeDefinition(
|
||||||
|
type = "boolean"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema.handler
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.json.schema.SchemaGenerator
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.ArrayDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.NullableDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.OneOfDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.ReferenceDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.util.Helpers.getReferenceSlug
|
||||||
|
import io.bkbn.kompendium.json.schema.util.Helpers.getSimpleSlug
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
|
||||||
|
object CollectionHandler {
|
||||||
|
|
||||||
|
fun handle(type: KType, cache: MutableMap<String, JsonSchema>): JsonSchema {
|
||||||
|
val collectionType = type.arguments.first().type!!
|
||||||
|
val typeSchema = SchemaGenerator.fromTypeToSchema(collectionType, cache).let {
|
||||||
|
if (it is TypeDefinition && it.type == "object") {
|
||||||
|
cache[collectionType.getSimpleSlug()] = it
|
||||||
|
ReferenceDefinition(collectionType.getReferenceSlug())
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val definition = ArrayDefinition(typeSchema)
|
||||||
|
return when (type.isMarkedNullable) {
|
||||||
|
true -> OneOfDefinition(NullableDefinition(), definition)
|
||||||
|
false -> definition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema.handler
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.EnumDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.NullableDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.OneOfDefinition
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
|
||||||
|
object EnumHandler {
|
||||||
|
|
||||||
|
fun handle(type: KType, clazz: KClass<*>): JsonSchema {
|
||||||
|
val options = clazz.java.enumConstants.map { it.toString() }.toSet()
|
||||||
|
val definition = EnumDefinition(enum = options)
|
||||||
|
return when (type.isMarkedNullable) {
|
||||||
|
true -> OneOfDefinition(NullableDefinition(), definition)
|
||||||
|
false -> definition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema.handler
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.json.schema.SchemaGenerator
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.MapDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.NullableDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.OneOfDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.ReferenceDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.util.Helpers.getReferenceSlug
|
||||||
|
import io.bkbn.kompendium.json.schema.util.Helpers.getSimpleSlug
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
|
||||||
|
object MapHandler {
|
||||||
|
|
||||||
|
fun handle(type: KType, cache: MutableMap<String, JsonSchema>): JsonSchema {
|
||||||
|
require(type.arguments.first().type!!.classifier as KClass<*> == String::class) {
|
||||||
|
"JSON requires that map keys MUST be Strings. You provided ${type.arguments.first().type}"
|
||||||
|
}
|
||||||
|
val valueType = type.arguments[1].type!!
|
||||||
|
val valueSchema = SchemaGenerator.fromTypeToSchema(valueType, cache).let {
|
||||||
|
if (it is TypeDefinition && it.type == "object") {
|
||||||
|
cache[valueType.getSimpleSlug()] = it
|
||||||
|
ReferenceDefinition(valueType.getReferenceSlug())
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val definition = MapDefinition(valueSchema)
|
||||||
|
return when (type.isMarkedNullable) {
|
||||||
|
true -> OneOfDefinition(NullableDefinition(), definition)
|
||||||
|
false -> definition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema.handler
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.json.schema.SchemaGenerator
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.AnyOfDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.ReferenceDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.util.Helpers.getReferenceSlug
|
||||||
|
import io.bkbn.kompendium.json.schema.util.Helpers.getSimpleSlug
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
import kotlin.reflect.full.createType
|
||||||
|
|
||||||
|
object SealedObjectHandler {
|
||||||
|
|
||||||
|
fun handle(type: KType, clazz: KClass<*>, cache: MutableMap<String, JsonSchema>): JsonSchema {
|
||||||
|
val subclasses = clazz.sealedSubclasses
|
||||||
|
.map { it.createType(type.arguments) }
|
||||||
|
.map { t ->
|
||||||
|
SchemaGenerator.fromTypeToSchema(t, cache).let { js ->
|
||||||
|
if (js is TypeDefinition && js.type == "object") {
|
||||||
|
cache[t.getSimpleSlug()] = js
|
||||||
|
ReferenceDefinition(t.getReferenceSlug())
|
||||||
|
} else {
|
||||||
|
js
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.toSet()
|
||||||
|
return AnyOfDefinition(subclasses)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema.handler
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.json.schema.SchemaGenerator
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.NullableDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.OneOfDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.ReferenceDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
|
||||||
|
import io.bkbn.kompendium.json.schema.util.Helpers.getReferenceSlug
|
||||||
|
import io.bkbn.kompendium.json.schema.util.Helpers.getSimpleSlug
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
import kotlin.reflect.KTypeParameter
|
||||||
|
import kotlin.reflect.KTypeProjection
|
||||||
|
import kotlin.reflect.full.memberProperties
|
||||||
|
import kotlin.reflect.full.primaryConstructor
|
||||||
|
|
||||||
|
object SimpleObjectHandler {
|
||||||
|
|
||||||
|
fun handle(type: KType, clazz: KClass<*>, cache: MutableMap<String, JsonSchema>): JsonSchema {
|
||||||
|
// cache[type.getSimpleSlug()] = ReferenceDefinition("RECURSION_PLACEHOLDER")
|
||||||
|
val typeMap = clazz.typeParameters.zip(type.arguments).toMap()
|
||||||
|
val props = clazz.memberProperties.associate { prop ->
|
||||||
|
val schema = when (typeMap.containsKey(prop.returnType.classifier)) {
|
||||||
|
true -> handleGenericProperty(prop, typeMap, cache)
|
||||||
|
false -> handleProperty(prop, cache)
|
||||||
|
}
|
||||||
|
|
||||||
|
prop.name to schema
|
||||||
|
}
|
||||||
|
|
||||||
|
val required = clazz.memberProperties.filterNot { prop -> prop.returnType.isMarkedNullable }
|
||||||
|
.filterNot { prop -> clazz.primaryConstructor!!.parameters.find { it.name == prop.name }!!.isOptional }
|
||||||
|
.map { it.name }
|
||||||
|
.toSet()
|
||||||
|
|
||||||
|
|
||||||
|
val definition = TypeDefinition(
|
||||||
|
type = "object",
|
||||||
|
properties = props,
|
||||||
|
required = required
|
||||||
|
)
|
||||||
|
|
||||||
|
return when (type.isMarkedNullable) {
|
||||||
|
true -> OneOfDefinition(NullableDefinition(), definition)
|
||||||
|
false -> definition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleGenericProperty(
|
||||||
|
prop: KProperty<*>,
|
||||||
|
typeMap: Map<KTypeParameter, KTypeProjection>,
|
||||||
|
cache: MutableMap<String, JsonSchema>
|
||||||
|
): JsonSchema {
|
||||||
|
val type = typeMap[prop.returnType.classifier]?.type!!
|
||||||
|
return SchemaGenerator.fromTypeToSchema(type, cache).let {
|
||||||
|
if (it is TypeDefinition && it.type == "object") {
|
||||||
|
cache[type.getSimpleSlug()] = it
|
||||||
|
ReferenceDefinition(prop.returnType.getReferenceSlug())
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleProperty(prop: KProperty<*>, cache: MutableMap<String, JsonSchema>): JsonSchema =
|
||||||
|
SchemaGenerator.fromTypeToSchema(prop.returnType, cache).let {
|
||||||
|
if (it is TypeDefinition && it.type == "object") {
|
||||||
|
cache[prop.returnType.getSimpleSlug()] = it
|
||||||
|
ReferenceDefinition(prop.returnType.getReferenceSlug())
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema.util
|
||||||
|
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
|
||||||
|
object Helpers {
|
||||||
|
|
||||||
|
private const val COMPONENT_SLUG = "#/components/schemas"
|
||||||
|
|
||||||
|
fun KType.getSimpleSlug(): String = when {
|
||||||
|
this.arguments.isNotEmpty() -> genericNameAdapter(this, classifier as KClass<*>)
|
||||||
|
else -> (classifier as KClass<*>).simpleName ?: error("Could not determine simple name for $this")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KType.getReferenceSlug(): String = when {
|
||||||
|
arguments.isNotEmpty() -> "$COMPONENT_SLUG/${genericNameAdapter(this, classifier as KClass<*>)}"
|
||||||
|
else -> "$COMPONENT_SLUG/${(classifier as KClass<*>).simpleName}"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapts a class with type parameters into a reference friendly string
|
||||||
|
*/
|
||||||
|
private fun genericNameAdapter(type: KType, clazz: KClass<*>): String {
|
||||||
|
val classNames = type.arguments
|
||||||
|
.map { it.type?.classifier as KClass<*> }
|
||||||
|
.map { it.simpleName }
|
||||||
|
return classNames.joinToString(separator = "-", prefix = "${clazz.simpleName}-")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema.util
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
|
||||||
|
data class ReferenceCache(
|
||||||
|
val referenceRootPath: String = "#/",
|
||||||
|
val cache: MutableMap<KType, JsonSchema> = mutableMapOf()
|
||||||
|
)
|
@ -0,0 +1,98 @@
|
|||||||
|
package io.bkbn.kompendium.json.schema
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.core.fixtures.ComplexRequest
|
||||||
|
import io.bkbn.kompendium.core.fixtures.FlibbityGibbit
|
||||||
|
import io.bkbn.kompendium.core.fixtures.SimpleEnum
|
||||||
|
import io.bkbn.kompendium.core.fixtures.SlammaJamma
|
||||||
|
import io.bkbn.kompendium.core.fixtures.TestHelpers.getFileSnapshot
|
||||||
|
import io.bkbn.kompendium.core.fixtures.TestResponse
|
||||||
|
import io.bkbn.kompendium.core.fixtures.TestSimpleRequest
|
||||||
|
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||||
|
import io.kotest.assertions.json.shouldEqualJson
|
||||||
|
import io.kotest.assertions.throwables.shouldThrow
|
||||||
|
import io.kotest.core.spec.style.DescribeSpec
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
class SchemaGeneratorTest : DescribeSpec({
|
||||||
|
describe("Scalars") {
|
||||||
|
it("Can generate the schema for an Int") {
|
||||||
|
jsonSchemaTest<Int>("T0001__scalar_int.json")
|
||||||
|
}
|
||||||
|
it("Can generate the schema for a Boolean") {
|
||||||
|
jsonSchemaTest<Boolean>("T0002__scalar_bool.json")
|
||||||
|
}
|
||||||
|
it("Can generate the schema for a String") {
|
||||||
|
jsonSchemaTest<String>("T0003__scalar_string.json")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
describe("Objects") {
|
||||||
|
it("Can generate the schema for a simple object") {
|
||||||
|
jsonSchemaTest<TestSimpleRequest>("T0004__simple_object.json")
|
||||||
|
}
|
||||||
|
it("Can generate the schema for a complex object") {
|
||||||
|
jsonSchemaTest<ComplexRequest>("T0005__complex_object.json")
|
||||||
|
}
|
||||||
|
it("Can generate the schema for a nullable object") {
|
||||||
|
jsonSchemaTest<TestSimpleRequest?>("T0006__nullable_object.json")
|
||||||
|
}
|
||||||
|
it("Can generate the schema for a polymorphic object") {
|
||||||
|
jsonSchemaTest<FlibbityGibbit>("T0015__polymorphic_object.json")
|
||||||
|
}
|
||||||
|
xit("Can generate the schema for a recursive type") {
|
||||||
|
// TODO jsonSchemaTest<SlammaJamma>("T0016__recursive_object.json")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
describe("Enums") {
|
||||||
|
it("Can generate the schema for a simple enum") {
|
||||||
|
jsonSchemaTest<SimpleEnum>("T0007__simple_enum.json")
|
||||||
|
}
|
||||||
|
it("Can generate the schema for a nullable enum") {
|
||||||
|
jsonSchemaTest<SimpleEnum?>("T0008__nullable_enum.json")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
describe("Arrays") {
|
||||||
|
it("Can generate the schema for an array of scalars") {
|
||||||
|
jsonSchemaTest<List<Int>>("T0009__scalar_array.json")
|
||||||
|
}
|
||||||
|
it("Can generate the schema for an array of objects") {
|
||||||
|
jsonSchemaTest<List<TestResponse>>("T0010__object_array.json")
|
||||||
|
}
|
||||||
|
it("Can generate the schema for a nullable array") {
|
||||||
|
jsonSchemaTest<List<Int>?>("T0011__nullable_array.json")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
describe("Maps") {
|
||||||
|
it("Can generate the schema for a map of scalars") {
|
||||||
|
jsonSchemaTest<Map<String, Int>>("T0012__scalar_map.json")
|
||||||
|
}
|
||||||
|
it("Throws an error when map keys are not strings") {
|
||||||
|
shouldThrow<IllegalArgumentException> { SchemaGenerator.fromTypeToSchema<Map<Int, Int>>() }
|
||||||
|
}
|
||||||
|
it("Can generate the schema for a map of objects") {
|
||||||
|
jsonSchemaTest<Map<String, TestResponse>>("T0013__object_map.json")
|
||||||
|
}
|
||||||
|
it("Can generate the schema for a nullable map") {
|
||||||
|
jsonSchemaTest<Map<String, Int>?>("T0014__nullable_map.json")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
companion object {
|
||||||
|
private val json = Json {
|
||||||
|
encodeDefaults = true
|
||||||
|
explicitNulls = false
|
||||||
|
prettyPrint = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JsonSchema.serialize() = json.encodeToString(JsonSchema.serializer(), this)
|
||||||
|
|
||||||
|
private inline fun <reified T> jsonSchemaTest(snapshotName: String) {
|
||||||
|
// act
|
||||||
|
val schema = SchemaGenerator.fromTypeToSchema<T>()
|
||||||
|
|
||||||
|
// todo add cache assertions!!!
|
||||||
|
|
||||||
|
// assert
|
||||||
|
schema.serialize() shouldEqualJson getFileSnapshot(snapshotName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
json-schema/src/test/resources/T0001__scalar_int.json
Normal file
4
json-schema/src/test/resources/T0001__scalar_int.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
3
json-schema/src/test/resources/T0002__scalar_bool.json
Normal file
3
json-schema/src/test/resources/T0002__scalar_bool.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
3
json-schema/src/test/resources/T0003__scalar_string.json
Normal file
3
json-schema/src/test/resources/T0003__scalar_string.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
16
json-schema/src/test/resources/T0004__simple_object.json
Normal file
16
json-schema/src/test/resources/T0004__simple_object.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"a": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"b": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"a",
|
||||||
|
"b"
|
||||||
|
]
|
||||||
|
}
|
22
json-schema/src/test/resources/T0005__complex_object.json
Normal file
22
json-schema/src/test/resources/T0005__complex_object.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"amazingField": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"org": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tables": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/NestedComplexItem"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"amazingField",
|
||||||
|
"org",
|
||||||
|
"tables"
|
||||||
|
]
|
||||||
|
}
|
23
json-schema/src/test/resources/T0006__nullable_object.json
Normal file
23
json-schema/src/test/resources/T0006__nullable_object.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"a": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"b": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"a",
|
||||||
|
"b"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
3
json-schema/src/test/resources/T0007__simple_enum.json
Normal file
3
json-schema/src/test/resources/T0007__simple_enum.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"enum": [ "ONE", "TWO" ]
|
||||||
|
}
|
13
json-schema/src/test/resources/T0008__nullable_enum.json
Normal file
13
json-schema/src/test/resources/T0008__nullable_enum.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enum": [
|
||||||
|
"ONE",
|
||||||
|
"TWO"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
7
json-schema/src/test/resources/T0009__scalar_array.json
Normal file
7
json-schema/src/test/resources/T0009__scalar_array.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"items": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
6
json-schema/src/test/resources/T0010__object_array.json
Normal file
6
json-schema/src/test/resources/T0010__object_array.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/TestResponse"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
14
json-schema/src/test/resources/T0011__nullable_array.json
Normal file
14
json-schema/src/test/resources/T0011__nullable_array.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"items": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
7
json-schema/src/test/resources/T0012__scalar_map.json
Normal file
7
json-schema/src/test/resources/T0012__scalar_map.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
6
json-schema/src/test/resources/T0013__object_map.json
Normal file
6
json-schema/src/test/resources/T0013__object_map.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"additionalProperties": {
|
||||||
|
"$ref": "#/components/schemas/TestResponse"
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
14
json-schema/src/test/resources/T0014__nullable_map.json
Normal file
14
json-schema/src/test/resources/T0014__nullable_map.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/ComplexGibbit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/SimpleGibbit"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user