Compare commits

..

11 Commits

52 changed files with 1041 additions and 350 deletions

View File

@ -2,6 +2,9 @@ name: Publish to GitHub Packages
on: on:
push: push:
branches: [ main ] branches: [ main ]
env:
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SONATYPE_SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SONATYPE_SIGNING_PASSWORD }}
jobs: jobs:
publish: publish:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -4,8 +4,11 @@ on:
types: types:
- prereleased - prereleased
- released - released
env:
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SONATYPE_SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SONATYPE_SIGNING_PASSWORD }}
jobs: jobs:
publish: publish-to-github:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -20,6 +23,25 @@ jobs:
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }} key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: ${{ runner.os }}-gradle restore-keys: ${{ runner.os }}-gradle
- name: Publish packages to Github - name: Publish packages to Github
run: ./gradlew publish -Prelease=true run: ./gradlew publishAllPublicationsToGithubPackagesRepository -Prelease=true
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish-to-nexus:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '11'
- name: Cache Gradle packages
uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: ${{ runner.os }}-gradle
- name: Publish packages to Github
run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository -Prelease=true
env:
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USER }}
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}

View File

@ -1,5 +1,51 @@
# Changelog # Changelog
## [1.6.0] - August 12, 2021
### Added
- Ability to add custom type schema overrides for edge case types.
## [1.5.1] - August 12th, 2021
### Changed
- Fixed bug where polymorphic types were not being rendered correctly when part of collections and maps
## [1.5.0] - July 25th, 2021
### Changed
- Added support for BigInteger and BigDecimal in response types
## [1.4.0] - July 22nd, 2021
### Changed
- Decreased jvmTarget version from 11 to 1.8
## [1.3.0] - June 4th, 2021
### Changed
- Explicitly encode JSON object by default
## [1.2.3] - June 3rd, 2021
### Added
- Updates showing/explaining serializer agnostic approach
## [1.2.2] - May 23rd, 2021
This is just to get my repo back to normal now that I have confirmed sonatype publish is happening
## [1.2.0] - May 23rd, 2021
### Added
- Finally, successfully pushed to Maven Central!!!
## [1.1.0] - May 19th, 2021 ## [1.1.0] - May 19th, 2021
### Added ### Added

View File

@ -1,5 +1,7 @@
# Kompendium # Kompendium
[![version](https://img.shields.io/maven-central/v/io.bkbn/kompendium-core?style=flat-square)](https://search.maven.org/search?q=io.bkbn%20kompendium)
## What is Kompendium ## What is Kompendium
Kompendium is intended to be a minimally invasive OpenApi Specification generator for [Ktor](https://ktor.io). Kompendium is intended to be a minimally invasive OpenApi Specification generator for [Ktor](https://ktor.io).
@ -8,8 +10,26 @@ supplement with Kompendium code in order to generate the appropriate spec.
## How to install ## How to install
Kompendium uses GitHub packages as its repository. Installing with Gradle is pretty painless. In your `build.gradle.kts` Kompendium publishes all releases to Maven Central. As such, using the stable version of `Kompendium` is as simple
add the following as declaring it as an implementation dependency in your `build.gradle.kts`
```kotlin
repositories {
mavenCentral()
}
dependencies {
// other (less cool) dependencies
implementation("io.bkbn:kompendium-core:latest")
implementation("io.bkbn:kompendium-auth:latest")
implementation("io.bkbn:kompendium-swagger-ui:latest")
}
```
The last two dependencies are optional.
If you want to get a little spicy 🤠 every merge of Kompendium is published to the GitHub package registry. Pulling
from GitHub is slightly more involved, but such is the price you pay for bleeding edge fake data generation.
```kotlin ```kotlin
// 1 Setup a helper function to import any Github Repository Package // 1 Setup a helper function to import any Github Repository Package
@ -17,7 +37,7 @@ add the following
fun RepositoryHandler.github(packageUrl: String) = maven { fun RepositoryHandler.github(packageUrl: String) = maven {
name = "GithubPackages" name = "GithubPackages"
url = uri(packageUrl) url = uri(packageUrl)
credentials { // TODO Not sure this is necessary for public repositories? credentials {
username = java.lang.System.getenv("GITHUB_USER") username = java.lang.System.getenv("GITHUB_USER")
password = java.lang.System.getenv("GITHUB_TOKEN") password = java.lang.System.getenv("GITHUB_TOKEN")
} }
@ -82,6 +102,11 @@ Out of the box, Kompendium has support for sealed classes. At runtime, it will b
and build a spec that takes `anyOf` the implementations. This is currently a weak point of the entire library, and and build a spec that takes `anyOf` the implementations. This is currently a weak point of the entire library, and
suggestions on better implementations are welcome 🤠 suggestions on better implementations are welcome 🤠
### Serialization
Under the hood, Kompendium uses Jackson to serialize the final api spec. However, this implementation detail
does not leak to the actual API, meaning that users are free to choose the serialization library of their choice.
## Examples ## Examples
The full source code can be found in the `kompendium-playground` module. Here is a simple get endpoint example The full source code can be found in the `kompendium-playground` module. Here is a simple get endpoint example
@ -191,6 +216,25 @@ routing {
} }
``` ```
## Custom Type Overrides
Kompendium does its best to analyze types and to generate an OpenAPI format accordingly. However, there are certain
classes that just don't play nice with the standard reflection analysis that Kompendium performs.
Should you encounter a data type that Kompendium cannot comprehend, you will need to
add it explicitly. For example, adding the Joda Time `DateTime` object would be as simple as the following
```kotlin
Kompendium.addCustomTypeSchema(DateTime::class, FormatSchema("date-time", "string"))
```
Since `Kompendium` is an object, this needs to be declared once, ahead of the actual API instantiation. This way, this
type override can be cached ahead of reflection. Kompendium will then match all instances of this type and return the
specified schema.
So how do you know a type can and cannot be inferred? The safe bet is that it can be. So go ahead and give it a shot.
However, in the very odd scenario (almost always having to do with date/time libraries 😤) where it can't, you can rest
safely knowing that you have the option to inject a custom override should you need to.
## Limitations ## Limitations
### Kompendium as a singleton ### Kompendium as a singleton
@ -209,7 +253,6 @@ should have. There are several outstanding features that have been added to the
- AsyncAPI Integration - AsyncAPI Integration
- Field Validation - Field Validation
- MavenCentral Release
If you have a feature that you would like to see implemented that is not on this list, or discover a 🐞, please open If you have a feature that you would like to see implemented that is not on this list, or discover a 🐞, please open
an issue [here](https://github.com/bkbnio/kompendium/issues/new) an issue [here](https://github.com/bkbnio/kompendium/issues/new)

View File

@ -1,12 +1,13 @@
import com.adarshr.gradle.testlogger.theme.ThemeType
import com.adarshr.gradle.testlogger.TestLoggerExtension import com.adarshr.gradle.testlogger.TestLoggerExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import com.adarshr.gradle.testlogger.theme.ThemeType
import io.gitlab.arturbosch.detekt.extensions.DetektExtension import io.gitlab.arturbosch.detekt.extensions.DetektExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { plugins {
id("org.jetbrains.kotlin.jvm") version "1.5.0" apply false id("org.jetbrains.kotlin.jvm") version "1.5.0" apply false
id("io.gitlab.arturbosch.detekt") version "1.17.0-RC3" apply false id("io.gitlab.arturbosch.detekt") version "1.17.0-RC3" apply false
id("com.adarshr.test-logger") version "3.0.0" apply false id("com.adarshr.test-logger") version "3.0.0" apply false
id("io.github.gradle-nexus.publish-plugin") version "1.1.0" apply true
} }
allprojects { allprojects {
@ -32,7 +33,7 @@ allprojects {
tasks.withType<KotlinCompile>().configureEach { tasks.withType<KotlinCompile>().configureEach {
kotlinOptions { kotlinOptions {
jvmTarget = "11" jvmTarget = "1.8"
} }
} }
@ -63,5 +64,15 @@ allprojects {
configure<JavaPluginExtension> { configure<JavaPluginExtension> {
withSourcesJar() withSourcesJar()
withJavadocJar()
}
}
nexusPublishing {
repositories {
sonatype {
nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/"))
snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
}
} }
} }

View File

@ -1,5 +1,5 @@
# Kompendium # Kompendium
project.version=1.1.0 project.version=1.6.0
# Kotlin # Kotlin
kotlin.code.style=official kotlin.code.style=official
# Gradle # Gradle

View File

@ -1,6 +1,8 @@
[versions] [versions]
kotlin = "1.4.32" kotlin = "1.4.32"
ktor = "1.5.3" ktor = "1.5.3"
kotlinx-serialization = "1.2.1"
jackson-kotlin = "2.12.0"
slf4j = "1.7.30" slf4j = "1.7.30"
logback = "1.2.3" logback = "1.2.3"
swagger-ui = "3.47.1" swagger-ui = "3.47.1"
@ -10,11 +12,17 @@ swagger-ui = "3.47.1"
ktor-server-core = { group = "io.ktor", name = "ktor-server-core", version.ref = "ktor" } ktor-server-core = { group = "io.ktor", name = "ktor-server-core", version.ref = "ktor" }
ktor-server-netty = { group = "io.ktor", name = "ktor-server-netty", version.ref = "ktor" } ktor-server-netty = { group = "io.ktor", name = "ktor-server-netty", version.ref = "ktor" }
ktor-jackson = { group = "io.ktor", name = "ktor-jackson", version.ref = "ktor" } ktor-jackson = { group = "io.ktor", name = "ktor-jackson", version.ref = "ktor" }
ktor-serialization = { group = "io.ktor", name = "ktor-serialization", version.ref = "ktor" }
ktor-html-builder = { group = "io.ktor", name = "ktor-html-builder", version.ref = "ktor" } ktor-html-builder = { group = "io.ktor", name = "ktor-html-builder", version.ref = "ktor" }
ktor-auth-lib = { group = "io.ktor", name = "ktor-auth", version.ref = "ktor" } ktor-auth-lib = { group = "io.ktor", name = "ktor-auth", version.ref = "ktor" }
ktor-auth-jwt = { group = "io.ktor", name = "ktor-auth-jwt", version.ref = "ktor" } ktor-auth-jwt = { group = "io.ktor", name = "ktor-auth-jwt", version.ref = "ktor" }
ktor-webjars = { group = "io.ktor", name = "ktor-webjars", version.ref = "ktor" } ktor-webjars = { group = "io.ktor", name = "ktor-webjars", version.ref = "ktor" }
# Serialization
jackson-module-kotlin = { group = "com.fasterxml.jackson.module", name = "jackson-module-kotlin", version.ref = "jackson-kotlin" }
kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
# Logging # Logging
slf4j = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4j" } slf4j = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4j" }
logback-classic = { group = "ch.qos.logback", name = "logback-classic", version.ref = "logback" } logback-classic = { group = "ch.qos.logback", name = "logback-classic", version.ref = "logback" }
@ -23,7 +31,10 @@ logback-core = { group = "ch.qos.logback", name = "logback-core", version.ref =
# webjars # webjars
webjars-swagger-ui = { group = "org.webjars", name = "swagger-ui", version.ref = "swagger-ui" } webjars-swagger-ui = { group = "org.webjars", name = "swagger-ui", version.ref = "swagger-ui" }
# Testing
ktor-server-test-host = { group = "io.ktor", name = "ktor-server-test-host", version.ref = "ktor" }
[bundles] [bundles]
ktor = [ "ktor-server-core", "ktor-server-netty", "ktor-jackson", "ktor-html-builder" ] ktor = ["ktor-server-core", "ktor-server-netty", "ktor-html-builder"]
ktorAuth = ["ktor-auth-lib", "ktor-auth-jwt"] ktorAuth = ["ktor-auth-lib", "ktor-auth-jwt"]
logging = ["slf4j", "logback-classic", "logback-core"] logging = ["slf4j", "logback-classic", "logback-core"]

View File

@ -1,6 +1,7 @@
plugins { plugins {
`java-library` `java-library`
`maven-publish` `maven-publish`
signing
} }
dependencies { dependencies {
@ -10,14 +11,16 @@ dependencies {
implementation(libs.bundles.ktorAuth) implementation(libs.bundles.ktorAuth)
implementation(projects.kompendiumCore) implementation(projects.kompendiumCore)
testImplementation(libs.ktor.jackson)
testImplementation("org.jetbrains.kotlin:kotlin-test") testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit") testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.12.0") testImplementation(libs.jackson.module.kotlin)
testImplementation("io.ktor:ktor-server-test-host:1.5.3") testImplementation(libs.ktor.server.test.host)
} }
java { java {
withSourcesJar() withSourcesJar()
withJavadocJar()
} }
publishing { publishing {
@ -35,6 +38,41 @@ publishing {
create<MavenPublication>("kompendium") { create<MavenPublication>("kompendium") {
from(components["kotlin"]) from(components["kotlin"])
artifact(tasks.sourcesJar) artifact(tasks.sourcesJar)
artifact(tasks.javadocJar)
groupId = project.group.toString()
artifactId = project.name.toLowerCase()
version = project.version.toString()
pom {
name.set("Kompendium")
description.set("A minimally invasive OpenAPI spec generator for Ktor")
url.set("https://github.com/bkbnio/Kompendium")
licenses {
license {
name.set("MIT License")
url.set("https://mit-license.org/")
}
}
developers {
developer {
id.set("bkbnio")
name.set("Ryan Brink")
email.set("admin@bkbn.io")
}
}
scm {
connection.set("scm:git:git://github.com/bkbnio/Kompendium.git")
developerConnection.set("scm:git:ssh://github.com/bkbnio/Kompendium.git")
url.set("https://github.com/bkbnio/Kompendium.git")
} }
} }
} }
}
}
signing {
val signingKey: String? by project
val signingPassword: String? by project
useInMemoryPgpKeys(signingKey, signingPassword)
sign(publishing.publications)
}

View File

@ -20,8 +20,8 @@
"name" : "aa", "name" : "aa",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -51,16 +51,16 @@
"type" : "string" "type" : "string"
}, },
"TestResponse" : { "TestResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
} }
}, },
"securitySchemes" : { "securitySchemes" : {

View File

@ -20,8 +20,8 @@
"name" : "aa", "name" : "aa",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -51,16 +51,16 @@
"type" : "string" "type" : "string"
}, },
"TestResponse" : { "TestResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
} }
}, },
"securitySchemes" : { "securitySchemes" : {

View File

@ -20,8 +20,8 @@
"name" : "aa", "name" : "aa",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -51,16 +51,16 @@
"type" : "string" "type" : "string"
}, },
"TestResponse" : { "TestResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
} }
}, },
"securitySchemes" : { "securitySchemes" : {

View File

@ -20,8 +20,8 @@
"name" : "aa", "name" : "aa",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -51,16 +51,16 @@
"type" : "string" "type" : "string"
}, },
"TestResponse" : { "TestResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
} }
}, },
"securitySchemes" : { "securitySchemes" : {

View File

@ -20,8 +20,8 @@
"name" : "aa", "name" : "aa",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -52,16 +52,16 @@
"type" : "string" "type" : "string"
}, },
"TestResponse" : { "TestResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
} }
}, },
"securitySchemes" : { "securitySchemes" : {

View File

@ -1,20 +1,25 @@
plugins { plugins {
`java-library` `java-library`
`maven-publish` `maven-publish`
signing
} }
dependencies { dependencies {
implementation(platform("org.jetbrains.kotlin:kotlin-bom")) implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation(libs.jackson.module.kotlin)
implementation(libs.bundles.ktor) implementation(libs.bundles.ktor)
testImplementation("org.jetbrains.kotlin:kotlin-test") testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit") testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.12.0") testImplementation(libs.ktor.serialization)
testImplementation("io.ktor:ktor-server-test-host:1.5.3") testImplementation(libs.kotlinx.serialization.json)
testImplementation(libs.ktor.jackson)
testImplementation(libs.ktor.server.test.host)
} }
java { java {
withSourcesJar() withSourcesJar()
withJavadocJar()
} }
publishing { publishing {
@ -32,6 +37,41 @@ publishing {
create<MavenPublication>("kompendium") { create<MavenPublication>("kompendium") {
from(components["kotlin"]) from(components["kotlin"])
artifact(tasks.sourcesJar) artifact(tasks.sourcesJar)
artifact(tasks.javadocJar)
groupId = project.group.toString()
artifactId = project.name.toLowerCase()
version = project.version.toString()
pom {
name.set("Kompendium")
description.set("A minimally invasive OpenAPI spec generator for Ktor")
url.set("https://github.com/bkbnio/Kompendium")
licenses {
license {
name.set("MIT License")
url.set("https://mit-license.org/")
}
}
developers {
developer {
id.set("bkbnio")
name.set("Ryan Brink")
email.set("admin@bkbn.io")
}
}
scm {
connection.set("scm:git:git://github.com/bkbnio/Kompendium.git")
developerConnection.set("scm:git:ssh://github.com/bkbnio/Kompendium.git")
url.set("https://github.com/bkbnio/Kompendium.git")
} }
} }
} }
}
}
signing {
val signingKey: String? by project
val signingPassword: String? by project
useInMemoryPgpKeys(signingKey, signingPassword)
sign(publishing.publications)
}

View File

@ -4,8 +4,10 @@ import io.bkbn.kompendium.models.meta.ErrorMap
import io.bkbn.kompendium.models.meta.SchemaMap import io.bkbn.kompendium.models.meta.SchemaMap
import io.bkbn.kompendium.models.oas.OpenApiSpec import io.bkbn.kompendium.models.oas.OpenApiSpec
import io.bkbn.kompendium.models.oas.OpenApiSpecInfo import io.bkbn.kompendium.models.oas.OpenApiSpecInfo
import io.bkbn.kompendium.models.oas.TypedSchema
import io.bkbn.kompendium.path.CorePathCalculator import io.bkbn.kompendium.path.CorePathCalculator
import io.bkbn.kompendium.path.PathCalculator import io.bkbn.kompendium.path.PathCalculator
import kotlin.reflect.KClass
/** /**
* Maintains all state for the Kompendium library * Maintains all state for the Kompendium library
@ -31,4 +33,8 @@ object Kompendium {
) )
cache = emptyMap() cache = emptyMap()
} }
fun addCustomTypeSchema(clazz: KClass<*>, schema: TypedSchema) {
cache = cache.plus(clazz.simpleName!! to schema)
}
} }

View File

@ -49,23 +49,8 @@ object KompendiumPreFlight {
} }
fun addToCache(paramType: KType, requestType: KType, responseType: KType) { fun addToCache(paramType: KType, requestType: KType, responseType: KType) {
gatherSubTypes(requestType).forEach { Kompendium.cache = Kontent.generateKontent(requestType, Kompendium.cache)
Kompendium.cache = Kontent.generateKontent(it, Kompendium.cache) Kompendium.cache = Kontent.generateKontent(responseType, Kompendium.cache)
}
gatherSubTypes(responseType).forEach {
Kompendium.cache = Kontent.generateKontent(it, Kompendium.cache)
}
Kompendium.cache = Kontent.generateParameterKontent(paramType, Kompendium.cache) Kompendium.cache = Kontent.generateParameterKontent(paramType, Kompendium.cache)
} }
private fun gatherSubTypes(type: KType): List<KType> {
val classifier = type.classifier as KClass<*>
return if (classifier.isSealed) {
classifier.sealedSubclasses.map {
it.createType(type.arguments)
}
} else {
listOf(type)
}
}
} }

View File

@ -23,6 +23,8 @@ import kotlin.reflect.full.memberProperties
import kotlin.reflect.jvm.javaField import kotlin.reflect.jvm.javaField
import kotlin.reflect.typeOf import kotlin.reflect.typeOf
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.math.BigDecimal
import java.math.BigInteger
/** /**
* Responsible for generating the schema map that is used to power all object references across the API Spec. * Responsible for generating the schema map that is used to power all object references across the API Spec.
@ -55,7 +57,22 @@ object Kontent {
type: KType, type: KType,
cache: SchemaMap = emptyMap() cache: SchemaMap = emptyMap()
): SchemaMap { ): SchemaMap {
return generateKTypeKontent(type, cache) var newCache = cache
gatherSubTypes(type).forEach {
newCache = generateKTypeKontent(it, newCache)
}
return newCache
}
private fun gatherSubTypes(type: KType): List<KType> {
val classifier = type.classifier as KClass<*>
return if (classifier.isSealed) {
classifier.sealedSubclasses.map {
it.createType(type.arguments)
}
} else {
listOf(type)
}
} }
/** /**
@ -106,6 +123,8 @@ object Kontent {
String::class -> cache.plus(clazz.simpleName!! to SimpleSchema("string")) String::class -> cache.plus(clazz.simpleName!! to SimpleSchema("string"))
Boolean::class -> cache.plus(clazz.simpleName!! to SimpleSchema("boolean")) Boolean::class -> cache.plus(clazz.simpleName!! to SimpleSchema("boolean"))
UUID::class -> cache.plus(clazz.simpleName!! to FormatSchema("uuid", "string")) UUID::class -> cache.plus(clazz.simpleName!! to FormatSchema("uuid", "string"))
BigDecimal::class -> cache.plus(clazz.simpleName!! to FormatSchema("double", "number"))
BigInteger::class -> cache.plus(clazz.simpleName!! to FormatSchema("int64", "integer"))
else -> when { else -> when {
clazz.isSubclassOf(Collection::class) -> handleCollectionType(type, clazz, cache) clazz.isSubclassOf(Collection::class) -> handleCollectionType(type, clazz, cache)
clazz.isSubclassOf(Enum::class) -> handleEnumType(clazz, cache) clazz.isSubclassOf(Enum::class) -> handleEnumType(clazz, cache)
@ -216,11 +235,20 @@ object Kontent {
if (keyType?.classifier != String::class) { if (keyType?.classifier != String::class) {
error("Invalid Map $type: OpenAPI dictionaries must have keys of type String") error("Invalid Map $type: OpenAPI dictionaries must have keys of type String")
} }
val valClassName = (valType?.classifier as KClass<*>).simpleName val valClass = valType?.classifier as KClass<*>
val valClassName = valClass.simpleName
val referenceName = genericNameAdapter(type, clazz) val referenceName = genericNameAdapter(type, clazz)
val valueReference = ReferencedSchema("$COMPONENT_SLUG/$valClassName") val valueReference = when(valClass.isSealed) {
true -> {
val subTypes = gatherSubTypes(valType)
AnyOfReferencedSchema(subTypes.map {
ReferencedSchema(("$COMPONENT_SLUG/${it.getSimpleSlug()}"))
})
}
false -> ReferencedSchema("$COMPONENT_SLUG/$valClassName")
}
val schema = DictionarySchema(additionalProperties = valueReference) val schema = DictionarySchema(additionalProperties = valueReference)
val updatedCache = generateKTypeKontent(valType, cache) val updatedCache = generateKontent(valType, cache)
return updatedCache.plus(referenceName to schema) return updatedCache.plus(referenceName to schema)
} }
@ -236,9 +264,17 @@ object Kontent {
val collectionClass = collectionType.classifier as KClass<*> val collectionClass = collectionType.classifier as KClass<*>
logger.debug("Obtained collection class: $collectionClass") logger.debug("Obtained collection class: $collectionClass")
val referenceName = genericNameAdapter(type, clazz) val referenceName = genericNameAdapter(type, clazz)
val valueReference = ReferencedSchema("${COMPONENT_SLUG}/${collectionClass.simpleName}") val valueReference = when (collectionClass.isSealed) {
true -> {
val subTypes = gatherSubTypes(collectionType)
AnyOfReferencedSchema(subTypes.map {
ReferencedSchema(("$COMPONENT_SLUG/${it.getSimpleSlug()}"))
})
}
false -> ReferencedSchema("${COMPONENT_SLUG}/${collectionClass.simpleName}")
}
val schema = ArraySchema(items = valueReference) val schema = ArraySchema(items = valueReference)
val updatedCache = generateKTypeKontent(collectionType, cache) val updatedCache = generateKontent(collectionType, cache)
return updatedCache.plus(referenceName to schema) return updatedCache.plus(referenceName to schema)
} }
} }

View File

@ -1,20 +1,26 @@
package io.bkbn.kompendium.routes package io.bkbn.kompendium.routes
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import io.bkbn.kompendium.models.oas.OpenApiSpec
import io.ktor.application.call import io.ktor.application.call
import io.ktor.response.respond import io.ktor.response.respondText
import io.ktor.routing.Routing import io.ktor.routing.Routing
import io.ktor.routing.get import io.ktor.routing.get
import io.ktor.routing.route import io.ktor.routing.route
import io.bkbn.kompendium.models.oas.OpenApiSpec
/** /**
* Provides an out-of-the-box route to return the generated [OpenApiSpec] * Provides an out-of-the-box route to return the generated [OpenApiSpec]
* @param oas spec that is returned * @param oas spec that is returned
*/ */
fun Routing.openApi(oas: OpenApiSpec) { fun Routing.openApi(oas: OpenApiSpec) {
val om = ObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.enable(SerializationFeature.INDENT_OUTPUT)
route("/openapi.json") { route("/openapi.json") {
get { get {
call.respond(oas) call.respondText { om.writeValueAsString(oas) }
} }
} }
} }

View File

@ -18,10 +18,11 @@ import io.bkbn.kompendium.routes.openApi
import io.bkbn.kompendium.routes.redoc import io.bkbn.kompendium.routes.redoc
import io.bkbn.kompendium.util.TestHelpers.getFileSnapshot import io.bkbn.kompendium.util.TestHelpers.getFileSnapshot
import io.bkbn.kompendium.util.complexType import io.bkbn.kompendium.util.complexType
import io.bkbn.kompendium.util.configModule import io.bkbn.kompendium.util.jacksonConfigModule
import io.bkbn.kompendium.util.emptyGet import io.bkbn.kompendium.util.emptyGet
import io.bkbn.kompendium.util.genericPolymorphicResponse import io.bkbn.kompendium.util.genericPolymorphicResponse
import io.bkbn.kompendium.util.genericPolymorphicResponseMultipleImpls import io.bkbn.kompendium.util.genericPolymorphicResponseMultipleImpls
import io.bkbn.kompendium.util.kotlinxConfigModule
import io.bkbn.kompendium.util.nestedUnderRootModule import io.bkbn.kompendium.util.nestedUnderRootModule
import io.bkbn.kompendium.util.nonRequiredParamsGet import io.bkbn.kompendium.util.nonRequiredParamsGet
import io.bkbn.kompendium.util.notarizedDeleteModule import io.bkbn.kompendium.util.notarizedDeleteModule
@ -31,6 +32,9 @@ import io.bkbn.kompendium.util.notarizedGetWithNotarizedException
import io.bkbn.kompendium.util.notarizedPostModule import io.bkbn.kompendium.util.notarizedPostModule
import io.bkbn.kompendium.util.notarizedPutModule import io.bkbn.kompendium.util.notarizedPutModule
import io.bkbn.kompendium.util.pathParsingTestModule import io.bkbn.kompendium.util.pathParsingTestModule
import io.bkbn.kompendium.util.polymorphicCollectionResponse
import io.bkbn.kompendium.util.polymorphicInterfaceResponse
import io.bkbn.kompendium.util.polymorphicMapResponse
import io.bkbn.kompendium.util.polymorphicResponse import io.bkbn.kompendium.util.polymorphicResponse
import io.bkbn.kompendium.util.primitives import io.bkbn.kompendium.util.primitives
import io.bkbn.kompendium.util.returnsList import io.bkbn.kompendium.util.returnsList
@ -57,7 +61,7 @@ internal class KompendiumTest {
@Test @Test
fun `Notarized Get records all expected information`() { fun `Notarized Get records all expected information`() {
withTestApplication({ withTestApplication({
configModule() kotlinxConfigModule()
docs() docs()
notarizedGetModule() notarizedGetModule()
}) { }) {
@ -73,7 +77,7 @@ internal class KompendiumTest {
@Test @Test
fun `Notarized Get does not interrupt the pipeline`() { fun `Notarized Get does not interrupt the pipeline`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
notarizedGetModule() notarizedGetModule()
}) { }) {
@ -89,7 +93,7 @@ internal class KompendiumTest {
@Test @Test
fun `Notarized Post records all expected information`() { fun `Notarized Post records all expected information`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
notarizedPostModule() notarizedPostModule()
}) { }) {
@ -105,7 +109,7 @@ internal class KompendiumTest {
@Test @Test
fun `Notarized post does not interrupt the pipeline`() { fun `Notarized post does not interrupt the pipeline`() {
withTestApplication({ withTestApplication({
configModule() kotlinxConfigModule()
docs() docs()
notarizedPostModule() notarizedPostModule()
}) { }) {
@ -121,7 +125,7 @@ internal class KompendiumTest {
@Test @Test
fun `Notarized Put records all expected information`() { fun `Notarized Put records all expected information`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
notarizedPutModule() notarizedPutModule()
}) { }) {
@ -138,7 +142,7 @@ internal class KompendiumTest {
@Test @Test
fun `Notarized put does not interrupt the pipeline`() { fun `Notarized put does not interrupt the pipeline`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
notarizedPutModule() notarizedPutModule()
}) { }) {
@ -154,7 +158,7 @@ internal class KompendiumTest {
@Test @Test
fun `Notarized delete records all expected information`() { fun `Notarized delete records all expected information`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
notarizedDeleteModule() notarizedDeleteModule()
}) { }) {
@ -170,7 +174,7 @@ internal class KompendiumTest {
@Test @Test
fun `Notarized delete does not interrupt the pipeline`() { fun `Notarized delete does not interrupt the pipeline`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
notarizedDeleteModule() notarizedDeleteModule()
}) { }) {
@ -185,7 +189,7 @@ internal class KompendiumTest {
@Test @Test
fun `Path parser stores the expected path`() { fun `Path parser stores the expected path`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
pathParsingTestModule() pathParsingTestModule()
}) { }) {
@ -201,7 +205,7 @@ internal class KompendiumTest {
@Test @Test
fun `Can notarize the root route`() { fun `Can notarize the root route`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
rootModule() rootModule()
}) { }) {
@ -217,7 +221,7 @@ internal class KompendiumTest {
@Test @Test
fun `Can call the root route`() { fun `Can call the root route`() {
withTestApplication({ withTestApplication({
configModule() kotlinxConfigModule()
docs() docs()
rootModule() rootModule()
}) { }) {
@ -233,7 +237,7 @@ internal class KompendiumTest {
@Test @Test
fun `Nested under root module does not append trailing slash`() { fun `Nested under root module does not append trailing slash`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
nestedUnderRootModule() nestedUnderRootModule()
}) { }) {
@ -249,7 +253,7 @@ internal class KompendiumTest {
@Test @Test
fun `Can notarize a trailing slash route`() { fun `Can notarize a trailing slash route`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
trailingSlash() trailingSlash()
}) { }) {
@ -265,7 +269,7 @@ internal class KompendiumTest {
@Test @Test
fun `Can call a trailing slash route`() { fun `Can call a trailing slash route`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
trailingSlash() trailingSlash()
}) { }) {
@ -281,7 +285,7 @@ internal class KompendiumTest {
@Test @Test
fun `Can notarize a complex type`() { fun `Can notarize a complex type`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
complexType() complexType()
}) { }) {
@ -297,7 +301,7 @@ internal class KompendiumTest {
@Test @Test
fun `Can notarize primitives`() { fun `Can notarize primitives`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
primitives() primitives()
}) { }) {
@ -313,7 +317,7 @@ internal class KompendiumTest {
@Test @Test
fun `Can notarize a top level list response`() { fun `Can notarize a top level list response`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
returnsList() returnsList()
}) { }) {
@ -329,7 +333,7 @@ internal class KompendiumTest {
@Test @Test
fun `Can notarize route with no request params and no response body`() { fun `Can notarize route with no request params and no response body`() {
withTestApplication({ withTestApplication({
configModule() kotlinxConfigModule()
docs() docs()
emptyGet() emptyGet()
}) { }) {
@ -345,7 +349,7 @@ internal class KompendiumTest {
@Test @Test
fun `Can notarize route with non-required params`() { fun `Can notarize route with non-required params`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
nonRequiredParamsGet() nonRequiredParamsGet()
}) { }) {
@ -361,7 +365,7 @@ internal class KompendiumTest {
@Test @Test
fun `Generates the expected redoc`() { fun `Generates the expected redoc`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
returnsList() returnsList()
}) { }) {
@ -378,7 +382,7 @@ internal class KompendiumTest {
fun `Generates additional responses when passed a throwable`() { fun `Generates additional responses when passed a throwable`() {
withTestApplication({ withTestApplication({
statusPageModule() statusPageModule()
configModule() jacksonConfigModule()
docs() docs()
notarizedGetWithNotarizedException() notarizedGetWithNotarizedException()
}) { }) {
@ -395,7 +399,7 @@ internal class KompendiumTest {
fun `Generates additional responses when passed multiple throwables`() { fun `Generates additional responses when passed multiple throwables`() {
withTestApplication({ withTestApplication({
statusPageMultiExceptions() statusPageMultiExceptions()
configModule() jacksonConfigModule()
docs() docs()
notarizedGetWithMultipleThrowables() notarizedGetWithMultipleThrowables()
}) { }) {
@ -411,7 +415,7 @@ internal class KompendiumTest {
@Test @Test
fun `Can generate example response and request bodies`() { fun `Can generate example response and request bodies`() {
withTestApplication({ withTestApplication({
configModule() kotlinxConfigModule()
docs() docs()
withExamples() withExamples()
}) { }) {
@ -427,7 +431,7 @@ internal class KompendiumTest {
@Test @Test
fun `Can generate a default parameter value`() { fun `Can generate a default parameter value`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
withDefaultParameter() withDefaultParameter()
}) { }) {
@ -443,7 +447,7 @@ internal class KompendiumTest {
@Test @Test
fun `Can generate a polymorphic response type`() { fun `Can generate a polymorphic response type`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
polymorphicResponse() polymorphicResponse()
}) { }) {
@ -456,10 +460,58 @@ internal class KompendiumTest {
} }
} }
@Test
fun `Can generate a collection with polymorphic response type`() {
withTestApplication({
jacksonConfigModule()
docs()
polymorphicCollectionResponse()
}) {
// do
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
// expect
val expected = getFileSnapshot("polymorphic_list_response.json").trim()
assertEquals(expected, json, "The received json spec should match the expected content")
}
}
@Test
fun `Can generate a map with a polymorphic response type`() {
withTestApplication({
jacksonConfigModule()
docs()
polymorphicMapResponse()
}) {
// do
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
// expect
val expected = getFileSnapshot("polymorphic_map_response.json").trim()
assertEquals(expected, json, "The received json spec should match the expected content")
}
}
@Test
fun `Can generate a polymorphic response from a sealed interface`() {
withTestApplication({
jacksonConfigModule()
docs()
polymorphicInterfaceResponse()
}) {
// do
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
// expect
val expected = getFileSnapshot("sealed_interface_response.json").trim()
assertEquals(expected, json, "The received json spec should match the expected content")
}
}
@Test @Test
fun `Can generate a response type with a generic type`() { fun `Can generate a response type with a generic type`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
simpleGenericResponse() simpleGenericResponse()
}) { }) {
@ -475,7 +527,7 @@ internal class KompendiumTest {
@Test @Test
fun `Can generate a polymorphic response type with generics`() { fun `Can generate a polymorphic response type with generics`() {
withTestApplication({ withTestApplication({
configModule() jacksonConfigModule()
docs() docs()
genericPolymorphicResponse() genericPolymorphicResponse()
}) { }) {
@ -491,7 +543,7 @@ internal class KompendiumTest {
@Test @Test
fun `Absolute Psycho Inheritance Test`() { fun `Absolute Psycho Inheritance Test`() {
withTestApplication({ withTestApplication({
configModule() kotlinxConfigModule()
docs() docs()
genericPolymorphicResponseMultipleImpls() genericPolymorphicResponseMultipleImpls()
}) { }) {

View File

@ -13,15 +13,7 @@ import io.bkbn.kompendium.models.oas.DictionarySchema
import io.bkbn.kompendium.models.oas.FormatSchema import io.bkbn.kompendium.models.oas.FormatSchema
import io.bkbn.kompendium.models.oas.ObjectSchema import io.bkbn.kompendium.models.oas.ObjectSchema
import io.bkbn.kompendium.models.oas.ReferencedSchema import io.bkbn.kompendium.models.oas.ReferencedSchema
import io.bkbn.kompendium.util.ComplexRequest import io.bkbn.kompendium.util.*
import io.bkbn.kompendium.util.TestInvalidMap
import io.bkbn.kompendium.util.TestNestedModel
import io.bkbn.kompendium.util.TestSimpleModel
import io.bkbn.kompendium.util.TestSimpleWithEnumList
import io.bkbn.kompendium.util.TestSimpleWithEnums
import io.bkbn.kompendium.util.TestSimpleWithList
import io.bkbn.kompendium.util.TestSimpleWithMap
import io.bkbn.kompendium.util.TestWithUUID
@ExperimentalStdlibApi @ExperimentalStdlibApi
internal class KontentTest { internal class KontentTest {
@ -45,6 +37,18 @@ internal class KontentTest {
assertEquals(FormatSchema("int64", "integer"), result["Long"]) assertEquals(FormatSchema("int64", "integer"), result["Long"])
} }
@Test
fun `Object with BigDecimal and BigInteger types`() {
// do
val result = generateKontent<TestBigNumberModel>()
// expect
assertEquals(3, result.count())
assertTrue { result.containsKey(TestBigNumberModel::class.simpleName) }
assertEquals(FormatSchema("double", "number"), result["BigDecimal"])
assertEquals(FormatSchema("int64", "integer"), result["BigInteger"])
}
@Test @Test
fun `Objects reference their base types in the cache`() { fun `Objects reference their base types in the cache`() {
// do // do

View File

@ -4,9 +4,13 @@ import java.util.UUID
import io.bkbn.kompendium.annotations.KompendiumField import io.bkbn.kompendium.annotations.KompendiumField
import io.bkbn.kompendium.annotations.KompendiumParam import io.bkbn.kompendium.annotations.KompendiumParam
import io.bkbn.kompendium.annotations.ParamType import io.bkbn.kompendium.annotations.ParamType
import java.math.BigDecimal
import java.math.BigInteger
data class TestSimpleModel(val a: String, val b: Int) data class TestSimpleModel(val a: String, val b: Int)
data class TestBigNumberModel(val a: BigDecimal, val b: BigInteger)
data class TestNestedModel(val inner: TestSimpleModel) data class TestNestedModel(val inner: TestSimpleModel)
data class TestSimpleWithEnums(val a: String, val b: SimpleEnum) data class TestSimpleWithEnums(val a: String, val b: SimpleEnum)
@ -80,6 +84,12 @@ sealed class FlibbityGibbit
data class SimpleGibbit(val a: String) : FlibbityGibbit() data class SimpleGibbit(val a: String) : FlibbityGibbit()
data class ComplexGibbit(val b: String, val c: Int) : FlibbityGibbit() data class ComplexGibbit(val b: String, val c: Int) : 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> sealed interface Flibbity<T>
data class Gibbity<T>(val a: T): Flibbity<T> data class Gibbity<T>(val a: T): Flibbity<T>

View File

@ -21,8 +21,9 @@ import io.ktor.response.respond
import io.ktor.response.respondText import io.ktor.response.respondText
import io.ktor.routing.route import io.ktor.routing.route
import io.ktor.routing.routing import io.ktor.routing.routing
import io.ktor.serialization.json
fun Application.configModule() { fun Application.jacksonConfigModule() {
install(ContentNegotiation) { install(ContentNegotiation) {
jackson { jackson {
enable(SerializationFeature.INDENT_OUTPUT) enable(SerializationFeature.INDENT_OUTPUT)
@ -31,6 +32,12 @@ fun Application.configModule() {
} }
} }
fun Application.kotlinxConfigModule() {
install(ContentNegotiation) {
json()
}
}
fun Application.statusPageModule() { fun Application.statusPageModule() {
install(StatusPages) { install(StatusPages) {
notarizedException<Exception, ExceptionResponse>( notarizedException<Exception, ExceptionResponse>(
@ -278,6 +285,36 @@ fun Application.polymorphicResponse() {
} }
} }
fun Application.polymorphicCollectionResponse() {
routing {
route("/test/polymorphiclist") {
notarizedGet(TestResponseInfo.polymorphicListResponse) {
call.respond(HttpStatusCode.OK, listOf(SimpleGibbit("hi")))
}
}
}
}
fun Application.polymorphicMapResponse() {
routing {
route("/test/polymorphicmap") {
notarizedGet(TestResponseInfo.polymorphicMapResponse) {
call.respond(HttpStatusCode.OK, listOf(SimpleGibbit("hi")))
}
}
}
}
fun Application.polymorphicInterfaceResponse() {
routing {
route("/test/polymorphicmap") {
notarizedGet(TestResponseInfo.polymorphicInterfaceResponse) {
call.respond(HttpStatusCode.OK, listOf(SimpleGibbit("hi")))
}
}
}
}
fun Application.genericPolymorphicResponse() { fun Application.genericPolymorphicResponse() {
routing { routing {
route("/test/polymorphic") { route("/test/polymorphic") {

View File

@ -78,6 +78,21 @@ object TestResponseInfo {
description = "Polymorphic response", description = "Polymorphic response",
responseInfo = simpleOkResponse() responseInfo = simpleOkResponse()
) )
val polymorphicListResponse = GetInfo<Unit, List<FlibbityGibbit>>(
summary = "Oh so many gibbits",
description = "Polymorphic list response",
responseInfo = simpleOkResponse()
)
val polymorphicMapResponse = GetInfo<Unit, Map<String, FlibbityGibbit>>(
summary = "By gawd that's a lot of gibbits",
description = "Polymorphic list response",
responseInfo = simpleOkResponse()
)
val polymorphicInterfaceResponse = GetInfo<Unit, SlammaJamma>(
summary = "Come on and slam",
description = "and welcome to the jam",
responseInfo = simpleOkResponse()
)
val genericPolymorphicResponse = GetInfo<Unit, Flibbity<TestNested>>( val genericPolymorphicResponse = GetInfo<Unit, Flibbity<TestNested>>(
summary = "More flibbity", summary = "More flibbity",
description = "Polymorphic with generics", description = "Polymorphic with generics",

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -62,24 +62,25 @@
"type" : "string" "type" : "string"
}, },
"SimpleEnum" : { "SimpleEnum" : {
"enum" : [ "ONE", "TWO" ], "type" : "string",
"type" : "string" "enum" : [ "ONE", "TWO" ]
}, },
"CrazyItem" : { "CrazyItem" : {
"type" : "object",
"properties" : { "properties" : {
"enumeration" : { "enumeration" : {
"$ref" : "#/components/schemas/SimpleEnum" "$ref" : "#/components/schemas/SimpleEnum"
} }
}, }
"type" : "object"
}, },
"Map-String-CrazyItem" : { "Map-String-CrazyItem" : {
"type" : "object",
"additionalProperties" : { "additionalProperties" : {
"$ref" : "#/components/schemas/CrazyItem" "$ref" : "#/components/schemas/CrazyItem"
}, }
"type" : "object"
}, },
"NestedComplexItem" : { "NestedComplexItem" : {
"type" : "object",
"properties" : { "properties" : {
"alias" : { "alias" : {
"$ref" : "#/components/schemas/Map-String-CrazyItem" "$ref" : "#/components/schemas/Map-String-CrazyItem"
@ -87,16 +88,16 @@
"name" : { "name" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"List-NestedComplexItem" : { "List-NestedComplexItem" : {
"type" : "array",
"items" : { "items" : {
"$ref" : "#/components/schemas/NestedComplexItem" "$ref" : "#/components/schemas/NestedComplexItem"
}, }
"type" : "array"
}, },
"ComplexRequest" : { "ComplexRequest" : {
"type" : "object",
"properties" : { "properties" : {
"amazingField" : { "amazingField" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
@ -107,14 +108,14 @@
"tables" : { "tables" : {
"$ref" : "#/components/schemas/List-NestedComplexItem" "$ref" : "#/components/schemas/List-NestedComplexItem"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"TestCreatedResponse" : { "TestCreatedResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
@ -122,8 +123,7 @@
"id" : { "id" : {
"$ref" : "#/components/schemas/Int" "$ref" : "#/components/schemas/Int"
} }
}, }
"type" : "object"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -80,22 +80,23 @@
"type" : "string" "type" : "string"
}, },
"TestNested" : { "TestNested" : {
"type" : "object",
"properties" : { "properties" : {
"nesty" : { "nesty" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Gibbity-TestNested" : { "Gibbity-TestNested" : {
"type" : "object",
"properties" : { "properties" : {
"a" : { "a" : {
"$ref" : "#/components/schemas/TestNested" "$ref" : "#/components/schemas/TestNested"
} }
}, }
"type" : "object"
}, },
"Bibbity-TestNested" : { "Bibbity-TestNested" : {
"type" : "object",
"properties" : { "properties" : {
"b" : { "b" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
@ -103,22 +104,22 @@
"f" : { "f" : {
"$ref" : "#/components/schemas/TestNested" "$ref" : "#/components/schemas/TestNested"
} }
}, }
"type" : "object"
}, },
"SimpleGibbit" : { "SimpleGibbit" : {
"type" : "object",
"properties" : { "properties" : {
"a" : { "a" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"ComplexGibbit" : { "ComplexGibbit" : {
"type" : "object",
"properties" : { "properties" : {
"b" : { "b" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
@ -126,10 +127,10 @@
"c" : { "c" : {
"$ref" : "#/components/schemas/Int" "$ref" : "#/components/schemas/Int"
} }
}, }
"type" : "object"
}, },
"Gibbity-FlibbityGibbit" : { "Gibbity-FlibbityGibbit" : {
"type" : "object",
"properties" : { "properties" : {
"a" : { "a" : {
"anyOf" : [ { "anyOf" : [ {
@ -138,10 +139,10 @@
"$ref" : "#/components/schemas/ComplexGibbit" "$ref" : "#/components/schemas/ComplexGibbit"
} ] } ]
} }
}, }
"type" : "object"
}, },
"Bibbity-FlibbityGibbit" : { "Bibbity-FlibbityGibbit" : {
"type" : "object",
"properties" : { "properties" : {
"b" : { "b" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
@ -153,8 +154,7 @@
"$ref" : "#/components/schemas/ComplexGibbit" "$ref" : "#/components/schemas/ComplexGibbit"
} ] } ]
} }
}, }
"type" : "object"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -86,31 +86,32 @@
"components" : { "components" : {
"schemas" : { "schemas" : {
"Long" : { "Long" : {
"format" : "int64", "type" : "integer",
"type" : "integer" "format" : "int64"
}, },
"List-Long" : { "List-Long" : {
"type" : "array",
"items" : { "items" : {
"$ref" : "#/components/schemas/Long" "$ref" : "#/components/schemas/Long"
}, }
"type" : "array"
}, },
"Double" : { "Double" : {
"format" : "double", "type" : "number",
"type" : "number" "format" : "double"
}, },
"String" : { "String" : {
"type" : "string" "type" : "string"
}, },
"TestNested" : { "TestNested" : {
"type" : "object",
"properties" : { "properties" : {
"nesty" : { "nesty" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"TestRequest" : { "TestRequest" : {
"type" : "object",
"properties" : { "properties" : {
"aaa" : { "aaa" : {
"$ref" : "#/components/schemas/List-Long" "$ref" : "#/components/schemas/List-Long"
@ -121,16 +122,15 @@
"fieldName" : { "fieldName" : {
"$ref" : "#/components/schemas/TestNested" "$ref" : "#/components/schemas/TestNested"
} }
}, }
"type" : "object"
}, },
"TestResponse" : { "TestResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -51,10 +51,11 @@
"type" : "string" "type" : "string"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"TestGeneric-Int" : { "TestGeneric-Int" : {
"type" : "object",
"properties" : { "properties" : {
"messy" : { "messy" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
@ -62,8 +63,7 @@
"potato" : { "potato" : {
"$ref" : "#/components/schemas/Int" "$ref" : "#/components/schemas/Int"
} }
}, }
"type" : "object"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa", "name" : "aa",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -68,16 +68,16 @@
"type" : "string" "type" : "string"
}, },
"TestResponse" : { "TestResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa", "name" : "aa",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -61,8 +61,8 @@
"type" : "string" "type" : "string"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa", "name" : "aa",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -68,16 +68,16 @@
"type" : "string" "type" : "string"
}, },
"TestResponse" : { "TestResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa", "name" : "aa",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -78,24 +78,24 @@
"type" : "string" "type" : "string"
}, },
"ExceptionResponse" : { "ExceptionResponse" : {
"type" : "object",
"properties" : { "properties" : {
"message" : { "message" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"TestResponse" : { "TestResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa", "name" : "aa",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -81,24 +81,24 @@
"type" : "string" "type" : "string"
}, },
"ExceptionResponse" : { "ExceptionResponse" : {
"type" : "object",
"properties" : { "properties" : {
"message" : { "message" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"TestResponse" : { "TestResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa", "name" : "aa",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -76,31 +76,32 @@
"components" : { "components" : {
"schemas" : { "schemas" : {
"Long" : { "Long" : {
"format" : "int64", "type" : "integer",
"type" : "integer" "format" : "int64"
}, },
"List-Long" : { "List-Long" : {
"type" : "array",
"items" : { "items" : {
"$ref" : "#/components/schemas/Long" "$ref" : "#/components/schemas/Long"
}, }
"type" : "array"
}, },
"Double" : { "Double" : {
"format" : "double", "type" : "number",
"type" : "number" "format" : "double"
}, },
"String" : { "String" : {
"type" : "string" "type" : "string"
}, },
"TestNested" : { "TestNested" : {
"type" : "object",
"properties" : { "properties" : {
"nesty" : { "nesty" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"TestRequest" : { "TestRequest" : {
"type" : "object",
"properties" : { "properties" : {
"aaa" : { "aaa" : {
"$ref" : "#/components/schemas/List-Long" "$ref" : "#/components/schemas/List-Long"
@ -111,14 +112,14 @@
"fieldName" : { "fieldName" : {
"$ref" : "#/components/schemas/TestNested" "$ref" : "#/components/schemas/TestNested"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"TestCreatedResponse" : { "TestCreatedResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
@ -126,8 +127,7 @@
"id" : { "id" : {
"$ref" : "#/components/schemas/Int" "$ref" : "#/components/schemas/Int"
} }
}, }
"type" : "object"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -59,8 +59,8 @@
"components" : { "components" : {
"schemas" : { "schemas" : {
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"Boolean" : { "Boolean" : {
"type" : "boolean" "type" : "boolean"

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa", "name" : "aa",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -76,31 +76,32 @@
"components" : { "components" : {
"schemas" : { "schemas" : {
"Long" : { "Long" : {
"format" : "int64", "type" : "integer",
"type" : "integer" "format" : "int64"
}, },
"List-Long" : { "List-Long" : {
"type" : "array",
"items" : { "items" : {
"$ref" : "#/components/schemas/Long" "$ref" : "#/components/schemas/Long"
}, }
"type" : "array"
}, },
"Double" : { "Double" : {
"format" : "double", "type" : "number",
"type" : "number" "format" : "double"
}, },
"String" : { "String" : {
"type" : "string" "type" : "string"
}, },
"TestNested" : { "TestNested" : {
"type" : "object",
"properties" : { "properties" : {
"nesty" : { "nesty" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"TestRequest" : { "TestRequest" : {
"type" : "object",
"properties" : { "properties" : {
"aaa" : { "aaa" : {
"$ref" : "#/components/schemas/List-Long" "$ref" : "#/components/schemas/List-Long"
@ -111,14 +112,14 @@
"fieldName" : { "fieldName" : {
"$ref" : "#/components/schemas/TestNested" "$ref" : "#/components/schemas/TestNested"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"TestCreatedResponse" : { "TestCreatedResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
@ -126,8 +127,7 @@
"id" : { "id" : {
"$ref" : "#/components/schemas/Int" "$ref" : "#/components/schemas/Int"
} }
}, }
"type" : "object"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa", "name" : "aa",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -68,16 +68,16 @@
"type" : "string" "type" : "string"
}, },
"TestResponse" : { "TestResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -0,0 +1,91 @@
{
"openapi" : "3.0.3",
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
"url" : "https://gph.is/1NPUDiM",
"email" : "chunkylover53@aol.com"
},
"license" : {
"name" : "MIT",
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers" : [ {
"url" : "https://myawesomeapi.com",
"description" : "Production instance of my API"
}, {
"url" : "https://staging.myawesomeapi.com",
"description" : "Where the fun stuff happens"
} ],
"paths" : {
"/test/polymorphiclist" : {
"get" : {
"tags" : [ ],
"summary" : "Oh so many gibbits",
"description" : "Polymorphic list response",
"parameters" : [ ],
"responses" : {
"200" : {
"description" : "A successful endeavor",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/List-FlibbityGibbit"
}
}
}
}
},
"deprecated" : false
}
}
},
"components" : {
"schemas" : {
"String" : {
"type" : "string"
},
"SimpleGibbit" : {
"type" : "object",
"properties" : {
"a" : {
"$ref" : "#/components/schemas/String"
}
}
},
"Int" : {
"type" : "integer",
"format" : "int32"
},
"ComplexGibbit" : {
"type" : "object",
"properties" : {
"b" : {
"$ref" : "#/components/schemas/String"
},
"c" : {
"$ref" : "#/components/schemas/Int"
}
}
},
"List-FlibbityGibbit" : {
"type" : "array",
"items" : {
"anyOf" : [ {
"$ref" : "#/components/schemas/SimpleGibbit"
}, {
"$ref" : "#/components/schemas/ComplexGibbit"
} ]
}
}
},
"securitySchemes" : { }
},
"security" : [ ],
"tags" : [ ]
}

View File

@ -0,0 +1,91 @@
{
"openapi" : "3.0.3",
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
"url" : "https://gph.is/1NPUDiM",
"email" : "chunkylover53@aol.com"
},
"license" : {
"name" : "MIT",
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers" : [ {
"url" : "https://myawesomeapi.com",
"description" : "Production instance of my API"
}, {
"url" : "https://staging.myawesomeapi.com",
"description" : "Where the fun stuff happens"
} ],
"paths" : {
"/test/polymorphicmap" : {
"get" : {
"tags" : [ ],
"summary" : "By gawd that's a lot of gibbits",
"description" : "Polymorphic list response",
"parameters" : [ ],
"responses" : {
"200" : {
"description" : "A successful endeavor",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/Map-String-FlibbityGibbit"
}
}
}
}
},
"deprecated" : false
}
}
},
"components" : {
"schemas" : {
"String" : {
"type" : "string"
},
"SimpleGibbit" : {
"type" : "object",
"properties" : {
"a" : {
"$ref" : "#/components/schemas/String"
}
}
},
"Int" : {
"type" : "integer",
"format" : "int32"
},
"ComplexGibbit" : {
"type" : "object",
"properties" : {
"b" : {
"$ref" : "#/components/schemas/String"
},
"c" : {
"$ref" : "#/components/schemas/Int"
}
}
},
"Map-String-FlibbityGibbit" : {
"type" : "object",
"additionalProperties" : {
"anyOf" : [ {
"$ref" : "#/components/schemas/SimpleGibbit"
}, {
"$ref" : "#/components/schemas/ComplexGibbit"
} ]
}
}
},
"securitySchemes" : { }
},
"security" : [ ],
"tags" : [ ]
}

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -55,18 +55,19 @@
"type" : "string" "type" : "string"
}, },
"SimpleGibbit" : { "SimpleGibbit" : {
"type" : "object",
"properties" : { "properties" : {
"a" : { "a" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"ComplexGibbit" : { "ComplexGibbit" : {
"type" : "object",
"properties" : { "properties" : {
"b" : { "b" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
@ -74,8 +75,7 @@
"c" : { "c" : {
"$ref" : "#/components/schemas/Int" "$ref" : "#/components/schemas/Int"
} }
}, }
"type" : "object"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -55,22 +55,23 @@
"type" : "string" "type" : "string"
}, },
"TestNested" : { "TestNested" : {
"type" : "object",
"properties" : { "properties" : {
"nesty" : { "nesty" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Gibbity-TestNested" : { "Gibbity-TestNested" : {
"type" : "object",
"properties" : { "properties" : {
"a" : { "a" : {
"$ref" : "#/components/schemas/TestNested" "$ref" : "#/components/schemas/TestNested"
} }
}, }
"type" : "object"
}, },
"Bibbity-TestNested" : { "Bibbity-TestNested" : {
"type" : "object",
"properties" : { "properties" : {
"b" : { "b" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
@ -78,8 +79,7 @@
"f" : { "f" : {
"$ref" : "#/components/schemas/TestNested" "$ref" : "#/components/schemas/TestNested"
} }
}, }
"type" : "object"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -32,9 +32,9 @@
"name" : "a", "name" : "a",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "default" : 100,
"type" : "integer", "type" : "integer",
"default" : 100 "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -65,16 +65,16 @@
"type" : "string" "type" : "string"
}, },
"TestResponse" : { "TestResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"Boolean" : { "Boolean" : {
"type" : "boolean" "type" : "boolean"

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa", "name" : "aa",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -68,22 +68,22 @@
"type" : "string" "type" : "string"
}, },
"TestResponse" : { "TestResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"List-TestResponse" : { "List-TestResponse" : {
"type" : "array",
"items" : { "items" : {
"$ref" : "#/components/schemas/TestResponse" "$ref" : "#/components/schemas/TestResponse"
}, }
"type" : "array"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa", "name" : "aa",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -68,16 +68,16 @@
"type" : "string" "type" : "string"
}, },
"TestResponse" : { "TestResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -0,0 +1,83 @@
{
"openapi" : "3.0.3",
"info" : {
"title" : "Test API",
"version" : "1.33.7",
"description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com",
"contact" : {
"name" : "Homer Simpson",
"url" : "https://gph.is/1NPUDiM",
"email" : "chunkylover53@aol.com"
},
"license" : {
"name" : "MIT",
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers" : [ {
"url" : "https://myawesomeapi.com",
"description" : "Production instance of my API"
}, {
"url" : "https://staging.myawesomeapi.com",
"description" : "Where the fun stuff happens"
} ],
"paths" : {
"/test/polymorphicmap" : {
"get" : {
"tags" : [ ],
"summary" : "Come on and slam",
"description" : "and welcome to the jam",
"parameters" : [ ],
"responses" : {
"200" : {
"description" : "A successful endeavor",
"content" : {
"application/json" : {
"schema" : {
"anyOf" : [ {
"$ref" : "#/components/schemas/OneJamma"
}, {
"$ref" : "#/components/schemas/AnothaJamma"
} ]
}
}
}
}
},
"deprecated" : false
}
}
},
"components" : {
"schemas" : {
"Int" : {
"type" : "integer",
"format" : "int32"
},
"OneJamma" : {
"type" : "object",
"properties" : {
"a" : {
"$ref" : "#/components/schemas/Int"
}
}
},
"Float" : {
"type" : "number",
"format" : "float"
},
"AnothaJamma" : {
"type" : "object",
"properties" : {
"b" : {
"$ref" : "#/components/schemas/Float"
}
}
}
},
"securitySchemes" : { }
},
"security" : [ ],
"tags" : [ ]
}

View File

@ -3,7 +3,7 @@
"info" : { "info" : {
"title" : "Test API", "title" : "Test API",
"version" : "1.33.7", "version" : "1.33.7",
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec", "description" : "An amazing, fully-ish 😉 generated API spec",
"termsOfService" : "https://example.com", "termsOfService" : "https://example.com",
"contact" : { "contact" : {
"name" : "Homer Simpson", "name" : "Homer Simpson",
@ -40,8 +40,8 @@
"name" : "aa", "name" : "aa",
"in" : "query", "in" : "query",
"schema" : { "schema" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
}, },
"required" : true, "required" : true,
"deprecated" : false "deprecated" : false
@ -68,16 +68,16 @@
"type" : "string" "type" : "string"
}, },
"TestResponse" : { "TestResponse" : {
"type" : "object",
"properties" : { "properties" : {
"c" : { "c" : {
"$ref" : "#/components/schemas/String" "$ref" : "#/components/schemas/String"
} }
}, }
"type" : "object"
}, },
"Int" : { "Int" : {
"format" : "int32", "type" : "integer",
"type" : "integer" "format" : "int32"
} }
}, },
"securitySchemes" : { } "securitySchemes" : { }

View File

@ -1,4 +1,5 @@
plugins { plugins {
kotlin("plugin.serialization") version "1.5.0"
application application
} }
@ -11,9 +12,14 @@ dependencies {
implementation(projects.kompendiumSwaggerUi) implementation(projects.kompendiumSwaggerUi)
implementation(libs.bundles.ktor) implementation(libs.bundles.ktor)
implementation(libs.ktor.jackson)
implementation(libs.kotlinx.serialization.json)
implementation(libs.ktor.serialization)
implementation(libs.bundles.ktorAuth) implementation(libs.bundles.ktorAuth)
implementation(libs.bundles.logging) implementation(libs.bundles.logging)
implementation("joda-time:joda-time:2.10.10")
testImplementation("org.jetbrains.kotlin:kotlin-test") testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit") testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
} }

View File

@ -1,24 +1,6 @@
package io.bkbn.kompendium.playground package io.bkbn.kompendium.playground
import com.fasterxml.jackson.annotation.JsonInclude import io.bkbn.kompendium.Kompendium
import com.fasterxml.jackson.databind.SerializationFeature
import io.ktor.application.Application
import io.ktor.application.call
import io.ktor.application.install
import io.ktor.auth.Authentication
import io.ktor.auth.UserIdPrincipal
import io.ktor.auth.authenticate
import io.ktor.features.ContentNegotiation
import io.ktor.features.StatusPages
import io.ktor.http.HttpStatusCode
import io.ktor.jackson.jackson
import io.ktor.response.respond
import io.ktor.response.respondText
import io.ktor.routing.route
import io.ktor.routing.routing
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import io.ktor.webjars.Webjars
import io.bkbn.kompendium.Notarized.notarizedDelete import io.bkbn.kompendium.Notarized.notarizedDelete
import io.bkbn.kompendium.Notarized.notarizedException import io.bkbn.kompendium.Notarized.notarizedException
import io.bkbn.kompendium.Notarized.notarizedGet import io.bkbn.kompendium.Notarized.notarizedGet
@ -26,7 +8,9 @@ import io.bkbn.kompendium.Notarized.notarizedPost
import io.bkbn.kompendium.Notarized.notarizedPut import io.bkbn.kompendium.Notarized.notarizedPut
import io.bkbn.kompendium.auth.KompendiumAuth.notarizedBasic import io.bkbn.kompendium.auth.KompendiumAuth.notarizedBasic
import io.bkbn.kompendium.models.meta.ResponseInfo import io.bkbn.kompendium.models.meta.ResponseInfo
import io.bkbn.kompendium.models.oas.FormatSchema
import io.bkbn.kompendium.playground.PlaygroundToC.testAuthenticatedSingleGetInfo import io.bkbn.kompendium.playground.PlaygroundToC.testAuthenticatedSingleGetInfo
import io.bkbn.kompendium.playground.PlaygroundToC.testCustomOverride
import io.bkbn.kompendium.playground.PlaygroundToC.testGetWithExamples import io.bkbn.kompendium.playground.PlaygroundToC.testGetWithExamples
import io.bkbn.kompendium.playground.PlaygroundToC.testIdGetInfo import io.bkbn.kompendium.playground.PlaygroundToC.testIdGetInfo
import io.bkbn.kompendium.playground.PlaygroundToC.testPostWithExamples import io.bkbn.kompendium.playground.PlaygroundToC.testPostWithExamples
@ -38,8 +22,28 @@ import io.bkbn.kompendium.playground.PlaygroundToC.testSinglePutInfo
import io.bkbn.kompendium.routes.openApi import io.bkbn.kompendium.routes.openApi
import io.bkbn.kompendium.routes.redoc import io.bkbn.kompendium.routes.redoc
import io.bkbn.kompendium.swagger.swaggerUI import io.bkbn.kompendium.swagger.swaggerUI
import io.ktor.application.Application
import io.ktor.application.call
import io.ktor.application.install
import io.ktor.auth.Authentication
import io.ktor.auth.UserIdPrincipal
import io.ktor.auth.authenticate
import io.ktor.features.ContentNegotiation
import io.ktor.features.StatusPages
import io.ktor.http.HttpStatusCode
import io.ktor.response.respond
import io.ktor.response.respondText
import io.ktor.routing.route
import io.ktor.routing.routing
import io.ktor.serialization.json
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import io.ktor.webjars.Webjars
import org.joda.time.DateTime
fun main() { fun main() {
Kompendium.addCustomTypeSchema(DateTime::class, FormatSchema("date-time", "string"))
embeddedServer( embeddedServer(
Netty, Netty,
port = 8081, port = 8081,
@ -52,10 +56,7 @@ var featuresInstalled = false
fun Application.configModule() { fun Application.configModule() {
if (!featuresInstalled) { if (!featuresInstalled) {
install(ContentNegotiation) { install(ContentNegotiation) {
jackson { json()
enable(SerializationFeature.INDENT_OUTPUT)
setSerializationInclusion(JsonInclude.Include.NON_NULL)
}
} }
install(Authentication) { install(Authentication) {
notarizedBasic("basic") { notarizedBasic("basic") {
@ -91,46 +92,51 @@ fun Application.mainModule() {
openApi(oas) openApi(oas)
redoc(oas) redoc(oas)
swaggerUI() swaggerUI()
// route("/potato/spud") { route("/potato/spud") {
// notarizedGet(testGetWithExamples) { notarizedGet(testGetWithExamples) {
// call.respond(HttpStatusCode.OK) call.respond(HttpStatusCode.OK)
// } }
// notarizedPost(testPostWithExamples) { notarizedPost(testPostWithExamples) {
// call.respond(HttpStatusCode.Created, ExampleResponse("hey")) call.respond(HttpStatusCode.Created, ExampleResponse("hey"))
// } }
// } }
route("/test") { route("/test") {
route("/{id}") { route("/{id}") {
notarizedGet(testIdGetInfo) { notarizedGet(testIdGetInfo) {
call.respondText("get by id") call.respondText("get by id")
} }
} }
// route("/single") { route("/single") {
// notarizedGet(testSingleGetInfo) { notarizedGet(testSingleGetInfo) {
// call.respondText("get single") call.respondText("get single")
// } }
// notarizedPost(testSinglePostInfo) { notarizedPost(testSinglePostInfo) {
// call.respondText("test post") call.respondText("test post")
// } }
// notarizedPut(testSinglePutInfo) { notarizedPut(testSinglePutInfo) {
// call.respondText { "hey" } call.respondText { "hey" }
// } }
// notarizedDelete(testSingleDeleteInfo) { notarizedDelete(testSingleDeleteInfo) {
// call.respondText { "heya" } call.respondText { "heya" }
// } }
// } }
// authenticate("basic") { route("custom_override") {
// route("/authenticated/single") { notarizedGet(testCustomOverride) {
// notarizedGet(testAuthenticatedSingleGetInfo) { call.respondText { DateTime.now().toString() }
// call.respond(HttpStatusCode.OK) }
// } }
// } authenticate("basic") {
// } route("/authenticated/single") {
notarizedGet(testAuthenticatedSingleGetInfo) {
call.respond(HttpStatusCode.OK)
}
}
}
}
route("/error") {
notarizedGet(testSingleGetInfoWithThrowable) {
error("bad things just happened")
}
} }
// route("/error") {
// notarizedGet(testSingleGetInfoWithThrowable) {
// error("bad things just happened")
// }
// }
} }
} }

View File

@ -3,6 +3,7 @@ package io.bkbn.kompendium.playground
import io.bkbn.kompendium.annotations.KompendiumField import io.bkbn.kompendium.annotations.KompendiumField
import io.bkbn.kompendium.annotations.KompendiumParam import io.bkbn.kompendium.annotations.KompendiumParam
import io.bkbn.kompendium.annotations.ParamType import io.bkbn.kompendium.annotations.ParamType
import org.joda.time.DateTime
data class ExampleParams( data class ExampleParams(
@KompendiumParam(ParamType.PATH) val id: Int, @KompendiumParam(ParamType.PATH) val id: Int,
@ -30,3 +31,5 @@ data class ExampleResponse(val c: String)
data class ExceptionResponse(val message: String) data class ExceptionResponse(val message: String)
data class ExampleCreatedResponse(val id: Int, val c: String) data class ExampleCreatedResponse(val id: Int, val c: String)
data class DateTimeWrapper(val dt: DateTime)

View File

@ -55,6 +55,15 @@ object PlaygroundToC {
description = "Returns a different sample" description = "Returns a different sample"
) )
) )
val testCustomOverride = MethodInfo.GetInfo<Unit, DateTimeWrapper>(
summary = "custom schema test",
description = "testing",
tags = setOf("custom"),
responseInfo = ResponseInfo(
status = HttpStatusCode.OK,
description = "good tings"
)
)
val testSingleGetInfoWithThrowable = testSingleGetInfo.copy( val testSingleGetInfoWithThrowable = testSingleGetInfo.copy(
summary = "Show me the error baby 🙏", summary = "Show me the error baby 🙏",
canThrow = setOf(Exception::class) canThrow = setOf(Exception::class)

View File

@ -1,6 +1,7 @@
plugins { plugins {
`java-library` `java-library`
`maven-publish` `maven-publish`
signing
} }
dependencies { dependencies {
@ -11,12 +12,13 @@ dependencies {
implementation(libs.webjars.swagger.ui) implementation(libs.webjars.swagger.ui)
testImplementation("org.jetbrains.kotlin:kotlin-test") testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit") testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.12.0") testImplementation(libs.jackson.module.kotlin)
testImplementation("io.ktor:ktor-server-test-host:1.5.3") testImplementation(libs.ktor.server.test.host)
} }
java { java {
withSourcesJar() withSourcesJar()
withJavadocJar()
} }
publishing { publishing {
@ -34,6 +36,41 @@ publishing {
create<MavenPublication>("kompendium") { create<MavenPublication>("kompendium") {
from(components["kotlin"]) from(components["kotlin"])
artifact(tasks.sourcesJar) artifact(tasks.sourcesJar)
artifact(tasks.javadocJar)
groupId = project.group.toString()
artifactId = project.name.toLowerCase()
version = project.version.toString()
pom {
name.set("Kompendium")
description.set("A minimally invasive OpenAPI spec generator for Ktor")
url.set("https://github.com/bkbnio/Kompendium")
licenses {
license {
name.set("MIT License")
url.set("https://mit-license.org/")
}
}
developers {
developer {
id.set("bkbnio")
name.set("Ryan Brink")
email.set("admin@bkbn.io")
}
}
scm {
connection.set("scm:git:git://github.com/bkbnio/Kompendium.git")
developerConnection.set("scm:git:ssh://github.com/bkbnio/Kompendium.git")
url.set("https://github.com/bkbnio/Kompendium.git")
} }
} }
} }
}
}
signing {
val signingKey: String? by project
val signingPassword: String? by project
useInMemoryPgpKeys(signingKey, signingPassword)
sign(publishing.publications)
}