Compare commits
21 Commits
V1.0.0-bet
...
v1.6.0
Author | SHA1 | Date | |
---|---|---|---|
c32c91829b | |||
b021935b10 | |||
3d99bf35fd | |||
c5f8ace5d2 | |||
b0149c293e | |||
925172cf86 | |||
aa3290243b | |||
2e7dad444b | |||
6e56bf7425 | |||
dfc1593022 | |||
5fe98a04e8 | |||
59c0c3aabf | |||
c885ff1cfb | |||
8c206b7ad6 | |||
2bccb1745a | |||
b66c757c51 | |||
1e76a2382d | |||
798ff553b5 | |||
5b71adc323 | |||
5a038697bc | |||
5b99564a75 |
5
.github/workflows/publish.yml
vendored
5
.github/workflows/publish.yml
vendored
@ -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
|
||||||
@ -18,6 +21,6 @@ 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 package
|
- name: Publish package
|
||||||
run: ./gradlew publish
|
run: ./gradlew publishAllPublicationsToGithubPackagesRepository
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
28
.github/workflows/release.yml
vendored
28
.github/workflows/release.yml
vendored
@ -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
|
||||||
@ -19,7 +22,26 @@ jobs:
|
|||||||
path: ~/.gradle/caches
|
path: ~/.gradle/caches
|
||||||
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 package
|
- 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 }}
|
||||||
|
71
CHANGELOG.md
71
CHANGELOG.md
@ -1,5 +1,76 @@
|
|||||||
# 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
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Support for sealed classes 🔥
|
||||||
|
- Support for generic classes ☄️
|
||||||
|
|
||||||
|
## [1.0.1] - May 10th, 2021
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- a word to sweep my rude commit message to Nexus under the rug
|
||||||
|
|
||||||
|
## [1.0.0] - May 9th, 2021
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- SonaType integration to publish to MavenCentral
|
||||||
|
|
||||||
|
### [1.0.0-rc] - May 8th, 2021
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Migrated to io.bkbn group and package name
|
||||||
|
|
||||||
### [1.0.0-beta] - May 6th, 2021
|
### [1.0.0-beta] - May 6th, 2021
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
66
README.md
66
README.md
@ -1,5 +1,7 @@
|
|||||||
# Kompendium
|
# Kompendium
|
||||||
|
|
||||||
|
[](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")
|
||||||
}
|
}
|
||||||
@ -25,12 +45,12 @@ fun RepositoryHandler.github(packageUrl: String) = maven {
|
|||||||
|
|
||||||
// 2 Add the repo in question (in this case Kompendium)
|
// 2 Add the repo in question (in this case Kompendium)
|
||||||
repositories {
|
repositories {
|
||||||
github("https://maven.pkg.github.com/lg-backbone/kompendium")
|
github("https://maven.pkg.github.com/bkbnio/kompendium")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3 Add the package like any normal dependency
|
// 3 Add the package like any normal dependency
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.leafygreens:kompendium-core:0.1.0-SNAPSHOT")
|
implementation("io.bkbn:kompendium-core:1.0.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -76,6 +96,17 @@ The intended purpose of `KompendiumField` is to offer field level overrides such
|
|||||||
The purpose of `KompendiumParam` is to provide supplemental information needed to properly assign the type of parameter
|
The purpose of `KompendiumParam` is to provide supplemental information needed to properly assign the type of parameter
|
||||||
(cookie, header, query, path) as well as other parameter-level metadata.
|
(cookie, header, query, path) as well as other parameter-level metadata.
|
||||||
|
|
||||||
|
### Polymorphism
|
||||||
|
|
||||||
|
Out of the box, Kompendium has support for sealed classes. At runtime, it will build a mapping of all available sub-classes
|
||||||
|
and build a spec that takes `anyOf` the implementations. This is currently a weak point of the entire library, and
|
||||||
|
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
|
||||||
@ -185,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
|
||||||
@ -199,12 +249,10 @@ If this is a blocker, please open a GitHub issue, and we can start to think out
|
|||||||
Work on V1 of Kompendium has come to a close. This, however, does not mean it has achieved complete
|
Work on V1 of Kompendium has come to a close. This, however, does not mean it has achieved complete
|
||||||
parity with the OpenAPI feature spec, nor does it have all-of-the nice to have features that a truly next-gen API spec
|
parity with the OpenAPI feature spec, nor does it have all-of-the nice to have features that a truly next-gen API spec
|
||||||
should have. There are several outstanding features that have been added to the
|
should have. There are several outstanding features that have been added to the
|
||||||
[V2 Milestone](https://github.com/lg-backbone/kompendium/milestone/2). Among others, this includes
|
[V2 Milestone](https://github.com/bkbnio/kompendium/milestone/2). Among others, this includes
|
||||||
|
|
||||||
- Polymorphic support
|
|
||||||
- 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/lg-backbone/kompendium/issues/new)
|
an issue [here](https://github.com/bkbnio/kompendium/issues/new)
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
|
import com.adarshr.gradle.testlogger.TestLoggerExtension
|
||||||
|
import com.adarshr.gradle.testlogger.theme.ThemeType
|
||||||
|
import io.gitlab.arturbosch.detekt.extensions.DetektExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("org.jetbrains.kotlin.jvm") version "1.4.32" apply false
|
id("org.jetbrains.kotlin.jvm") version "1.5.0" apply false
|
||||||
id("io.gitlab.arturbosch.detekt") version "1.16.0-RC2" 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 {
|
||||||
group = "org.leafygreens"
|
group = "io.bkbn"
|
||||||
version = run {
|
version = run {
|
||||||
val baseVersion =
|
val baseVersion =
|
||||||
project.findProperty("project.version") ?: error("project.version must be set in gradle.properties")
|
project.findProperty("project.version") ?: error("project.version needs to be set in gradle.properties")
|
||||||
when ((project.findProperty("release") as? String)?.toBoolean()) {
|
when ((project.findProperty("release") as? String)?.toBoolean()) {
|
||||||
true -> baseVersion
|
true -> baseVersion
|
||||||
else -> "$baseVersion-SNAPSHOT"
|
else -> "$baseVersion-SNAPSHOT"
|
||||||
@ -25,14 +31,14 @@ allprojects {
|
|||||||
apply(plugin = "com.adarshr.test-logger")
|
apply(plugin = "com.adarshr.test-logger")
|
||||||
apply(plugin = "idea")
|
apply(plugin = "idea")
|
||||||
|
|
||||||
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
|
tasks.withType<KotlinCompile>().configureEach {
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "11"
|
jvmTarget = "1.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configure<com.adarshr.gradle.testlogger.TestLoggerExtension> {
|
configure<TestLoggerExtension> {
|
||||||
setTheme("standard")
|
theme = ThemeType.MOCHA
|
||||||
setLogLevel("lifecycle")
|
setLogLevel("lifecycle")
|
||||||
showExceptions = true
|
showExceptions = true
|
||||||
showStackTraces = true
|
showStackTraces = true
|
||||||
@ -50,13 +56,23 @@ allprojects {
|
|||||||
showFailedStandardStreams = true
|
showFailedStandardStreams = true
|
||||||
}
|
}
|
||||||
|
|
||||||
configure<io.gitlab.arturbosch.detekt.extensions.DetektExtension> {
|
configure<DetektExtension> {
|
||||||
toolVersion = "1.16.0-RC2"
|
toolVersion = "1.17.0-RC3"
|
||||||
config = files("${rootProject.projectDir}/detekt.yml")
|
config = files("${rootProject.projectDir}/detekt.yml")
|
||||||
buildUponDefaultConfig = true
|
buildUponDefaultConfig = true
|
||||||
}
|
}
|
||||||
|
|
||||||
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/"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Kompendium
|
# Kompendium
|
||||||
project.version=1.0.0-beta
|
project.version=1.6.0
|
||||||
# Kotlin
|
# Kotlin
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
# Gradle
|
# Gradle
|
||||||
|
@ -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"]
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
|
signing
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -10,21 +11,23 @@ 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 {
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
name = "GithubPackages"
|
name = "GithubPackages"
|
||||||
url = uri("https://maven.pkg.github.com/lg-backbone/kompendium")
|
url = uri("https://maven.pkg.github.com/bkbnio/kompendium")
|
||||||
credentials {
|
credentials {
|
||||||
username = System.getenv("GITHUB_ACTOR")
|
username = System.getenv("GITHUB_ACTOR")
|
||||||
password = System.getenv("GITHUB_TOKEN")
|
password = System.getenv("GITHUB_TOKEN")
|
||||||
@ -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)
|
||||||
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package org.leafygreens.kompendium.auth
|
package io.bkbn.kompendium.auth
|
||||||
|
|
||||||
import io.ktor.auth.AuthenticationRouteSelector
|
import io.ktor.auth.AuthenticationRouteSelector
|
||||||
import io.ktor.routing.Route
|
import io.ktor.routing.Route
|
||||||
import org.leafygreens.kompendium.path.CorePathCalculator
|
import io.bkbn.kompendium.path.CorePathCalculator
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
class AuthPathCalculator : CorePathCalculator() {
|
class AuthPathCalculator : CorePathCalculator() {
|
@ -1,12 +1,12 @@
|
|||||||
package org.leafygreens.kompendium.auth
|
package io.bkbn.kompendium.auth
|
||||||
|
|
||||||
import io.ktor.auth.Authentication
|
import io.ktor.auth.Authentication
|
||||||
import io.ktor.auth.basic
|
import io.ktor.auth.basic
|
||||||
import io.ktor.auth.BasicAuthenticationProvider
|
import io.ktor.auth.BasicAuthenticationProvider
|
||||||
import io.ktor.auth.jwt.jwt
|
import io.ktor.auth.jwt.jwt
|
||||||
import io.ktor.auth.jwt.JWTAuthenticationProvider
|
import io.ktor.auth.jwt.JWTAuthenticationProvider
|
||||||
import org.leafygreens.kompendium.Kompendium
|
import io.bkbn.kompendium.Kompendium
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecSchemaSecurity
|
import io.bkbn.kompendium.models.oas.OpenApiSpecSchemaSecurity
|
||||||
|
|
||||||
object KompendiumAuth {
|
object KompendiumAuth {
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.auth
|
package io.bkbn.kompendium.auth
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude
|
import com.fasterxml.jackson.annotation.JsonInclude
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature
|
import com.fasterxml.jackson.databind.SerializationFeature
|
||||||
@ -21,17 +21,17 @@ import io.ktor.server.testing.withTestApplication
|
|||||||
import kotlin.test.AfterTest
|
import kotlin.test.AfterTest
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.leafygreens.kompendium.Kompendium
|
import io.bkbn.kompendium.Kompendium
|
||||||
import org.leafygreens.kompendium.Notarized.notarizedGet
|
import io.bkbn.kompendium.Notarized.notarizedGet
|
||||||
import org.leafygreens.kompendium.auth.KompendiumAuth.notarizedBasic
|
import io.bkbn.kompendium.auth.KompendiumAuth.notarizedBasic
|
||||||
import org.leafygreens.kompendium.auth.KompendiumAuth.notarizedJwt
|
import io.bkbn.kompendium.auth.KompendiumAuth.notarizedJwt
|
||||||
import org.leafygreens.kompendium.auth.util.TestData
|
import io.bkbn.kompendium.auth.util.TestData
|
||||||
import org.leafygreens.kompendium.auth.util.TestParams
|
import io.bkbn.kompendium.auth.util.TestParams
|
||||||
import org.leafygreens.kompendium.auth.util.TestResponse
|
import io.bkbn.kompendium.auth.util.TestResponse
|
||||||
import org.leafygreens.kompendium.models.meta.MethodInfo
|
import io.bkbn.kompendium.models.meta.MethodInfo
|
||||||
import org.leafygreens.kompendium.models.meta.ResponseInfo
|
import io.bkbn.kompendium.models.meta.ResponseInfo
|
||||||
import org.leafygreens.kompendium.routes.openApi
|
import io.bkbn.kompendium.routes.openApi
|
||||||
import org.leafygreens.kompendium.routes.redoc
|
import io.bkbn.kompendium.routes.redoc
|
||||||
|
|
||||||
internal class KompendiumAuthTest {
|
internal class KompendiumAuthTest {
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.auth.util
|
package io.bkbn.kompendium.auth.util
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
package org.leafygreens.kompendium.auth.util
|
package io.bkbn.kompendium.auth.util
|
||||||
|
|
||||||
import org.leafygreens.kompendium.annotations.KompendiumField
|
import io.bkbn.kompendium.annotations.KompendiumField
|
||||||
import org.leafygreens.kompendium.annotations.KompendiumParam
|
import io.bkbn.kompendium.annotations.KompendiumParam
|
||||||
import org.leafygreens.kompendium.annotations.ParamType
|
import io.bkbn.kompendium.annotations.ParamType
|
||||||
|
|
||||||
data class TestParams(
|
data class TestParams(
|
||||||
@KompendiumParam(ParamType.PATH) val a: String,
|
@KompendiumParam(ParamType.PATH) val a: String,
|
@ -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" : {
|
||||||
|
@ -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" : {
|
||||||
|
@ -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" : {
|
||||||
|
@ -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" : {
|
||||||
|
@ -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" : {
|
||||||
|
@ -1,27 +1,32 @@
|
|||||||
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 {
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
name = "GithubPackages"
|
name = "GithubPackages"
|
||||||
url = uri("https://maven.pkg.github.com/lg-backbone/kompendium")
|
url = uri("https://maven.pkg.github.com/bkbnio/kompendium")
|
||||||
credentials {
|
credentials {
|
||||||
username = System.getenv("GITHUB_ACTOR")
|
username = System.getenv("GITHUB_ACTOR")
|
||||||
password = System.getenv("GITHUB_TOKEN")
|
password = System.getenv("GITHUB_TOKEN")
|
||||||
@ -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)
|
||||||
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package org.leafygreens.kompendium
|
package io.bkbn.kompendium
|
||||||
|
|
||||||
import org.leafygreens.kompendium.models.meta.ErrorMap
|
import io.bkbn.kompendium.models.meta.ErrorMap
|
||||||
import org.leafygreens.kompendium.models.meta.SchemaMap
|
import io.bkbn.kompendium.models.meta.SchemaMap
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpec
|
import io.bkbn.kompendium.models.oas.OpenApiSpec
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecInfo
|
import io.bkbn.kompendium.models.oas.OpenApiSpecInfo
|
||||||
import org.leafygreens.kompendium.path.CorePathCalculator
|
import io.bkbn.kompendium.models.oas.TypedSchema
|
||||||
import org.leafygreens.kompendium.path.PathCalculator
|
import io.bkbn.kompendium.path.CorePathCalculator
|
||||||
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,7 +1,9 @@
|
|||||||
package org.leafygreens.kompendium
|
package io.bkbn.kompendium
|
||||||
|
|
||||||
import io.ktor.routing.Route
|
import io.ktor.routing.Route
|
||||||
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
|
import kotlin.reflect.full.createType
|
||||||
import kotlin.reflect.typeOf
|
import kotlin.reflect.typeOf
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,13 +23,11 @@ object KompendiumPreFlight {
|
|||||||
inline fun <reified TParam : Any, reified TReq : Any, reified TResp : Any> methodNotarizationPreFlight(
|
inline fun <reified TParam : Any, reified TReq : Any, reified TResp : Any> methodNotarizationPreFlight(
|
||||||
block: (KType, KType, KType) -> Route
|
block: (KType, KType, KType) -> Route
|
||||||
): Route {
|
): Route {
|
||||||
Kompendium.cache = Kontent.generateKontent<TResp>(Kompendium.cache)
|
|
||||||
Kompendium.cache = Kontent.generateKontent<TReq>(Kompendium.cache)
|
|
||||||
Kompendium.cache = Kontent.generateParameterKontent<TParam>(Kompendium.cache)
|
|
||||||
Kompendium.openApiSpec.components.schemas.putAll(Kompendium.cache)
|
|
||||||
val requestType = typeOf<TReq>()
|
val requestType = typeOf<TReq>()
|
||||||
val responseType = typeOf<TResp>()
|
val responseType = typeOf<TResp>()
|
||||||
val paramType = typeOf<TParam>()
|
val paramType = typeOf<TParam>()
|
||||||
|
addToCache(paramType, requestType, responseType)
|
||||||
|
Kompendium.openApiSpec.components.schemas.putAll(Kompendium.cache)
|
||||||
return block.invoke(paramType, requestType, responseType)
|
return block.invoke(paramType, requestType, responseType)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,13 +38,19 @@ object KompendiumPreFlight {
|
|||||||
* @param block The function to execute, provided type information of the parameters above
|
* @param block The function to execute, provided type information of the parameters above
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalStdlibApi::class)
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
inline fun <reified TErr: Throwable, reified TResp : Any> errorNotarizationPreFlight(
|
inline fun <reified TErr : Throwable, reified TResp : Any> errorNotarizationPreFlight(
|
||||||
block: (KType, KType) -> Unit
|
block: (KType, KType) -> Unit
|
||||||
) {
|
) {
|
||||||
Kompendium.cache = Kontent.generateKontent<TResp>(Kompendium.cache)
|
|
||||||
Kompendium.openApiSpec.components.schemas.putAll(Kompendium.cache)
|
|
||||||
val errorType = typeOf<TErr>()
|
val errorType = typeOf<TErr>()
|
||||||
val responseType = typeOf<TResp>()
|
val responseType = typeOf<TResp>()
|
||||||
|
addToCache(typeOf<Unit>(), typeOf<Unit>(), responseType)
|
||||||
|
Kompendium.openApiSpec.components.schemas.putAll(Kompendium.cache)
|
||||||
return block.invoke(errorType, responseType)
|
return block.invoke(errorType, responseType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addToCache(paramType: KType, requestType: KType, responseType: KType) {
|
||||||
|
Kompendium.cache = Kontent.generateKontent(requestType, Kompendium.cache)
|
||||||
|
Kompendium.cache = Kontent.generateKontent(responseType, Kompendium.cache)
|
||||||
|
Kompendium.cache = Kontent.generateParameterKontent(paramType, Kompendium.cache)
|
||||||
|
}
|
||||||
}
|
}
|
280
kompendium-core/src/main/kotlin/io/bkbn/kompendium/Kontent.kt
Normal file
280
kompendium-core/src/main/kotlin/io/bkbn/kompendium/Kontent.kt
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
package io.bkbn.kompendium
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.models.meta.SchemaMap
|
||||||
|
import io.bkbn.kompendium.models.oas.AnyOfReferencedSchema
|
||||||
|
import io.bkbn.kompendium.models.oas.ArraySchema
|
||||||
|
import io.bkbn.kompendium.models.oas.DictionarySchema
|
||||||
|
import io.bkbn.kompendium.models.oas.EnumSchema
|
||||||
|
import io.bkbn.kompendium.models.oas.FormatSchema
|
||||||
|
import io.bkbn.kompendium.models.oas.ObjectSchema
|
||||||
|
import io.bkbn.kompendium.models.oas.ReferencedSchema
|
||||||
|
import io.bkbn.kompendium.models.oas.SimpleSchema
|
||||||
|
import io.bkbn.kompendium.util.Helpers.COMPONENT_SLUG
|
||||||
|
import io.bkbn.kompendium.util.Helpers.genericNameAdapter
|
||||||
|
import io.bkbn.kompendium.util.Helpers.getReferenceSlug
|
||||||
|
import io.bkbn.kompendium.util.Helpers.getSimpleSlug
|
||||||
|
import io.bkbn.kompendium.util.Helpers.logged
|
||||||
|
import java.util.UUID
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
import kotlin.reflect.full.createType
|
||||||
|
import kotlin.reflect.full.isSubclassOf
|
||||||
|
import kotlin.reflect.full.memberProperties
|
||||||
|
import kotlin.reflect.jvm.javaField
|
||||||
|
import kotlin.reflect.typeOf
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
object Kontent {
|
||||||
|
|
||||||
|
private val logger = LoggerFactory.getLogger(javaClass)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analyzes a type [T] for its top-level and any nested schemas, and adds them to a [SchemaMap], if provided
|
||||||
|
* @param T type to analyze
|
||||||
|
* @param cache Existing schema map to append to
|
||||||
|
* @return an updated schema map containing all type information for [T]
|
||||||
|
*/
|
||||||
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
|
inline fun <reified T> generateKontent(
|
||||||
|
cache: SchemaMap = emptyMap()
|
||||||
|
): SchemaMap {
|
||||||
|
val kontentType = typeOf<T>()
|
||||||
|
return generateKTypeKontent(kontentType, cache)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analyzes a [KType] for its top-level and any nested schemas, and adds them to a [SchemaMap], if provided
|
||||||
|
* @param type [KType] to analyze
|
||||||
|
* @param cache Existing schema map to append to
|
||||||
|
* @return an updated schema map containing all type information for [KType] type
|
||||||
|
*/
|
||||||
|
fun generateKontent(
|
||||||
|
type: KType,
|
||||||
|
cache: SchemaMap = emptyMap()
|
||||||
|
): SchemaMap {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analyze a type [T], but filters out the top-level type
|
||||||
|
* @param T type to analyze
|
||||||
|
* @param cache Existing schema map to append to
|
||||||
|
* @return an updated schema map containing all type information for [T]
|
||||||
|
*/
|
||||||
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
|
inline fun <reified T> generateParameterKontent(
|
||||||
|
cache: SchemaMap = emptyMap()
|
||||||
|
): SchemaMap {
|
||||||
|
val kontentType = typeOf<T>()
|
||||||
|
return generateKTypeKontent(kontentType, cache)
|
||||||
|
.filterNot { (slug, _) -> slug == (kontentType.classifier as KClass<*>).simpleName }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analyze a type but filters out the top-level type
|
||||||
|
* @param type to analyze
|
||||||
|
* @param cache Existing schema map to append to
|
||||||
|
* @return an updated schema map containing all type information for [T]
|
||||||
|
*/
|
||||||
|
fun generateParameterKontent(
|
||||||
|
type: KType,
|
||||||
|
cache: SchemaMap = emptyMap()
|
||||||
|
): SchemaMap {
|
||||||
|
return generateKTypeKontent(type, cache)
|
||||||
|
.filterNot { (slug, _) -> slug == (type.classifier as KClass<*>).simpleName }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively fills schema map depending on [KType] classifier
|
||||||
|
* @param type [KType] to parse
|
||||||
|
* @param cache Existing schema map to append to
|
||||||
|
*/
|
||||||
|
fun generateKTypeKontent(
|
||||||
|
type: KType,
|
||||||
|
cache: SchemaMap = emptyMap()
|
||||||
|
): SchemaMap = logged(object {}.javaClass.enclosingMethod.name, mapOf("cache" to cache)) {
|
||||||
|
logger.debug("Parsing Kontent of $type")
|
||||||
|
when (val clazz = type.classifier as KClass<*>) {
|
||||||
|
Unit::class -> cache
|
||||||
|
Int::class -> cache.plus(clazz.simpleName!! to FormatSchema("int32", "integer"))
|
||||||
|
Long::class -> cache.plus(clazz.simpleName!! to FormatSchema("int64", "integer"))
|
||||||
|
Double::class -> cache.plus(clazz.simpleName!! to FormatSchema("double", "number"))
|
||||||
|
Float::class -> cache.plus(clazz.simpleName!! to FormatSchema("float", "number"))
|
||||||
|
String::class -> cache.plus(clazz.simpleName!! to SimpleSchema("string"))
|
||||||
|
Boolean::class -> cache.plus(clazz.simpleName!! to SimpleSchema("boolean"))
|
||||||
|
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 {
|
||||||
|
clazz.isSubclassOf(Collection::class) -> handleCollectionType(type, clazz, cache)
|
||||||
|
clazz.isSubclassOf(Enum::class) -> handleEnumType(clazz, cache)
|
||||||
|
clazz.isSubclassOf(Map::class) -> handleMapType(type, clazz, cache)
|
||||||
|
else -> handleComplexType(type, clazz, cache)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In the event of an object type, this method will parse out individual fields to recursively aggregate object map.
|
||||||
|
* @param clazz Class of the object to analyze
|
||||||
|
* @param cache Existing schema map to append to
|
||||||
|
*/
|
||||||
|
private fun handleComplexType(type: KType, clazz: KClass<*>, cache: SchemaMap): SchemaMap {
|
||||||
|
// This needs to be simple because it will be stored under it's appropriate reference component implicitly
|
||||||
|
val slug = type.getSimpleSlug()
|
||||||
|
// Only analyze if component has not already been stored in the cache
|
||||||
|
return when (cache.containsKey(slug)) {
|
||||||
|
true -> {
|
||||||
|
logger.debug("Cache already contains $slug, returning cache untouched")
|
||||||
|
cache
|
||||||
|
}
|
||||||
|
false -> {
|
||||||
|
logger.debug("$slug was not found in cache, generating now")
|
||||||
|
var newCache = cache
|
||||||
|
// Grabs any type parameters as a zip with the corresponding type argument
|
||||||
|
val typeMap = clazz.typeParameters.zip(type.arguments).toMap()
|
||||||
|
// associates each member with a Pair of prop name to property schema
|
||||||
|
val fieldMap = clazz.memberProperties.associate { prop ->
|
||||||
|
logger.debug("Analyzing $prop in class $clazz")
|
||||||
|
// Grab the field of the current property
|
||||||
|
val field = prop.javaField?.type?.kotlin ?: error("Unable to parse field type from $prop")
|
||||||
|
logger.debug("Detected field $field")
|
||||||
|
// Yoinks any generic types from the type map should the field be a generic
|
||||||
|
val yoinkBaseType = if (typeMap.containsKey(prop.returnType.classifier)) {
|
||||||
|
logger.debug("Generic type detected")
|
||||||
|
typeMap[prop.returnType.classifier]?.type!!
|
||||||
|
} else {
|
||||||
|
prop.returnType
|
||||||
|
}
|
||||||
|
// converts the base type to a class
|
||||||
|
val yoinkedClassifier = yoinkBaseType.classifier as KClass<*>
|
||||||
|
// in the event of a sealed class, grab all sealed subclasses and create a type from the base args
|
||||||
|
val yoinkedTypes = if (yoinkedClassifier.isSealed) {
|
||||||
|
yoinkedClassifier.sealedSubclasses.map { it.createType(yoinkBaseType.arguments) }
|
||||||
|
} else {
|
||||||
|
listOf(yoinkBaseType)
|
||||||
|
}
|
||||||
|
// if the most up-to-date cache does not contain the content for this field, generate it and add to cache
|
||||||
|
if (!newCache.containsKey(field.simpleName)) {
|
||||||
|
logger.debug("Cache was missing ${field.simpleName}, adding now")
|
||||||
|
yoinkedTypes.forEach {
|
||||||
|
newCache = generateKTypeKontent(it, newCache)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO This in particular is worthy of a refactor... just not very well written
|
||||||
|
// builds the appropriate property schema based on the property return type
|
||||||
|
val propSchema = if (typeMap.containsKey(prop.returnType.classifier)) {
|
||||||
|
if (yoinkedClassifier.isSealed) {
|
||||||
|
val refs = yoinkedClassifier.sealedSubclasses
|
||||||
|
.map { it.createType(yoinkBaseType.arguments) }
|
||||||
|
.map { ReferencedSchema(it.getReferenceSlug()) }
|
||||||
|
AnyOfReferencedSchema(refs)
|
||||||
|
} else {
|
||||||
|
ReferencedSchema(typeMap[prop.returnType.classifier]?.type!!.getReferenceSlug())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (yoinkedClassifier.isSealed) {
|
||||||
|
val refs = yoinkedClassifier.sealedSubclasses
|
||||||
|
.map { it.createType(yoinkBaseType.arguments) }
|
||||||
|
.map { ReferencedSchema(it.getReferenceSlug()) }
|
||||||
|
AnyOfReferencedSchema(refs)
|
||||||
|
} else {
|
||||||
|
ReferencedSchema(field.getReferenceSlug(prop))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Pair(prop.name, propSchema)
|
||||||
|
}
|
||||||
|
logger.debug("$slug contains $fieldMap")
|
||||||
|
val schema = ObjectSchema(fieldMap)
|
||||||
|
logger.debug("$slug schema: $schema")
|
||||||
|
newCache.plus(slug to schema)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for when an [Enum] is encountered
|
||||||
|
* @param clazz Class of the object to analyze
|
||||||
|
* @param cache Existing schema map to append to
|
||||||
|
*/
|
||||||
|
private fun handleEnumType(clazz: KClass<*>, cache: SchemaMap): SchemaMap {
|
||||||
|
val options = clazz.java.enumConstants.map { it.toString() }.toSet()
|
||||||
|
return cache.plus(clazz.simpleName!! to EnumSchema(options))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for when a [Map] is encountered
|
||||||
|
* @param type Map type information
|
||||||
|
* @param clazz Map class information
|
||||||
|
* @param cache Existing schema map to append to
|
||||||
|
*/
|
||||||
|
private fun handleMapType(type: KType, clazz: KClass<*>, cache: SchemaMap): SchemaMap {
|
||||||
|
logger.debug("Map detected for $type, generating schema and appending to cache")
|
||||||
|
val (keyType, valType) = type.arguments.map { it.type }
|
||||||
|
logger.debug("Obtained map types -> key: $keyType and value: $valType")
|
||||||
|
if (keyType?.classifier != String::class) {
|
||||||
|
error("Invalid Map $type: OpenAPI dictionaries must have keys of type String")
|
||||||
|
}
|
||||||
|
val valClass = valType?.classifier as KClass<*>
|
||||||
|
val valClassName = valClass.simpleName
|
||||||
|
val referenceName = genericNameAdapter(type, clazz)
|
||||||
|
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 updatedCache = generateKontent(valType, cache)
|
||||||
|
return updatedCache.plus(referenceName to schema)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for when a [Collection] is encountered
|
||||||
|
* @param type Collection type information
|
||||||
|
* @param clazz Collection class information
|
||||||
|
* @param cache Existing schema map to append to
|
||||||
|
*/
|
||||||
|
private fun handleCollectionType(type: KType, clazz: KClass<*>, cache: SchemaMap): SchemaMap {
|
||||||
|
logger.debug("Collection detected for $type, generating schema and appending to cache")
|
||||||
|
val collectionType = type.arguments.first().type!!
|
||||||
|
val collectionClass = collectionType.classifier as KClass<*>
|
||||||
|
logger.debug("Obtained collection class: $collectionClass")
|
||||||
|
val referenceName = genericNameAdapter(type, clazz)
|
||||||
|
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 updatedCache = generateKontent(collectionType, cache)
|
||||||
|
return updatedCache.plus(referenceName to schema)
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,22 @@
|
|||||||
package org.leafygreens.kompendium
|
package io.bkbn.kompendium
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.annotations.KompendiumParam
|
||||||
|
import io.bkbn.kompendium.models.meta.MethodInfo
|
||||||
|
import io.bkbn.kompendium.models.meta.RequestInfo
|
||||||
|
import io.bkbn.kompendium.models.meta.ResponseInfo
|
||||||
|
import io.bkbn.kompendium.models.oas.ExampleWrapper
|
||||||
|
import io.bkbn.kompendium.models.oas.OpenApiAnyOf
|
||||||
|
import io.bkbn.kompendium.models.oas.OpenApiSpecMediaType
|
||||||
|
import io.bkbn.kompendium.models.oas.OpenApiSpecParameter
|
||||||
|
import io.bkbn.kompendium.models.oas.OpenApiSpecPathItemOperation
|
||||||
|
import io.bkbn.kompendium.models.oas.OpenApiSpecReferencable
|
||||||
|
import io.bkbn.kompendium.models.oas.OpenApiSpecReferenceObject
|
||||||
|
import io.bkbn.kompendium.models.oas.OpenApiSpecRequest
|
||||||
|
import io.bkbn.kompendium.models.oas.OpenApiSpecResponse
|
||||||
|
import io.bkbn.kompendium.util.Helpers
|
||||||
|
import io.bkbn.kompendium.util.Helpers.getReferenceSlug
|
||||||
|
import io.bkbn.kompendium.util.Helpers.getSimpleSlug
|
||||||
|
import java.util.Locale
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KParameter
|
import kotlin.reflect.KParameter
|
||||||
@ -10,21 +27,6 @@ import kotlin.reflect.full.findAnnotation
|
|||||||
import kotlin.reflect.full.memberProperties
|
import kotlin.reflect.full.memberProperties
|
||||||
import kotlin.reflect.full.primaryConstructor
|
import kotlin.reflect.full.primaryConstructor
|
||||||
import kotlin.reflect.jvm.javaField
|
import kotlin.reflect.jvm.javaField
|
||||||
import org.leafygreens.kompendium.annotations.KompendiumParam
|
|
||||||
import org.leafygreens.kompendium.models.meta.MethodInfo
|
|
||||||
import org.leafygreens.kompendium.models.meta.RequestInfo
|
|
||||||
import org.leafygreens.kompendium.models.meta.ResponseInfo
|
|
||||||
import org.leafygreens.kompendium.models.oas.ExampleWrapper
|
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecMediaType
|
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecParameter
|
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecPathItemOperation
|
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecReferencable
|
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecReferenceObject
|
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecRequest
|
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecResponse
|
|
||||||
import org.leafygreens.kompendium.util.Helpers
|
|
||||||
import org.leafygreens.kompendium.util.Helpers.getReferenceSlug
|
|
||||||
import org.leafygreens.kompendium.util.Helpers.getSimpleSlug
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The MethodParser is responsible for converting route metadata and types into an OpenAPI compatible data class.
|
* The MethodParser is responsible for converting route metadata and types into an OpenAPI compatible data class.
|
||||||
@ -106,7 +108,7 @@ object MethodParser {
|
|||||||
else -> {
|
else -> {
|
||||||
OpenApiSpecRequest(
|
OpenApiSpecRequest(
|
||||||
description = requestInfo.description,
|
description = requestInfo.description,
|
||||||
content = resolveContent(requestInfo.mediaTypes, requestInfo.examples) ?: mapOf()
|
content = resolveContent(this, requestInfo.mediaTypes, requestInfo.examples) ?: mapOf()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,7 +125,7 @@ object MethodParser {
|
|||||||
else -> {
|
else -> {
|
||||||
val specResponse = OpenApiSpecResponse(
|
val specResponse = OpenApiSpecResponse(
|
||||||
description = responseInfo.description,
|
description = responseInfo.description,
|
||||||
content = resolveContent(responseInfo.mediaTypes, responseInfo.examples)
|
content = resolveContent(this, responseInfo.mediaTypes, responseInfo.examples)
|
||||||
)
|
)
|
||||||
Pair(responseInfo.status.value, specResponse)
|
Pair(responseInfo.status.value, specResponse)
|
||||||
}
|
}
|
||||||
@ -131,20 +133,31 @@ object MethodParser {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates MediaTypes along with any examples provided
|
* Generates MediaTypes along with any examples provided
|
||||||
* @receiver [KType] Type of the object
|
* @param type [KType] Type of the object
|
||||||
* @param mediaTypes list of acceptable http media types
|
* @param mediaTypes list of acceptable http media types
|
||||||
* @param examples Mapping of named examples of valid bodies.
|
* @param examples Mapping of named examples of valid bodies.
|
||||||
* @return Named mapping of media types.
|
* @return Named mapping of media types.
|
||||||
*/
|
*/
|
||||||
private fun <F> KType.resolveContent(
|
private fun <F> resolveContent(
|
||||||
|
type: KType,
|
||||||
mediaTypes: List<String>,
|
mediaTypes: List<String>,
|
||||||
examples: Map<String, F>
|
examples: Map<String, F>
|
||||||
): Map<String, OpenApiSpecMediaType<F>>? {
|
): Map<String, OpenApiSpecMediaType<F>>? {
|
||||||
return if (this != Helpers.UNIT_TYPE && mediaTypes.isNotEmpty()) {
|
val classifier = type.classifier as KClass<*>
|
||||||
|
return if (type != Helpers.UNIT_TYPE && mediaTypes.isNotEmpty()) {
|
||||||
mediaTypes.associateWith {
|
mediaTypes.associateWith {
|
||||||
val ref = getReferenceSlug()
|
val schema = if (classifier.isSealed) {
|
||||||
|
val refs = classifier.sealedSubclasses
|
||||||
|
.map { it.createType(type.arguments) }
|
||||||
|
.map { it.getReferenceSlug() }
|
||||||
|
.map { OpenApiSpecReferenceObject(it) }
|
||||||
|
OpenApiAnyOf(refs)
|
||||||
|
} else {
|
||||||
|
val ref = type.getReferenceSlug()
|
||||||
|
OpenApiSpecReferenceObject(ref)
|
||||||
|
}
|
||||||
OpenApiSpecMediaType(
|
OpenApiSpecMediaType(
|
||||||
schema = OpenApiSpecReferenceObject(ref),
|
schema = schema,
|
||||||
examples = examples.mapValues { (_, v) -> ExampleWrapper(v) }.ifEmpty { null }
|
examples = examples.mapValues { (_, v) -> ExampleWrapper(v) }.ifEmpty { null }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -153,7 +166,7 @@ object MethodParser {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a type for all parameter information. All fields in the receiver
|
* Parses a type for all parameter information. All fields in the receiver
|
||||||
* must be annotated with [org.leafygreens.kompendium.annotations.KompendiumParam].
|
* must be annotated with [io.bkbn.kompendium.annotations.KompendiumParam].
|
||||||
* @receiver type
|
* @receiver type
|
||||||
* @return list of valid parameter specs as detailed by the [KType] members
|
* @return list of valid parameter specs as detailed by the [KType] members
|
||||||
* @throws [IllegalStateException] if the class could not be parsed properly
|
* @throws [IllegalStateException] if the class could not be parsed properly
|
||||||
@ -170,7 +183,7 @@ object MethodParser {
|
|||||||
val defaultValue = getDefaultParameterValue(clazz, prop)
|
val defaultValue = getDefaultParameterValue(clazz, prop)
|
||||||
OpenApiSpecParameter(
|
OpenApiSpecParameter(
|
||||||
name = prop.name,
|
name = prop.name,
|
||||||
`in` = anny.type.name.toLowerCase(),
|
`in` = anny.type.name.lowercase(Locale.getDefault()),
|
||||||
schema = schema.addDefault(defaultValue),
|
schema = schema.addDefault(defaultValue),
|
||||||
description = anny.description.ifBlank { null },
|
description = anny.description.ifBlank { null },
|
||||||
required = !prop.returnType.isMarkedNullable
|
required = !prop.returnType.isMarkedNullable
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium
|
package io.bkbn.kompendium
|
||||||
|
|
||||||
import io.ktor.application.ApplicationCall
|
import io.ktor.application.ApplicationCall
|
||||||
import io.ktor.features.StatusPages
|
import io.ktor.features.StatusPages
|
||||||
@ -7,15 +7,15 @@ import io.ktor.routing.Route
|
|||||||
import io.ktor.routing.method
|
import io.ktor.routing.method
|
||||||
import io.ktor.util.pipeline.PipelineContext
|
import io.ktor.util.pipeline.PipelineContext
|
||||||
import io.ktor.util.pipeline.PipelineInterceptor
|
import io.ktor.util.pipeline.PipelineInterceptor
|
||||||
import org.leafygreens.kompendium.KompendiumPreFlight.errorNotarizationPreFlight
|
import io.bkbn.kompendium.KompendiumPreFlight.errorNotarizationPreFlight
|
||||||
import org.leafygreens.kompendium.MethodParser.parseErrorInfo
|
import io.bkbn.kompendium.MethodParser.parseErrorInfo
|
||||||
import org.leafygreens.kompendium.MethodParser.parseMethodInfo
|
import io.bkbn.kompendium.MethodParser.parseMethodInfo
|
||||||
import org.leafygreens.kompendium.models.meta.MethodInfo.GetInfo
|
import io.bkbn.kompendium.models.meta.MethodInfo.GetInfo
|
||||||
import org.leafygreens.kompendium.models.meta.MethodInfo.PostInfo
|
import io.bkbn.kompendium.models.meta.MethodInfo.PostInfo
|
||||||
import org.leafygreens.kompendium.models.meta.MethodInfo.PutInfo
|
import io.bkbn.kompendium.models.meta.MethodInfo.PutInfo
|
||||||
import org.leafygreens.kompendium.models.meta.MethodInfo.DeleteInfo
|
import io.bkbn.kompendium.models.meta.MethodInfo.DeleteInfo
|
||||||
import org.leafygreens.kompendium.models.meta.ResponseInfo
|
import io.bkbn.kompendium.models.meta.ResponseInfo
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecPathItem
|
import io.bkbn.kompendium.models.oas.OpenApiSpecPathItem
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notarization methods are the primary way that a Ktor API using Kompendium differentiates
|
* Notarization methods are the primary way that a Ktor API using Kompendium differentiates
|
||||||
@ -27,7 +27,7 @@ object Notarized {
|
|||||||
/**
|
/**
|
||||||
* Notarization for an HTTP GET request
|
* Notarization for an HTTP GET request
|
||||||
* @param TParam The class containing all parameter fields.
|
* @param TParam The class containing all parameter fields.
|
||||||
* Each field must be annotated with @[org.leafygreens.kompendium.annotations.KompendiumField]
|
* Each field must be annotated with @[io.bkbn.kompendium.annotations.KompendiumField]
|
||||||
* @param TResp Class detailing the expected API response
|
* @param TResp Class detailing the expected API response
|
||||||
* @param info Route metadata
|
* @param info Route metadata
|
||||||
*/
|
*/
|
||||||
@ -45,7 +45,7 @@ object Notarized {
|
|||||||
/**
|
/**
|
||||||
* Notarization for an HTTP POST request
|
* Notarization for an HTTP POST request
|
||||||
* @param TParam The class containing all parameter fields.
|
* @param TParam The class containing all parameter fields.
|
||||||
* Each field must be annotated with @[org.leafygreens.kompendium.annotations.KompendiumField]
|
* Each field must be annotated with @[io.bkbn.kompendium.annotations.KompendiumField]
|
||||||
* @param TReq Class detailing the expected API request body
|
* @param TReq Class detailing the expected API request body
|
||||||
* @param TResp Class detailing the expected API response
|
* @param TResp Class detailing the expected API response
|
||||||
* @param info Route metadata
|
* @param info Route metadata
|
||||||
@ -64,7 +64,7 @@ object Notarized {
|
|||||||
/**
|
/**
|
||||||
* Notarization for an HTTP Delete request
|
* Notarization for an HTTP Delete request
|
||||||
* @param TParam The class containing all parameter fields.
|
* @param TParam The class containing all parameter fields.
|
||||||
* Each field must be annotated with @[org.leafygreens.kompendium.annotations.KompendiumField]
|
* Each field must be annotated with @[io.bkbn.kompendium.annotations.KompendiumField]
|
||||||
* @param TReq Class detailing the expected API request body
|
* @param TReq Class detailing the expected API request body
|
||||||
* @param TResp Class detailing the expected API response
|
* @param TResp Class detailing the expected API response
|
||||||
* @param info Route metadata
|
* @param info Route metadata
|
||||||
@ -84,7 +84,7 @@ object Notarized {
|
|||||||
/**
|
/**
|
||||||
* Notarization for an HTTP POST request
|
* Notarization for an HTTP POST request
|
||||||
* @param TParam The class containing all parameter fields.
|
* @param TParam The class containing all parameter fields.
|
||||||
* Each field must be annotated with @[org.leafygreens.kompendium.annotations.KompendiumField]
|
* Each field must be annotated with @[io.bkbn.kompendium.annotations.KompendiumField]
|
||||||
* @param TResp Class detailing the expected API response
|
* @param TResp Class detailing the expected API response
|
||||||
* @param info Route metadata
|
* @param info Route metadata
|
||||||
*/
|
*/
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.annotations
|
package io.bkbn.kompendium.annotations
|
||||||
|
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
@Target(AnnotationTarget.PROPERTY)
|
@Target(AnnotationTarget.PROPERTY)
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.annotations
|
package io.bkbn.kompendium.annotations
|
||||||
|
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
@Target(AnnotationTarget.PROPERTY)
|
@Target(AnnotationTarget.PROPERTY)
|
@ -0,0 +1,6 @@
|
|||||||
|
package io.bkbn.kompendium.models.meta
|
||||||
|
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
import io.bkbn.kompendium.models.oas.OpenApiSpecResponse
|
||||||
|
|
||||||
|
typealias ErrorMap = Map<KType, Pair<Int, OpenApiSpecResponse<*>>?>
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.meta
|
package io.bkbn.kompendium.models.meta
|
||||||
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.meta
|
package io.bkbn.kompendium.models.meta
|
||||||
|
|
||||||
data class RequestInfo<TReq>(
|
data class RequestInfo<TReq>(
|
||||||
val description: String,
|
val description: String,
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.meta
|
package io.bkbn.kompendium.models.meta
|
||||||
|
|
||||||
import io.ktor.http.HttpStatusCode
|
import io.ktor.http.HttpStatusCode
|
||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
package io.bkbn.kompendium.models.meta
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.models.oas.OpenApiSpecComponentSchema
|
||||||
|
|
||||||
|
typealias SchemaMap = Map<String, OpenApiSpecComponentSchema>
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
data class OpenApiSpec(
|
data class OpenApiSpec(
|
||||||
val openapi: String = "3.0.3",
|
val openapi: String = "3.0.3",
|
@ -1,8 +1,9 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
sealed class OpenApiSpecComponentSchema(open val default: Any? = null) {
|
sealed class OpenApiSpecComponentSchema(open val default: Any? = null) {
|
||||||
|
|
||||||
fun addDefault(default: Any?): OpenApiSpecComponentSchema = when (this) {
|
fun addDefault(default: Any?): OpenApiSpecComponentSchema = when (this) {
|
||||||
|
is AnyOfReferencedSchema -> error("Cannot add default to anyOf reference")
|
||||||
is ReferencedSchema -> this.copy(default = default)
|
is ReferencedSchema -> this.copy(default = default)
|
||||||
is ObjectSchema -> this.copy(default = default)
|
is ObjectSchema -> this.copy(default = default)
|
||||||
is DictionarySchema -> this.copy(default = default)
|
is DictionarySchema -> this.copy(default = default)
|
||||||
@ -17,6 +18,7 @@ sealed class OpenApiSpecComponentSchema(open val default: Any? = null) {
|
|||||||
sealed class TypedSchema(open val type: String, override val default: Any? = null) : OpenApiSpecComponentSchema(default)
|
sealed class TypedSchema(open val type: String, override val default: Any? = null) : OpenApiSpecComponentSchema(default)
|
||||||
|
|
||||||
data class ReferencedSchema(val `$ref`: String, override val default: Any? = null) : OpenApiSpecComponentSchema(default)
|
data class ReferencedSchema(val `$ref`: String, override val default: Any? = null) : OpenApiSpecComponentSchema(default)
|
||||||
|
data class AnyOfReferencedSchema(val anyOf: List<ReferencedSchema>) : OpenApiSpecComponentSchema()
|
||||||
|
|
||||||
data class ObjectSchema(
|
data class ObjectSchema(
|
||||||
val properties: Map<String, OpenApiSpecComponentSchema>,
|
val properties: Map<String, OpenApiSpecComponentSchema>,
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
// TODO I *think* the only thing I need here is the security https://swagger.io/specification/#components-object
|
// TODO I *think* the only thing I need here is the security https://swagger.io/specification/#components-object
|
||||||
data class OpenApiSpecComponents(
|
data class OpenApiSpecComponents(
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
data class OpenApiSpecLink(
|
data class OpenApiSpecLink(
|
||||||
val operationRef: String?, // todo mutually exclusive with operationId
|
val operationRef: String?, // todo mutually exclusive with operationId
|
@ -1,7 +1,7 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
data class OpenApiSpecMediaType<T>(
|
data class OpenApiSpecMediaType<T>(
|
||||||
val schema: OpenApiSpecReferenceObject,
|
val schema: OpenApiSpecReferencable,
|
||||||
val examples: Map<String, ExampleWrapper<T>>? = null
|
val examples: Map<String, ExampleWrapper<T>>? = null
|
||||||
)
|
)
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
data class OpenApiSpecOAuthFlows(
|
data class OpenApiSpecOAuthFlows(
|
||||||
val implicit: OpenApiSpecOAuthFlow?,
|
val implicit: OpenApiSpecOAuthFlow?,
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
data class OpenApiSpecPathItem(
|
data class OpenApiSpecPathItem(
|
||||||
var get: OpenApiSpecPathItemOperation? = null,
|
var get: OpenApiSpecPathItemOperation? = null,
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
data class OpenApiSpecPathItemOperation(
|
data class OpenApiSpecPathItemOperation(
|
||||||
var tags: Set<String> = emptySet(),
|
var tags: Set<String> = emptySet(),
|
@ -1,15 +1,16 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
sealed class OpenApiSpecReferencable
|
sealed interface OpenApiSpecReferencable
|
||||||
|
|
||||||
class OpenApiSpecReferenceObject(val `$ref`: String) : OpenApiSpecReferencable()
|
data class OpenApiAnyOf(val anyOf: List<OpenApiSpecReferenceObject>) : OpenApiSpecReferencable
|
||||||
|
data class OpenApiSpecReferenceObject(val `$ref`: String) : OpenApiSpecReferencable
|
||||||
|
|
||||||
data class OpenApiSpecResponse<T>(
|
data class OpenApiSpecResponse<T>(
|
||||||
val description: String? = null,
|
val description: String? = null,
|
||||||
val headers: Map<String, OpenApiSpecReferencable>? = null,
|
val headers: Map<String, OpenApiSpecReferencable>? = null,
|
||||||
val content: Map<String, OpenApiSpecMediaType<T>>? = null,
|
val content: Map<String, OpenApiSpecMediaType<T>>? = null,
|
||||||
val links: Map<String, OpenApiSpecReferencable>? = null
|
val links: Map<String, OpenApiSpecReferencable>? = null
|
||||||
) : OpenApiSpecReferencable()
|
) : OpenApiSpecReferencable
|
||||||
|
|
||||||
data class OpenApiSpecParameter(
|
data class OpenApiSpecParameter(
|
||||||
val name: String,
|
val name: String,
|
||||||
@ -21,10 +22,10 @@ data class OpenApiSpecParameter(
|
|||||||
val allowEmptyValue: Boolean? = null,
|
val allowEmptyValue: Boolean? = null,
|
||||||
val style: String? = null,
|
val style: String? = null,
|
||||||
val explode: Boolean? = null
|
val explode: Boolean? = null
|
||||||
) : OpenApiSpecReferencable()
|
) : OpenApiSpecReferencable
|
||||||
|
|
||||||
data class OpenApiSpecRequest<T>(
|
data class OpenApiSpecRequest<T>(
|
||||||
val description: String?,
|
val description: String?,
|
||||||
val content: Map<String, OpenApiSpecMediaType<T>>,
|
val content: Map<String, OpenApiSpecMediaType<T>>,
|
||||||
val required: Boolean = false
|
val required: Boolean = false
|
||||||
) : OpenApiSpecReferencable()
|
) : OpenApiSpecReferencable
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
data class OpenApiSpecSchemaSecurity(
|
data class OpenApiSpecSchemaSecurity(
|
||||||
val type: String? = null, // TODO Enum? "apiKey", "http", "oauth2", "openIdConnect"
|
val type: String? = null, // TODO Enum? "apiKey", "http", "oauth2", "openIdConnect"
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
data class OpenApiSpecServerVariable(
|
data class OpenApiSpecServerVariable(
|
||||||
val `enum`: Set<String>, // todo enforce not empty
|
val `enum`: Set<String>, // todo enforce not empty
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.models.oas
|
package io.bkbn.kompendium.models.oas
|
||||||
|
|
||||||
data class OpenApiSpecTag(
|
data class OpenApiSpecTag(
|
||||||
val name: String,
|
val name: String,
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.path
|
package io.bkbn.kompendium.path
|
||||||
|
|
||||||
import io.ktor.routing.PathSegmentConstantRouteSelector
|
import io.ktor.routing.PathSegmentConstantRouteSelector
|
||||||
import io.ktor.routing.PathSegmentParameterRouteSelector
|
import io.ktor.routing.PathSegmentParameterRouteSelector
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.path
|
package io.bkbn.kompendium.path
|
||||||
|
|
||||||
import io.ktor.routing.Route
|
import io.ktor.routing.Route
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
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.response.respondText
|
||||||
|
import io.ktor.routing.Routing
|
||||||
|
import io.ktor.routing.get
|
||||||
|
import io.ktor.routing.route
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides an out-of-the-box route to return the generated [OpenApiSpec]
|
||||||
|
* @param oas spec that is returned
|
||||||
|
*/
|
||||||
|
fun Routing.openApi(oas: OpenApiSpec) {
|
||||||
|
val om = ObjectMapper()
|
||||||
|
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
||||||
|
.enable(SerializationFeature.INDENT_OUTPUT)
|
||||||
|
route("/openapi.json") {
|
||||||
|
get {
|
||||||
|
call.respondText { om.writeValueAsString(oas) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.routes
|
package io.bkbn.kompendium.routes
|
||||||
|
|
||||||
import io.ktor.application.call
|
import io.ktor.application.call
|
||||||
import io.ktor.html.respondHtml
|
import io.ktor.html.respondHtml
|
||||||
@ -13,7 +13,7 @@ import kotlinx.html.script
|
|||||||
import kotlinx.html.style
|
import kotlinx.html.style
|
||||||
import kotlinx.html.title
|
import kotlinx.html.title
|
||||||
import kotlinx.html.unsafe
|
import kotlinx.html.unsafe
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpec
|
import io.bkbn.kompendium.models.oas.OpenApiSpec
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides an out-of-the-box route to view docs using ReDoc
|
* Provides an out-of-the-box route to view docs using ReDoc
|
@ -1,12 +1,12 @@
|
|||||||
package org.leafygreens.kompendium.util
|
package io.bkbn.kompendium.util
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.util.Helpers.getReferenceSlug
|
||||||
import java.lang.reflect.ParameterizedType
|
import java.lang.reflect.ParameterizedType
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
import kotlin.reflect.full.createType
|
import kotlin.reflect.full.createType
|
||||||
import kotlin.reflect.jvm.javaField
|
import kotlin.reflect.jvm.javaField
|
||||||
import org.leafygreens.kompendium.util.Helpers.getReferenceSlug
|
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
object Helpers {
|
object Helpers {
|
||||||
@ -17,27 +17,6 @@ object Helpers {
|
|||||||
|
|
||||||
val UNIT_TYPE by lazy { Unit::class.createType() }
|
val UNIT_TYPE by lazy { Unit::class.createType() }
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple extension function that will take a [Pair] and place it (if absent) into a [MutableMap].
|
|
||||||
*
|
|
||||||
* @receiver [MutableMap]
|
|
||||||
* @param pair to add to map
|
|
||||||
*/
|
|
||||||
fun <K, V> MutableMap<K, V>.putPairIfAbsent(pair: Pair<K, V>) = putIfAbsent(pair.first, pair.second)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple extension function that will convert a list with two items into a [Pair]
|
|
||||||
* @receiver [List]
|
|
||||||
* @return [Pair]
|
|
||||||
* @throws [IllegalArgumentException] when the list size is not exactly two
|
|
||||||
*/
|
|
||||||
fun <T> List<T>.toPair(): Pair<T, T> {
|
|
||||||
if (this.size != 2) {
|
|
||||||
throw IllegalArgumentException("List is not of length 2!")
|
|
||||||
}
|
|
||||||
return Pair(this[0], this[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Higher order function that takes a map of names to objects and will log their state ahead of function invocation
|
* Higher order function that takes a map of names to objects and will log their state ahead of function invocation
|
||||||
* along with the result of the function invocation
|
* along with the result of the function invocation
|
||||||
@ -54,6 +33,11 @@ object Helpers {
|
|||||||
else -> simpleName ?: error("Could not determine simple name for $this")
|
else -> simpleName ?: error("Could not determine simple name for $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
fun KType.getReferenceSlug(): String = when {
|
||||||
arguments.isNotEmpty() -> "$COMPONENT_SLUG/${genericNameAdapter(this, classifier as KClass<*>)}"
|
arguments.isNotEmpty() -> "$COMPONENT_SLUG/${genericNameAdapter(this, classifier as KClass<*>)}"
|
||||||
else -> "$COMPONENT_SLUG/${(classifier as KClass<*>).simpleName}"
|
else -> "$COMPONENT_SLUG/${(classifier as KClass<*>).simpleName}"
|
@ -1,168 +0,0 @@
|
|||||||
package org.leafygreens.kompendium
|
|
||||||
|
|
||||||
import java.util.UUID
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
import kotlin.reflect.KType
|
|
||||||
import kotlin.reflect.full.isSubclassOf
|
|
||||||
import kotlin.reflect.full.memberProperties
|
|
||||||
import kotlin.reflect.jvm.javaField
|
|
||||||
import kotlin.reflect.typeOf
|
|
||||||
import org.leafygreens.kompendium.models.meta.SchemaMap
|
|
||||||
import org.leafygreens.kompendium.models.oas.ArraySchema
|
|
||||||
import org.leafygreens.kompendium.models.oas.DictionarySchema
|
|
||||||
import org.leafygreens.kompendium.models.oas.EnumSchema
|
|
||||||
import org.leafygreens.kompendium.models.oas.FormatSchema
|
|
||||||
import org.leafygreens.kompendium.models.oas.ObjectSchema
|
|
||||||
import org.leafygreens.kompendium.models.oas.ReferencedSchema
|
|
||||||
import org.leafygreens.kompendium.models.oas.SimpleSchema
|
|
||||||
import org.leafygreens.kompendium.util.Helpers.COMPONENT_SLUG
|
|
||||||
import org.leafygreens.kompendium.util.Helpers.genericNameAdapter
|
|
||||||
import org.leafygreens.kompendium.util.Helpers.getReferenceSlug
|
|
||||||
import org.leafygreens.kompendium.util.Helpers.logged
|
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Responsible for generating the schema map that is used to power all object references across the API Spec.
|
|
||||||
*/
|
|
||||||
object Kontent {
|
|
||||||
|
|
||||||
private val logger = LoggerFactory.getLogger(javaClass)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Analyzes a type [T] for its top-level and any nested schemas, and adds them to a [SchemaMap], if provided
|
|
||||||
* @param T type to analyze
|
|
||||||
* @param cache Existing schema map to append to
|
|
||||||
* @return an updated schema map containing all type information for [T]
|
|
||||||
*/
|
|
||||||
@OptIn(ExperimentalStdlibApi::class)
|
|
||||||
inline fun <reified T> generateKontent(
|
|
||||||
cache: SchemaMap = emptyMap()
|
|
||||||
): SchemaMap {
|
|
||||||
val kontentType = typeOf<T>()
|
|
||||||
return generateKTypeKontent(kontentType, cache)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Analyze a type [T], but filters out the top-level type
|
|
||||||
* @param T type to analyze
|
|
||||||
* @param cache Existing schema map to append to
|
|
||||||
* @return an updated schema map containing all type information for [T]
|
|
||||||
*/
|
|
||||||
@OptIn(ExperimentalStdlibApi::class)
|
|
||||||
inline fun <reified T> generateParameterKontent(
|
|
||||||
cache: SchemaMap = emptyMap()
|
|
||||||
): SchemaMap {
|
|
||||||
val kontentType = typeOf<T>()
|
|
||||||
return generateKTypeKontent(kontentType, cache)
|
|
||||||
.filterNot { (slug, _) -> slug == (kontentType.classifier as KClass<*>).simpleName }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursively fills schema map depending on [KType] classifier
|
|
||||||
* @param type [KType] to parse
|
|
||||||
* @param cache Existing schema map to append to
|
|
||||||
*/
|
|
||||||
fun generateKTypeKontent(
|
|
||||||
type: KType,
|
|
||||||
cache: SchemaMap = emptyMap()
|
|
||||||
): SchemaMap = logged(object {}.javaClass.enclosingMethod.name, mapOf("cache" to cache)) {
|
|
||||||
logger.debug("Parsing Kontent of $type")
|
|
||||||
when (val clazz = type.classifier as KClass<*>) {
|
|
||||||
Unit::class -> cache
|
|
||||||
Int::class -> cache.plus(clazz.simpleName!! to FormatSchema("int32", "integer"))
|
|
||||||
Long::class -> cache.plus(clazz.simpleName!! to FormatSchema("int64", "integer"))
|
|
||||||
Double::class -> cache.plus(clazz.simpleName!! to FormatSchema("double", "number"))
|
|
||||||
Float::class -> cache.plus(clazz.simpleName!! to FormatSchema("float", "number"))
|
|
||||||
String::class -> cache.plus(clazz.simpleName!! to SimpleSchema("string"))
|
|
||||||
Boolean::class -> cache.plus(clazz.simpleName!! to SimpleSchema("boolean"))
|
|
||||||
UUID::class -> cache.plus(clazz.simpleName!! to FormatSchema("uuid", "string"))
|
|
||||||
else -> when {
|
|
||||||
clazz.isSubclassOf(Collection::class) -> handleCollectionType(type, clazz, cache)
|
|
||||||
clazz.isSubclassOf(Enum::class) -> handleEnumType(clazz, cache)
|
|
||||||
clazz.isSubclassOf(Map::class) -> handleMapType(type, clazz, cache)
|
|
||||||
else -> handleComplexType(clazz, cache)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* In the event of an object type, this method will parse out individual fields to recursively aggregate object map.
|
|
||||||
* @param clazz Class of the object to analyze
|
|
||||||
* @param cache Existing schema map to append to
|
|
||||||
*/
|
|
||||||
private fun handleComplexType(clazz: KClass<*>, cache: SchemaMap): SchemaMap =
|
|
||||||
when (cache.containsKey(clazz.simpleName)) {
|
|
||||||
true -> {
|
|
||||||
logger.debug("Cache already contains ${clazz.simpleName}, returning cache untouched")
|
|
||||||
cache
|
|
||||||
}
|
|
||||||
false -> {
|
|
||||||
logger.debug("${clazz.simpleName} was not found in cache, generating now")
|
|
||||||
var newCache = cache
|
|
||||||
val fieldMap = clazz.memberProperties.associate { prop ->
|
|
||||||
logger.debug("Analyzing $prop in class $clazz")
|
|
||||||
val field = prop.javaField?.type?.kotlin ?: error("Unable to parse field type from $prop")
|
|
||||||
logger.debug("Detected field $field")
|
|
||||||
if (!newCache.containsKey(field.simpleName)) {
|
|
||||||
logger.debug("Cache was missing ${field.simpleName}, adding now")
|
|
||||||
newCache = generateKTypeKontent(prop.returnType, newCache)
|
|
||||||
}
|
|
||||||
val propSchema = ReferencedSchema(field.getReferenceSlug(prop))
|
|
||||||
Pair(prop.name, propSchema)
|
|
||||||
}
|
|
||||||
logger.debug("${clazz.simpleName} contains $fieldMap")
|
|
||||||
val schema = ObjectSchema(fieldMap)
|
|
||||||
logger.debug("${clazz.simpleName} schema: $schema")
|
|
||||||
newCache.plus(clazz.simpleName!! to schema)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for when an [Enum] is encountered
|
|
||||||
* @param clazz Class of the object to analyze
|
|
||||||
* @param cache Existing schema map to append to
|
|
||||||
*/
|
|
||||||
private fun handleEnumType(clazz: KClass<*>, cache: SchemaMap): SchemaMap {
|
|
||||||
val options = clazz.java.enumConstants.map { it.toString() }.toSet()
|
|
||||||
return cache.plus(clazz.simpleName!! to EnumSchema(options))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for when a [Map] is encountered
|
|
||||||
* @param type Map type information
|
|
||||||
* @param clazz Map class information
|
|
||||||
* @param cache Existing schema map to append to
|
|
||||||
*/
|
|
||||||
private fun handleMapType(type: KType, clazz: KClass<*>, cache: SchemaMap): SchemaMap {
|
|
||||||
logger.debug("Map detected for $type, generating schema and appending to cache")
|
|
||||||
val (keyType, valType) = type.arguments.map { it.type }
|
|
||||||
logger.debug("Obtained map types -> key: $keyType and value: $valType")
|
|
||||||
if (keyType?.classifier != String::class) {
|
|
||||||
error("Invalid Map $type: OpenAPI dictionaries must have keys of type String")
|
|
||||||
}
|
|
||||||
val valClassName = (valType?.classifier as KClass<*>).simpleName
|
|
||||||
val referenceName = genericNameAdapter(type, clazz)
|
|
||||||
val valueReference = ReferencedSchema("$COMPONENT_SLUG/$valClassName")
|
|
||||||
val schema = DictionarySchema(additionalProperties = valueReference)
|
|
||||||
val updatedCache = generateKTypeKontent(valType, cache)
|
|
||||||
return updatedCache.plus(referenceName to schema)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for when a [Collection] is encountered
|
|
||||||
* @param type Collection type information
|
|
||||||
* @param clazz Collection class information
|
|
||||||
* @param cache Existing schema map to append to
|
|
||||||
*/
|
|
||||||
private fun handleCollectionType(type: KType, clazz: KClass<*>, cache: SchemaMap): SchemaMap {
|
|
||||||
logger.debug("Collection detected for $type, generating schema and appending to cache")
|
|
||||||
val collectionType = type.arguments.first().type!!
|
|
||||||
val collectionClass = collectionType.classifier as KClass<*>
|
|
||||||
logger.debug("Obtained collection class: $collectionClass")
|
|
||||||
val referenceName = genericNameAdapter(type, clazz)
|
|
||||||
val valueReference = ReferencedSchema("${COMPONENT_SLUG}/${collectionClass.simpleName}")
|
|
||||||
val schema = ArraySchema(items = valueReference)
|
|
||||||
val updatedCache = generateKTypeKontent(collectionType, cache)
|
|
||||||
return updatedCache.plus(referenceName to schema)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
package org.leafygreens.kompendium.models.meta
|
|
||||||
|
|
||||||
import kotlin.reflect.KType
|
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecResponse
|
|
||||||
|
|
||||||
typealias ErrorMap = Map<KType, Pair<Int, OpenApiSpecResponse<*>>?>
|
|
@ -1,5 +0,0 @@
|
|||||||
package org.leafygreens.kompendium.models.meta
|
|
||||||
|
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecComponentSchema
|
|
||||||
|
|
||||||
typealias SchemaMap = Map<String, OpenApiSpecComponentSchema>
|
|
@ -1,20 +0,0 @@
|
|||||||
package org.leafygreens.kompendium.routes
|
|
||||||
|
|
||||||
import io.ktor.application.call
|
|
||||||
import io.ktor.response.respond
|
|
||||||
import io.ktor.routing.Routing
|
|
||||||
import io.ktor.routing.get
|
|
||||||
import io.ktor.routing.route
|
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpec
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides an out-of-the-box route to return the generated [OpenApiSpec]
|
|
||||||
* @param oas spec that is returned
|
|
||||||
*/
|
|
||||||
fun Routing.openApi(oas: OpenApiSpec) {
|
|
||||||
route("/openapi.json") {
|
|
||||||
get {
|
|
||||||
call.respond(oas)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium
|
package io.bkbn.kompendium
|
||||||
|
|
||||||
import io.ktor.application.Application
|
import io.ktor.application.Application
|
||||||
import io.ktor.http.HttpMethod
|
import io.ktor.http.HttpMethod
|
||||||
@ -10,33 +10,41 @@ import java.net.URI
|
|||||||
import kotlin.test.AfterTest
|
import kotlin.test.AfterTest
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecInfo
|
import io.bkbn.kompendium.models.oas.OpenApiSpecInfo
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecInfoContact
|
import io.bkbn.kompendium.models.oas.OpenApiSpecInfoContact
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecInfoLicense
|
import io.bkbn.kompendium.models.oas.OpenApiSpecInfoLicense
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecServer
|
import io.bkbn.kompendium.models.oas.OpenApiSpecServer
|
||||||
import org.leafygreens.kompendium.routes.openApi
|
import io.bkbn.kompendium.routes.openApi
|
||||||
import org.leafygreens.kompendium.routes.redoc
|
import io.bkbn.kompendium.routes.redoc
|
||||||
import org.leafygreens.kompendium.util.TestHelpers.getFileSnapshot
|
import io.bkbn.kompendium.util.TestHelpers.getFileSnapshot
|
||||||
import org.leafygreens.kompendium.util.complexType
|
import io.bkbn.kompendium.util.complexType
|
||||||
import org.leafygreens.kompendium.util.configModule
|
import io.bkbn.kompendium.util.jacksonConfigModule
|
||||||
import org.leafygreens.kompendium.util.emptyGet
|
import io.bkbn.kompendium.util.emptyGet
|
||||||
import org.leafygreens.kompendium.util.nestedUnderRootModule
|
import io.bkbn.kompendium.util.genericPolymorphicResponse
|
||||||
import org.leafygreens.kompendium.util.nonRequiredParamsGet
|
import io.bkbn.kompendium.util.genericPolymorphicResponseMultipleImpls
|
||||||
import org.leafygreens.kompendium.util.notarizedDeleteModule
|
import io.bkbn.kompendium.util.kotlinxConfigModule
|
||||||
import org.leafygreens.kompendium.util.notarizedGetModule
|
import io.bkbn.kompendium.util.nestedUnderRootModule
|
||||||
import org.leafygreens.kompendium.util.notarizedGetWithMultipleThrowables
|
import io.bkbn.kompendium.util.nonRequiredParamsGet
|
||||||
import org.leafygreens.kompendium.util.notarizedGetWithNotarizedException
|
import io.bkbn.kompendium.util.notarizedDeleteModule
|
||||||
import org.leafygreens.kompendium.util.notarizedPostModule
|
import io.bkbn.kompendium.util.notarizedGetModule
|
||||||
import org.leafygreens.kompendium.util.notarizedPutModule
|
import io.bkbn.kompendium.util.notarizedGetWithMultipleThrowables
|
||||||
import org.leafygreens.kompendium.util.pathParsingTestModule
|
import io.bkbn.kompendium.util.notarizedGetWithNotarizedException
|
||||||
import org.leafygreens.kompendium.util.primitives
|
import io.bkbn.kompendium.util.notarizedPostModule
|
||||||
import org.leafygreens.kompendium.util.returnsList
|
import io.bkbn.kompendium.util.notarizedPutModule
|
||||||
import org.leafygreens.kompendium.util.rootModule
|
import io.bkbn.kompendium.util.pathParsingTestModule
|
||||||
import org.leafygreens.kompendium.util.statusPageModule
|
import io.bkbn.kompendium.util.polymorphicCollectionResponse
|
||||||
import org.leafygreens.kompendium.util.statusPageMultiExceptions
|
import io.bkbn.kompendium.util.polymorphicInterfaceResponse
|
||||||
import org.leafygreens.kompendium.util.trailingSlash
|
import io.bkbn.kompendium.util.polymorphicMapResponse
|
||||||
import org.leafygreens.kompendium.util.withDefaultParameter
|
import io.bkbn.kompendium.util.polymorphicResponse
|
||||||
import org.leafygreens.kompendium.util.withExamples
|
import io.bkbn.kompendium.util.primitives
|
||||||
|
import io.bkbn.kompendium.util.returnsList
|
||||||
|
import io.bkbn.kompendium.util.rootModule
|
||||||
|
import io.bkbn.kompendium.util.simpleGenericResponse
|
||||||
|
import io.bkbn.kompendium.util.statusPageModule
|
||||||
|
import io.bkbn.kompendium.util.statusPageMultiExceptions
|
||||||
|
import io.bkbn.kompendium.util.trailingSlash
|
||||||
|
import io.bkbn.kompendium.util.withDefaultParameter
|
||||||
|
import io.bkbn.kompendium.util.withExamples
|
||||||
|
|
||||||
internal class KompendiumTest {
|
internal class KompendiumTest {
|
||||||
|
|
||||||
@ -53,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()
|
||||||
}) {
|
}) {
|
||||||
@ -69,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()
|
||||||
}) {
|
}) {
|
||||||
@ -85,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()
|
||||||
}) {
|
}) {
|
||||||
@ -101,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()
|
||||||
}) {
|
}) {
|
||||||
@ -117,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()
|
||||||
}) {
|
}) {
|
||||||
@ -134,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()
|
||||||
}) {
|
}) {
|
||||||
@ -150,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()
|
||||||
}) {
|
}) {
|
||||||
@ -166,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()
|
||||||
}) {
|
}) {
|
||||||
@ -181,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()
|
||||||
}) {
|
}) {
|
||||||
@ -197,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()
|
||||||
}) {
|
}) {
|
||||||
@ -213,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()
|
||||||
}) {
|
}) {
|
||||||
@ -229,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()
|
||||||
}) {
|
}) {
|
||||||
@ -245,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()
|
||||||
}) {
|
}) {
|
||||||
@ -261,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()
|
||||||
}) {
|
}) {
|
||||||
@ -277,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()
|
||||||
}) {
|
}) {
|
||||||
@ -293,7 +301,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Can notarize primitives`() {
|
fun `Can notarize primitives`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
primitives()
|
primitives()
|
||||||
}) {
|
}) {
|
||||||
@ -309,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()
|
||||||
}) {
|
}) {
|
||||||
@ -325,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()
|
||||||
}) {
|
}) {
|
||||||
@ -341,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()
|
||||||
}) {
|
}) {
|
||||||
@ -357,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()
|
||||||
}) {
|
}) {
|
||||||
@ -374,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()
|
||||||
}) {
|
}) {
|
||||||
@ -391,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()
|
||||||
}) {
|
}) {
|
||||||
@ -407,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()
|
||||||
}) {
|
}) {
|
||||||
@ -423,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()
|
||||||
}) {
|
}) {
|
||||||
@ -436,6 +444,117 @@ internal class KompendiumTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Can generate a polymorphic response type`() {
|
||||||
|
withTestApplication({
|
||||||
|
jacksonConfigModule()
|
||||||
|
docs()
|
||||||
|
polymorphicResponse()
|
||||||
|
}) {
|
||||||
|
// do
|
||||||
|
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
|
||||||
|
|
||||||
|
// expect
|
||||||
|
val expected = getFileSnapshot("polymorphic_response.json").trim()
|
||||||
|
assertEquals(expected, json, "The received json spec should match the expected content")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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
|
||||||
|
fun `Can generate a response type with a generic type`() {
|
||||||
|
withTestApplication({
|
||||||
|
jacksonConfigModule()
|
||||||
|
docs()
|
||||||
|
simpleGenericResponse()
|
||||||
|
}) {
|
||||||
|
// do
|
||||||
|
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
|
||||||
|
|
||||||
|
// expect
|
||||||
|
val expected = getFileSnapshot("generic_response.json").trim()
|
||||||
|
assertEquals(expected, json, "The received json spec should match the expected content")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Can generate a polymorphic response type with generics`() {
|
||||||
|
withTestApplication({
|
||||||
|
jacksonConfigModule()
|
||||||
|
docs()
|
||||||
|
genericPolymorphicResponse()
|
||||||
|
}) {
|
||||||
|
// do
|
||||||
|
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
|
||||||
|
|
||||||
|
// expect
|
||||||
|
val expected = getFileSnapshot("polymorphic_response_with_generics.json").trim()
|
||||||
|
assertEquals(expected, json, "The received json spec should match the expected content")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Absolute Psycho Inheritance Test`() {
|
||||||
|
withTestApplication({
|
||||||
|
kotlinxConfigModule()
|
||||||
|
docs()
|
||||||
|
genericPolymorphicResponseMultipleImpls()
|
||||||
|
}) {
|
||||||
|
// do
|
||||||
|
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
|
||||||
|
|
||||||
|
// expect
|
||||||
|
val expected = getFileSnapshot("crazy_polymorphic_example.json").trim()
|
||||||
|
assertEquals(expected, json, "The received json spec should match the expected content")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val oas = Kompendium.openApiSpec.copy(
|
private val oas = Kompendium.openApiSpec.copy(
|
||||||
info = OpenApiSpecInfo(
|
info = OpenApiSpecInfo(
|
||||||
@ -450,7 +569,7 @@ internal class KompendiumTest {
|
|||||||
),
|
),
|
||||||
license = OpenApiSpecInfoLicense(
|
license = OpenApiSpecInfoLicense(
|
||||||
name = "MIT",
|
name = "MIT",
|
||||||
url = URI("https://github.com/lg-backbone/kompendium/blob/main/LICENSE")
|
url = URI("https://github.com/bkbnio/kompendium/blob/main/LICENSE")
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
servers = mutableListOf(
|
servers = mutableListOf(
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium
|
package io.bkbn.kompendium
|
||||||
|
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
@ -7,21 +7,13 @@ import kotlin.test.assertFailsWith
|
|||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFalse
|
||||||
import kotlin.test.assertNotNull
|
import kotlin.test.assertNotNull
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
import org.leafygreens.kompendium.Kontent.generateKontent
|
import io.bkbn.kompendium.Kontent.generateKontent
|
||||||
import org.leafygreens.kompendium.Kontent.generateParameterKontent
|
import io.bkbn.kompendium.Kontent.generateParameterKontent
|
||||||
import org.leafygreens.kompendium.models.oas.DictionarySchema
|
import io.bkbn.kompendium.models.oas.DictionarySchema
|
||||||
import org.leafygreens.kompendium.models.oas.FormatSchema
|
import io.bkbn.kompendium.models.oas.FormatSchema
|
||||||
import org.leafygreens.kompendium.models.oas.ObjectSchema
|
import io.bkbn.kompendium.models.oas.ObjectSchema
|
||||||
import org.leafygreens.kompendium.models.oas.ReferencedSchema
|
import io.bkbn.kompendium.models.oas.ReferencedSchema
|
||||||
import org.leafygreens.kompendium.util.ComplexRequest
|
import io.bkbn.kompendium.util.*
|
||||||
import org.leafygreens.kompendium.util.TestInvalidMap
|
|
||||||
import org.leafygreens.kompendium.util.TestNestedModel
|
|
||||||
import org.leafygreens.kompendium.util.TestSimpleModel
|
|
||||||
import org.leafygreens.kompendium.util.TestSimpleWithEnumList
|
|
||||||
import org.leafygreens.kompendium.util.TestSimpleWithEnums
|
|
||||||
import org.leafygreens.kompendium.util.TestSimpleWithList
|
|
||||||
import org.leafygreens.kompendium.util.TestSimpleWithMap
|
|
||||||
import org.leafygreens.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
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.util
|
package io.bkbn.kompendium.util
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
@ -1,15 +1,16 @@
|
|||||||
package org.leafygreens.kompendium.util
|
package io.bkbn.kompendium.util
|
||||||
|
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.reflect.KParameter
|
import io.bkbn.kompendium.annotations.KompendiumField
|
||||||
import kotlin.reflect.full.primaryConstructor
|
import io.bkbn.kompendium.annotations.KompendiumParam
|
||||||
import org.leafygreens.kompendium.MethodParser
|
import io.bkbn.kompendium.annotations.ParamType
|
||||||
import org.leafygreens.kompendium.annotations.KompendiumField
|
import java.math.BigDecimal
|
||||||
import org.leafygreens.kompendium.annotations.KompendiumParam
|
import java.math.BigInteger
|
||||||
import org.leafygreens.kompendium.annotations.ParamType
|
|
||||||
|
|
||||||
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)
|
||||||
@ -40,6 +41,8 @@ data class TestRequest(
|
|||||||
|
|
||||||
data class TestResponse(val c: String)
|
data class TestResponse(val c: String)
|
||||||
|
|
||||||
|
data class TestGeneric<T>(val messy: String, val potato: T)
|
||||||
|
|
||||||
data class TestCreatedResponse(val id: Int, val c: String)
|
data class TestCreatedResponse(val id: Int, val c: String)
|
||||||
|
|
||||||
data class ComplexRequest(
|
data class ComplexRequest(
|
||||||
@ -75,3 +78,19 @@ data class OptionalParams(
|
|||||||
@KompendiumParam(ParamType.QUERY) val required: String,
|
@KompendiumParam(ParamType.QUERY) val required: String,
|
||||||
@KompendiumParam(ParamType.QUERY) val notRequired: String?
|
@KompendiumParam(ParamType.QUERY) val notRequired: String?
|
||||||
)
|
)
|
||||||
|
|
||||||
|
sealed class FlibbityGibbit
|
||||||
|
|
||||||
|
data class SimpleGibbit(val a: String) : 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>
|
||||||
|
|
||||||
|
data class Gibbity<T>(val a: T): Flibbity<T>
|
||||||
|
data class Bibbity<T>(val b: String, val f: T) : Flibbity<T>
|
@ -1,7 +1,15 @@
|
|||||||
package org.leafygreens.kompendium.util
|
package io.bkbn.kompendium.util
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude
|
import com.fasterxml.jackson.annotation.JsonInclude
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature
|
import com.fasterxml.jackson.databind.SerializationFeature
|
||||||
|
import io.bkbn.kompendium.Notarized.notarizedDelete
|
||||||
|
import io.bkbn.kompendium.Notarized.notarizedException
|
||||||
|
import io.bkbn.kompendium.Notarized.notarizedGet
|
||||||
|
import io.bkbn.kompendium.Notarized.notarizedPost
|
||||||
|
import io.bkbn.kompendium.Notarized.notarizedPut
|
||||||
|
import io.bkbn.kompendium.models.meta.MethodInfo
|
||||||
|
import io.bkbn.kompendium.models.meta.RequestInfo
|
||||||
|
import io.bkbn.kompendium.models.meta.ResponseInfo
|
||||||
import io.ktor.application.Application
|
import io.ktor.application.Application
|
||||||
import io.ktor.application.call
|
import io.ktor.application.call
|
||||||
import io.ktor.application.install
|
import io.ktor.application.install
|
||||||
@ -13,16 +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 org.leafygreens.kompendium.Notarized.notarizedDelete
|
import io.ktor.serialization.json
|
||||||
import org.leafygreens.kompendium.Notarized.notarizedException
|
|
||||||
import org.leafygreens.kompendium.Notarized.notarizedGet
|
|
||||||
import org.leafygreens.kompendium.Notarized.notarizedPost
|
|
||||||
import org.leafygreens.kompendium.Notarized.notarizedPut
|
|
||||||
import org.leafygreens.kompendium.models.meta.MethodInfo
|
|
||||||
import org.leafygreens.kompendium.models.meta.RequestInfo
|
|
||||||
import org.leafygreens.kompendium.models.meta.ResponseInfo
|
|
||||||
|
|
||||||
fun Application.configModule() {
|
fun Application.jacksonConfigModule() {
|
||||||
install(ContentNegotiation) {
|
install(ContentNegotiation) {
|
||||||
jackson {
|
jackson {
|
||||||
enable(SerializationFeature.INDENT_OUTPUT)
|
enable(SerializationFeature.INDENT_OUTPUT)
|
||||||
@ -31,9 +32,20 @@ fun Application.configModule() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Application.kotlinxConfigModule() {
|
||||||
|
install(ContentNegotiation) {
|
||||||
|
json()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun Application.statusPageModule() {
|
fun Application.statusPageModule() {
|
||||||
install(StatusPages) {
|
install(StatusPages) {
|
||||||
notarizedException<Exception, ExceptionResponse>(info = ResponseInfo(HttpStatusCode.BadRequest, "Bad Things Happened")) {
|
notarizedException<Exception, ExceptionResponse>(
|
||||||
|
info = ResponseInfo(
|
||||||
|
HttpStatusCode.BadRequest,
|
||||||
|
"Bad Things Happened"
|
||||||
|
)
|
||||||
|
) {
|
||||||
call.respond(HttpStatusCode.BadRequest, ExceptionResponse("Why you do dis?"))
|
call.respond(HttpStatusCode.BadRequest, ExceptionResponse("Why you do dis?"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,10 +53,17 @@ fun Application.statusPageModule() {
|
|||||||
|
|
||||||
fun Application.statusPageMultiExceptions() {
|
fun Application.statusPageMultiExceptions() {
|
||||||
install(StatusPages) {
|
install(StatusPages) {
|
||||||
notarizedException<AccessDeniedException, Unit>(info = ResponseInfo(HttpStatusCode.Forbidden, "New API who dis?")) {
|
notarizedException<AccessDeniedException, Unit>(
|
||||||
|
info = ResponseInfo(HttpStatusCode.Forbidden, "New API who dis?")
|
||||||
|
) {
|
||||||
call.respond(HttpStatusCode.Forbidden)
|
call.respond(HttpStatusCode.Forbidden)
|
||||||
}
|
}
|
||||||
notarizedException<Exception, ExceptionResponse>(info = ResponseInfo(HttpStatusCode.BadRequest, "Bad Things Happened")) {
|
notarizedException<Exception, ExceptionResponse>(
|
||||||
|
info = ResponseInfo(
|
||||||
|
HttpStatusCode.BadRequest,
|
||||||
|
"Bad Things Happened"
|
||||||
|
)
|
||||||
|
) {
|
||||||
call.respond(HttpStatusCode.BadRequest, ExceptionResponse("Why you do dis?"))
|
call.respond(HttpStatusCode.BadRequest, ExceptionResponse("Why you do dis?"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,3 +274,78 @@ fun Application.nonRequiredParamsGet() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Application.polymorphicResponse() {
|
||||||
|
routing {
|
||||||
|
route("/test/polymorphic") {
|
||||||
|
notarizedGet(TestResponseInfo.polymorphicResponse) {
|
||||||
|
call.respond(HttpStatusCode.OK, SimpleGibbit("hey"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
routing {
|
||||||
|
route("/test/polymorphic") {
|
||||||
|
notarizedGet(TestResponseInfo.genericPolymorphicResponse) {
|
||||||
|
call.respond(HttpStatusCode.OK, Gibbity("hey"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Application.genericPolymorphicResponseMultipleImpls() {
|
||||||
|
routing {
|
||||||
|
route("/test/polymorphic") {
|
||||||
|
notarizedGet(TestResponseInfo.genericPolymorphicResponse) {
|
||||||
|
call.respond(HttpStatusCode.OK, Gibbity("hey"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
route("/test/also/poly") {
|
||||||
|
notarizedGet(TestResponseInfo.anotherGenericPolymorphicResponse) {
|
||||||
|
call.respond(HttpStatusCode.OK, Bibbity("test", ComplexGibbit("nice", 1)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Application.simpleGenericResponse() {
|
||||||
|
routing {
|
||||||
|
route("/test/polymorphic") {
|
||||||
|
notarizedGet(TestResponseInfo.genericResponse) {
|
||||||
|
call.respond(HttpStatusCode.OK, Gibbity("hey"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
package io.bkbn.kompendium.util
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.models.meta.MethodInfo.DeleteInfo
|
||||||
|
import io.bkbn.kompendium.models.meta.MethodInfo.GetInfo
|
||||||
|
import io.bkbn.kompendium.models.meta.MethodInfo.PostInfo
|
||||||
|
import io.bkbn.kompendium.models.meta.MethodInfo.PutInfo
|
||||||
|
import io.bkbn.kompendium.models.meta.RequestInfo
|
||||||
|
import io.bkbn.kompendium.models.meta.ResponseInfo
|
||||||
|
import io.ktor.http.HttpStatusCode
|
||||||
|
|
||||||
|
object TestResponseInfo {
|
||||||
|
private val testGetResponse = ResponseInfo<TestResponse>(HttpStatusCode.OK, "A Successful Endeavor")
|
||||||
|
private val testGetListResponse =
|
||||||
|
ResponseInfo<List<TestResponse>>(HttpStatusCode.OK, "A Successful List-y Endeavor")
|
||||||
|
private val testPostResponse = ResponseInfo<TestCreatedResponse>(HttpStatusCode.Created, "A Successful Endeavor")
|
||||||
|
private val testPostResponseAgain = ResponseInfo<Boolean>(HttpStatusCode.Created, "A Successful Endeavor")
|
||||||
|
private val testDeleteResponse =
|
||||||
|
ResponseInfo<Unit>(HttpStatusCode.NoContent, "A Successful Endeavor", mediaTypes = emptyList())
|
||||||
|
private val testRequest = RequestInfo<TestRequest>("A Test request")
|
||||||
|
private val testRequestAgain = RequestInfo<Int>("A Test request")
|
||||||
|
private val complexRequest = RequestInfo<ComplexRequest>("A Complex request")
|
||||||
|
val testGetInfo = GetInfo<TestParams, TestResponse>(
|
||||||
|
summary = "Another get test",
|
||||||
|
description = "testing more",
|
||||||
|
responseInfo = testGetResponse
|
||||||
|
)
|
||||||
|
val testGetInfoAgain = GetInfo<TestParams, List<TestResponse>>(
|
||||||
|
summary = "Another get test",
|
||||||
|
description = "testing more",
|
||||||
|
responseInfo = testGetListResponse
|
||||||
|
)
|
||||||
|
val testGetWithException = testGetInfo.copy(
|
||||||
|
canThrow = setOf(Exception::class)
|
||||||
|
)
|
||||||
|
val testGetWithMultipleExceptions = testGetInfo.copy(
|
||||||
|
canThrow = setOf(AccessDeniedException::class, Exception::class)
|
||||||
|
)
|
||||||
|
val testPostInfo = PostInfo<TestParams, TestRequest, TestCreatedResponse>(
|
||||||
|
summary = "Test post endpoint",
|
||||||
|
description = "Post your tests here!",
|
||||||
|
responseInfo = testPostResponse,
|
||||||
|
requestInfo = testRequest
|
||||||
|
)
|
||||||
|
val testPutInfo = PutInfo<Unit, ComplexRequest, TestCreatedResponse>(
|
||||||
|
summary = "Test put endpoint",
|
||||||
|
description = "Put your tests here!",
|
||||||
|
responseInfo = testPostResponse,
|
||||||
|
requestInfo = complexRequest
|
||||||
|
)
|
||||||
|
val testPutInfoAlso = PutInfo<TestParams, TestRequest, TestCreatedResponse>(
|
||||||
|
summary = "Test put endpoint",
|
||||||
|
description = "Put your tests here!",
|
||||||
|
responseInfo = testPostResponse,
|
||||||
|
requestInfo = testRequest
|
||||||
|
)
|
||||||
|
val testPutInfoAgain = PutInfo<Unit, Int, Boolean>(
|
||||||
|
summary = "Test put endpoint",
|
||||||
|
description = "Put your tests here!",
|
||||||
|
responseInfo = testPostResponseAgain,
|
||||||
|
requestInfo = testRequestAgain
|
||||||
|
)
|
||||||
|
val testDeleteInfo = DeleteInfo<TestParams, Unit>(
|
||||||
|
summary = "Test delete endpoint",
|
||||||
|
description = "testing my deletes",
|
||||||
|
responseInfo = testDeleteResponse
|
||||||
|
)
|
||||||
|
val emptyTestGetInfo =
|
||||||
|
GetInfo<OptionalParams, Unit>(
|
||||||
|
summary = "No request params and response body",
|
||||||
|
description = "testing more"
|
||||||
|
)
|
||||||
|
val trulyEmptyTestGetInfo = GetInfo<Unit, Unit>(
|
||||||
|
summary = "No request params and response body",
|
||||||
|
description = "testing more"
|
||||||
|
)
|
||||||
|
val polymorphicResponse = GetInfo<Unit, FlibbityGibbit>(
|
||||||
|
summary = "All the gibbits",
|
||||||
|
description = "Polymorphic response",
|
||||||
|
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>>(
|
||||||
|
summary = "More flibbity",
|
||||||
|
description = "Polymorphic with generics",
|
||||||
|
responseInfo = simpleOkResponse()
|
||||||
|
)
|
||||||
|
val anotherGenericPolymorphicResponse = GetInfo<Unit, Flibbity<FlibbityGibbit>>(
|
||||||
|
summary = "The Most Flibbity",
|
||||||
|
description = "Polymorphic with generics but like... crazier",
|
||||||
|
responseInfo = simpleOkResponse()
|
||||||
|
)
|
||||||
|
val genericResponse = GetInfo<Unit, TestGeneric<Int>>(
|
||||||
|
summary = "Single Generic",
|
||||||
|
description = "Simple generic data class",
|
||||||
|
responseInfo = simpleOkResponse()
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun <T> simpleOkResponse() = ResponseInfo<T>(HttpStatusCode.OK, "A successful endeavor")
|
||||||
|
}
|
@ -1,71 +0,0 @@
|
|||||||
package org.leafygreens.kompendium.util
|
|
||||||
|
|
||||||
import io.ktor.http.HttpStatusCode
|
|
||||||
import org.leafygreens.kompendium.models.meta.MethodInfo
|
|
||||||
import org.leafygreens.kompendium.models.meta.RequestInfo
|
|
||||||
import org.leafygreens.kompendium.models.meta.ResponseInfo
|
|
||||||
|
|
||||||
object TestResponseInfo {
|
|
||||||
private val testGetResponse = ResponseInfo<TestResponse>(HttpStatusCode.OK, "A Successful Endeavor")
|
|
||||||
private val testGetListResponse =
|
|
||||||
ResponseInfo<List<TestResponse>>(HttpStatusCode.OK, "A Successful List-y Endeavor")
|
|
||||||
private val testPostResponse = ResponseInfo<TestCreatedResponse>(HttpStatusCode.Created, "A Successful Endeavor")
|
|
||||||
private val testPostResponseAgain = ResponseInfo<Boolean>(HttpStatusCode.Created, "A Successful Endeavor")
|
|
||||||
private val testDeleteResponse =
|
|
||||||
ResponseInfo<Unit>(HttpStatusCode.NoContent, "A Successful Endeavor", mediaTypes = emptyList())
|
|
||||||
private val testRequest = RequestInfo<TestRequest>("A Test request")
|
|
||||||
private val testRequestAgain = RequestInfo<Int>("A Test request")
|
|
||||||
private val complexRequest = RequestInfo<ComplexRequest>("A Complex request")
|
|
||||||
val testGetInfo = MethodInfo.GetInfo<TestParams, TestResponse>(
|
|
||||||
summary = "Another get test",
|
|
||||||
description = "testing more",
|
|
||||||
responseInfo = testGetResponse
|
|
||||||
)
|
|
||||||
val testGetInfoAgain = MethodInfo.GetInfo<TestParams, List<TestResponse>>(
|
|
||||||
summary = "Another get test",
|
|
||||||
description = "testing more",
|
|
||||||
responseInfo = testGetListResponse
|
|
||||||
)
|
|
||||||
val testGetWithException = testGetInfo.copy(
|
|
||||||
canThrow = setOf(Exception::class)
|
|
||||||
)
|
|
||||||
val testGetWithMultipleExceptions = testGetInfo.copy(
|
|
||||||
canThrow = setOf(AccessDeniedException::class, Exception::class)
|
|
||||||
)
|
|
||||||
val testPostInfo = MethodInfo.PostInfo<TestParams, TestRequest, TestCreatedResponse>(
|
|
||||||
summary = "Test post endpoint",
|
|
||||||
description = "Post your tests here!",
|
|
||||||
responseInfo = testPostResponse,
|
|
||||||
requestInfo = testRequest
|
|
||||||
)
|
|
||||||
val testPutInfo = MethodInfo.PutInfo<Unit, ComplexRequest, TestCreatedResponse>(
|
|
||||||
summary = "Test put endpoint",
|
|
||||||
description = "Put your tests here!",
|
|
||||||
responseInfo = testPostResponse,
|
|
||||||
requestInfo = complexRequest
|
|
||||||
)
|
|
||||||
val testPutInfoAlso = MethodInfo.PutInfo<TestParams, TestRequest, TestCreatedResponse>(
|
|
||||||
summary = "Test put endpoint",
|
|
||||||
description = "Put your tests here!",
|
|
||||||
responseInfo = testPostResponse,
|
|
||||||
requestInfo = testRequest
|
|
||||||
)
|
|
||||||
val testPutInfoAgain = MethodInfo.PutInfo<Unit, Int, Boolean>(
|
|
||||||
summary = "Test put endpoint",
|
|
||||||
description = "Put your tests here!",
|
|
||||||
responseInfo = testPostResponseAgain,
|
|
||||||
requestInfo = testRequestAgain
|
|
||||||
)
|
|
||||||
val testDeleteInfo = MethodInfo.DeleteInfo<TestParams, Unit>(
|
|
||||||
summary = "Test delete endpoint",
|
|
||||||
description = "testing my deletes",
|
|
||||||
responseInfo = testDeleteResponse
|
|
||||||
)
|
|
||||||
val emptyTestGetInfo =
|
|
||||||
MethodInfo.GetInfo<OptionalParams, Unit>(
|
|
||||||
summary = "No request params and response body",
|
|
||||||
description = "testing more"
|
|
||||||
)
|
|
||||||
val trulyEmptyTestGetInfo =
|
|
||||||
MethodInfo.GetInfo<Unit, Unit>(summary = "No request params and response body", description = "testing more")
|
|
||||||
}
|
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
@ -61,40 +61,26 @@
|
|||||||
"String" : {
|
"String" : {
|
||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"Int" : {
|
|
||||||
"format" : "int32",
|
|
||||||
"type" : "integer"
|
|
||||||
},
|
|
||||||
"TestCreatedResponse" : {
|
|
||||||
"properties" : {
|
|
||||||
"c" : {
|
|
||||||
"$ref" : "#/components/schemas/String"
|
|
||||||
},
|
|
||||||
"id" : {
|
|
||||||
"$ref" : "#/components/schemas/Int"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"type" : "object"
|
|
||||||
},
|
|
||||||
"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"
|
||||||
@ -102,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"
|
||||||
@ -122,8 +108,22 @@
|
|||||||
"tables" : {
|
"tables" : {
|
||||||
"$ref" : "#/components/schemas/List-NestedComplexItem"
|
"$ref" : "#/components/schemas/List-NestedComplexItem"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
},
|
||||||
|
"Int" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"format" : "int32"
|
||||||
|
},
|
||||||
|
"TestCreatedResponse" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"c" : {
|
||||||
|
"$ref" : "#/components/schemas/String"
|
||||||
|
},
|
||||||
|
"id" : {
|
||||||
|
"$ref" : "#/components/schemas/Int"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -0,0 +1,164 @@
|
|||||||
|
{
|
||||||
|
"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/polymorphic" : {
|
||||||
|
"get" : {
|
||||||
|
"tags" : [ ],
|
||||||
|
"summary" : "More flibbity",
|
||||||
|
"description" : "Polymorphic with generics",
|
||||||
|
"parameters" : [ ],
|
||||||
|
"responses" : {
|
||||||
|
"200" : {
|
||||||
|
"description" : "A successful endeavor",
|
||||||
|
"content" : {
|
||||||
|
"application/json" : {
|
||||||
|
"schema" : {
|
||||||
|
"anyOf" : [ {
|
||||||
|
"$ref" : "#/components/schemas/Gibbity-TestNested"
|
||||||
|
}, {
|
||||||
|
"$ref" : "#/components/schemas/Bibbity-TestNested"
|
||||||
|
} ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deprecated" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/test/also/poly" : {
|
||||||
|
"get" : {
|
||||||
|
"tags" : [ ],
|
||||||
|
"summary" : "The Most Flibbity",
|
||||||
|
"description" : "Polymorphic with generics but like... crazier",
|
||||||
|
"parameters" : [ ],
|
||||||
|
"responses" : {
|
||||||
|
"200" : {
|
||||||
|
"description" : "A successful endeavor",
|
||||||
|
"content" : {
|
||||||
|
"application/json" : {
|
||||||
|
"schema" : {
|
||||||
|
"anyOf" : [ {
|
||||||
|
"$ref" : "#/components/schemas/Gibbity-FlibbityGibbit"
|
||||||
|
}, {
|
||||||
|
"$ref" : "#/components/schemas/Bibbity-FlibbityGibbit"
|
||||||
|
} ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deprecated" : false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components" : {
|
||||||
|
"schemas" : {
|
||||||
|
"String" : {
|
||||||
|
"type" : "string"
|
||||||
|
},
|
||||||
|
"TestNested" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"nesty" : {
|
||||||
|
"$ref" : "#/components/schemas/String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Gibbity-TestNested" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"a" : {
|
||||||
|
"$ref" : "#/components/schemas/TestNested"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Bibbity-TestNested" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"b" : {
|
||||||
|
"$ref" : "#/components/schemas/String"
|
||||||
|
},
|
||||||
|
"f" : {
|
||||||
|
"$ref" : "#/components/schemas/TestNested"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Gibbity-FlibbityGibbit" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"a" : {
|
||||||
|
"anyOf" : [ {
|
||||||
|
"$ref" : "#/components/schemas/SimpleGibbit"
|
||||||
|
}, {
|
||||||
|
"$ref" : "#/components/schemas/ComplexGibbit"
|
||||||
|
} ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Bibbity-FlibbityGibbit" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"b" : {
|
||||||
|
"$ref" : "#/components/schemas/String"
|
||||||
|
},
|
||||||
|
"f" : {
|
||||||
|
"anyOf" : [ {
|
||||||
|
"$ref" : "#/components/schemas/SimpleGibbit"
|
||||||
|
}, {
|
||||||
|
"$ref" : "#/components/schemas/ComplexGibbit"
|
||||||
|
} ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"securitySchemes" : { }
|
||||||
|
},
|
||||||
|
"security" : [ ],
|
||||||
|
"tags" : [ ]
|
||||||
|
}
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
@ -85,40 +85,33 @@
|
|||||||
},
|
},
|
||||||
"components" : {
|
"components" : {
|
||||||
"schemas" : {
|
"schemas" : {
|
||||||
|
"Long" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"format" : "int64"
|
||||||
|
},
|
||||||
|
"List-Long" : {
|
||||||
|
"type" : "array",
|
||||||
|
"items" : {
|
||||||
|
"$ref" : "#/components/schemas/Long"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Double" : {
|
||||||
|
"type" : "number",
|
||||||
|
"format" : "double"
|
||||||
|
},
|
||||||
"String" : {
|
"String" : {
|
||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"TestResponse" : {
|
|
||||||
"properties" : {
|
|
||||||
"c" : {
|
|
||||||
"$ref" : "#/components/schemas/String"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"type" : "object"
|
|
||||||
},
|
|
||||||
"Long" : {
|
|
||||||
"format" : "int64",
|
|
||||||
"type" : "integer"
|
|
||||||
},
|
|
||||||
"List-Long" : {
|
|
||||||
"items" : {
|
|
||||||
"$ref" : "#/components/schemas/Long"
|
|
||||||
},
|
|
||||||
"type" : "array"
|
|
||||||
},
|
|
||||||
"Double" : {
|
|
||||||
"format" : "double",
|
|
||||||
"type" : "number"
|
|
||||||
},
|
|
||||||
"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"
|
||||||
@ -129,8 +122,15 @@
|
|||||||
"fieldName" : {
|
"fieldName" : {
|
||||||
"$ref" : "#/components/schemas/TestNested"
|
"$ref" : "#/components/schemas/TestNested"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
},
|
||||||
|
"TestResponse" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"c" : {
|
||||||
|
"$ref" : "#/components/schemas/String"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
73
kompendium-core/src/test/resources/generic_response.json
Normal file
73
kompendium-core/src/test/resources/generic_response.json
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
{
|
||||||
|
"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/polymorphic" : {
|
||||||
|
"get" : {
|
||||||
|
"tags" : [ ],
|
||||||
|
"summary" : "Single Generic",
|
||||||
|
"description" : "Simple generic data class",
|
||||||
|
"parameters" : [ ],
|
||||||
|
"responses" : {
|
||||||
|
"200" : {
|
||||||
|
"description" : "A successful endeavor",
|
||||||
|
"content" : {
|
||||||
|
"application/json" : {
|
||||||
|
"schema" : {
|
||||||
|
"$ref" : "#/components/schemas/TestGeneric-Int"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deprecated" : false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components" : {
|
||||||
|
"schemas" : {
|
||||||
|
"String" : {
|
||||||
|
"type" : "string"
|
||||||
|
},
|
||||||
|
"Int" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"format" : "int32"
|
||||||
|
},
|
||||||
|
"TestGeneric-Int" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"messy" : {
|
||||||
|
"$ref" : "#/components/schemas/String"
|
||||||
|
},
|
||||||
|
"potato" : {
|
||||||
|
"$ref" : "#/components/schemas/Int"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"securitySchemes" : { }
|
||||||
|
},
|
||||||
|
"security" : [ ],
|
||||||
|
"tags" : [ ]
|
||||||
|
}
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
@ -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" : { }
|
||||||
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
@ -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" : { }
|
||||||
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
@ -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" : { }
|
||||||
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
@ -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" : { }
|
||||||
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
@ -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" : { }
|
||||||
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
@ -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
|
||||||
@ -75,47 +75,33 @@
|
|||||||
},
|
},
|
||||||
"components" : {
|
"components" : {
|
||||||
"schemas" : {
|
"schemas" : {
|
||||||
|
"Long" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"format" : "int64"
|
||||||
|
},
|
||||||
|
"List-Long" : {
|
||||||
|
"type" : "array",
|
||||||
|
"items" : {
|
||||||
|
"$ref" : "#/components/schemas/Long"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Double" : {
|
||||||
|
"type" : "number",
|
||||||
|
"format" : "double"
|
||||||
|
},
|
||||||
"String" : {
|
"String" : {
|
||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"Int" : {
|
|
||||||
"format" : "int32",
|
|
||||||
"type" : "integer"
|
|
||||||
},
|
|
||||||
"TestCreatedResponse" : {
|
|
||||||
"properties" : {
|
|
||||||
"c" : {
|
|
||||||
"$ref" : "#/components/schemas/String"
|
|
||||||
},
|
|
||||||
"id" : {
|
|
||||||
"$ref" : "#/components/schemas/Int"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"type" : "object"
|
|
||||||
},
|
|
||||||
"Long" : {
|
|
||||||
"format" : "int64",
|
|
||||||
"type" : "integer"
|
|
||||||
},
|
|
||||||
"List-Long" : {
|
|
||||||
"items" : {
|
|
||||||
"$ref" : "#/components/schemas/Long"
|
|
||||||
},
|
|
||||||
"type" : "array"
|
|
||||||
},
|
|
||||||
"Double" : {
|
|
||||||
"format" : "double",
|
|
||||||
"type" : "number"
|
|
||||||
},
|
|
||||||
"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"
|
||||||
@ -126,8 +112,22 @@
|
|||||||
"fieldName" : {
|
"fieldName" : {
|
||||||
"$ref" : "#/components/schemas/TestNested"
|
"$ref" : "#/components/schemas/TestNested"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
},
|
||||||
|
"Int" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"format" : "int32"
|
||||||
|
},
|
||||||
|
"TestCreatedResponse" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"c" : {
|
||||||
|
"$ref" : "#/components/schemas/String"
|
||||||
|
},
|
||||||
|
"id" : {
|
||||||
|
"$ref" : "#/components/schemas/Int"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
@ -58,12 +58,12 @@
|
|||||||
},
|
},
|
||||||
"components" : {
|
"components" : {
|
||||||
"schemas" : {
|
"schemas" : {
|
||||||
|
"Int" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"format" : "int32"
|
||||||
|
},
|
||||||
"Boolean" : {
|
"Boolean" : {
|
||||||
"type" : "boolean"
|
"type" : "boolean"
|
||||||
},
|
|
||||||
"Int" : {
|
|
||||||
"format" : "int32",
|
|
||||||
"type" : "integer"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
@ -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
|
||||||
@ -75,47 +75,33 @@
|
|||||||
},
|
},
|
||||||
"components" : {
|
"components" : {
|
||||||
"schemas" : {
|
"schemas" : {
|
||||||
|
"Long" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"format" : "int64"
|
||||||
|
},
|
||||||
|
"List-Long" : {
|
||||||
|
"type" : "array",
|
||||||
|
"items" : {
|
||||||
|
"$ref" : "#/components/schemas/Long"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Double" : {
|
||||||
|
"type" : "number",
|
||||||
|
"format" : "double"
|
||||||
|
},
|
||||||
"String" : {
|
"String" : {
|
||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"Int" : {
|
|
||||||
"format" : "int32",
|
|
||||||
"type" : "integer"
|
|
||||||
},
|
|
||||||
"TestCreatedResponse" : {
|
|
||||||
"properties" : {
|
|
||||||
"c" : {
|
|
||||||
"$ref" : "#/components/schemas/String"
|
|
||||||
},
|
|
||||||
"id" : {
|
|
||||||
"$ref" : "#/components/schemas/Int"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"type" : "object"
|
|
||||||
},
|
|
||||||
"Long" : {
|
|
||||||
"format" : "int64",
|
|
||||||
"type" : "integer"
|
|
||||||
},
|
|
||||||
"List-Long" : {
|
|
||||||
"items" : {
|
|
||||||
"$ref" : "#/components/schemas/Long"
|
|
||||||
},
|
|
||||||
"type" : "array"
|
|
||||||
},
|
|
||||||
"Double" : {
|
|
||||||
"format" : "double",
|
|
||||||
"type" : "number"
|
|
||||||
},
|
|
||||||
"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"
|
||||||
@ -126,8 +112,22 @@
|
|||||||
"fieldName" : {
|
"fieldName" : {
|
||||||
"$ref" : "#/components/schemas/TestNested"
|
"$ref" : "#/components/schemas/TestNested"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
},
|
||||||
|
"Int" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"format" : "int32"
|
||||||
|
},
|
||||||
|
"TestCreatedResponse" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"c" : {
|
||||||
|
"$ref" : "#/components/schemas/String"
|
||||||
|
},
|
||||||
|
"id" : {
|
||||||
|
"$ref" : "#/components/schemas/Int"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
@ -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" : { }
|
||||||
|
@ -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" : [ ]
|
||||||
|
}
|
@ -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" : [ ]
|
||||||
|
}
|
85
kompendium-core/src/test/resources/polymorphic_response.json
Normal file
85
kompendium-core/src/test/resources/polymorphic_response.json
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
"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/polymorphic" : {
|
||||||
|
"get" : {
|
||||||
|
"tags" : [ ],
|
||||||
|
"summary" : "All the gibbits",
|
||||||
|
"description" : "Polymorphic response",
|
||||||
|
"parameters" : [ ],
|
||||||
|
"responses" : {
|
||||||
|
"200" : {
|
||||||
|
"description" : "A successful endeavor",
|
||||||
|
"content" : {
|
||||||
|
"application/json" : {
|
||||||
|
"schema" : {
|
||||||
|
"anyOf" : [ {
|
||||||
|
"$ref" : "#/components/schemas/SimpleGibbit"
|
||||||
|
}, {
|
||||||
|
"$ref" : "#/components/schemas/ComplexGibbit"
|
||||||
|
} ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"securitySchemes" : { }
|
||||||
|
},
|
||||||
|
"security" : [ ],
|
||||||
|
"tags" : [ ]
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
{
|
||||||
|
"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/polymorphic" : {
|
||||||
|
"get" : {
|
||||||
|
"tags" : [ ],
|
||||||
|
"summary" : "More flibbity",
|
||||||
|
"description" : "Polymorphic with generics",
|
||||||
|
"parameters" : [ ],
|
||||||
|
"responses" : {
|
||||||
|
"200" : {
|
||||||
|
"description" : "A successful endeavor",
|
||||||
|
"content" : {
|
||||||
|
"application/json" : {
|
||||||
|
"schema" : {
|
||||||
|
"anyOf" : [ {
|
||||||
|
"$ref" : "#/components/schemas/Gibbity-TestNested"
|
||||||
|
}, {
|
||||||
|
"$ref" : "#/components/schemas/Bibbity-TestNested"
|
||||||
|
} ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deprecated" : false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components" : {
|
||||||
|
"schemas" : {
|
||||||
|
"String" : {
|
||||||
|
"type" : "string"
|
||||||
|
},
|
||||||
|
"TestNested" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"nesty" : {
|
||||||
|
"$ref" : "#/components/schemas/String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Gibbity-TestNested" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"a" : {
|
||||||
|
"$ref" : "#/components/schemas/TestNested"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Bibbity-TestNested" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"b" : {
|
||||||
|
"$ref" : "#/components/schemas/String"
|
||||||
|
},
|
||||||
|
"f" : {
|
||||||
|
"$ref" : "#/components/schemas/TestNested"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"securitySchemes" : { }
|
||||||
|
},
|
||||||
|
"security" : [ ],
|
||||||
|
"tags" : [ ]
|
||||||
|
}
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
@ -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"
|
||||||
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
@ -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" : { }
|
||||||
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
@ -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" : { }
|
||||||
|
@ -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" : [ ]
|
||||||
|
}
|
@ -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",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"license" : {
|
"license" : {
|
||||||
"name" : "MIT",
|
"name" : "MIT",
|
||||||
"url" : "https://github.com/lg-backbone/kompendium/blob/main/LICENSE"
|
"url" : "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"servers" : [ {
|
"servers" : [ {
|
||||||
@ -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" : { }
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
|
kotlin("plugin.serialization") version "1.5.0"
|
||||||
application
|
application
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11,15 +12,20 @@ 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")
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
mainClassName = "org.leafygreens.kompendium.playground.MainKt"
|
mainClassName = "io.bkbn.kompendium.playground.MainKt"
|
||||||
applicationDefaultJvmArgs = listOf("-Dio.ktor.development=true") // TODO I don't think this is working 😢
|
applicationDefaultJvmArgs = listOf("-Dio.ktor.development=true") // TODO I don't think this is working 😢
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,27 @@
|
|||||||
package org.leafygreens.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.bkbn.kompendium.Notarized.notarizedDelete
|
||||||
|
import io.bkbn.kompendium.Notarized.notarizedException
|
||||||
|
import io.bkbn.kompendium.Notarized.notarizedGet
|
||||||
|
import io.bkbn.kompendium.Notarized.notarizedPost
|
||||||
|
import io.bkbn.kompendium.Notarized.notarizedPut
|
||||||
|
import io.bkbn.kompendium.auth.KompendiumAuth.notarizedBasic
|
||||||
|
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.testCustomOverride
|
||||||
|
import io.bkbn.kompendium.playground.PlaygroundToC.testGetWithExamples
|
||||||
|
import io.bkbn.kompendium.playground.PlaygroundToC.testIdGetInfo
|
||||||
|
import io.bkbn.kompendium.playground.PlaygroundToC.testPostWithExamples
|
||||||
|
import io.bkbn.kompendium.playground.PlaygroundToC.testSingleDeleteInfo
|
||||||
|
import io.bkbn.kompendium.playground.PlaygroundToC.testSingleGetInfo
|
||||||
|
import io.bkbn.kompendium.playground.PlaygroundToC.testSingleGetInfoWithThrowable
|
||||||
|
import io.bkbn.kompendium.playground.PlaygroundToC.testSinglePostInfo
|
||||||
|
import io.bkbn.kompendium.playground.PlaygroundToC.testSinglePutInfo
|
||||||
|
import io.bkbn.kompendium.routes.openApi
|
||||||
|
import io.bkbn.kompendium.routes.redoc
|
||||||
|
import io.bkbn.kompendium.swagger.swaggerUI
|
||||||
import io.ktor.application.Application
|
import io.ktor.application.Application
|
||||||
import io.ktor.application.call
|
import io.ktor.application.call
|
||||||
import io.ktor.application.install
|
import io.ktor.application.install
|
||||||
@ -11,35 +31,19 @@ import io.ktor.auth.authenticate
|
|||||||
import io.ktor.features.ContentNegotiation
|
import io.ktor.features.ContentNegotiation
|
||||||
import io.ktor.features.StatusPages
|
import io.ktor.features.StatusPages
|
||||||
import io.ktor.http.HttpStatusCode
|
import io.ktor.http.HttpStatusCode
|
||||||
import io.ktor.jackson.jackson
|
|
||||||
import io.ktor.response.respond
|
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
|
||||||
import io.ktor.server.engine.embeddedServer
|
import io.ktor.server.engine.embeddedServer
|
||||||
import io.ktor.server.netty.Netty
|
import io.ktor.server.netty.Netty
|
||||||
import io.ktor.webjars.Webjars
|
import io.ktor.webjars.Webjars
|
||||||
import org.leafygreens.kompendium.Notarized.notarizedDelete
|
import org.joda.time.DateTime
|
||||||
import org.leafygreens.kompendium.Notarized.notarizedException
|
|
||||||
import org.leafygreens.kompendium.Notarized.notarizedGet
|
|
||||||
import org.leafygreens.kompendium.Notarized.notarizedPost
|
|
||||||
import org.leafygreens.kompendium.Notarized.notarizedPut
|
|
||||||
import org.leafygreens.kompendium.auth.KompendiumAuth.notarizedBasic
|
|
||||||
import org.leafygreens.kompendium.models.meta.ResponseInfo
|
|
||||||
import org.leafygreens.kompendium.playground.PlaygroundToC.testAuthenticatedSingleGetInfo
|
|
||||||
import org.leafygreens.kompendium.playground.PlaygroundToC.testGetWithExamples
|
|
||||||
import org.leafygreens.kompendium.playground.PlaygroundToC.testIdGetInfo
|
|
||||||
import org.leafygreens.kompendium.playground.PlaygroundToC.testPostWithExamples
|
|
||||||
import org.leafygreens.kompendium.playground.PlaygroundToC.testSingleDeleteInfo
|
|
||||||
import org.leafygreens.kompendium.playground.PlaygroundToC.testSingleGetInfo
|
|
||||||
import org.leafygreens.kompendium.playground.PlaygroundToC.testSingleGetInfoWithThrowable
|
|
||||||
import org.leafygreens.kompendium.playground.PlaygroundToC.testSinglePostInfo
|
|
||||||
import org.leafygreens.kompendium.playground.PlaygroundToC.testSinglePutInfo
|
|
||||||
import org.leafygreens.kompendium.routes.openApi
|
|
||||||
import org.leafygreens.kompendium.routes.redoc
|
|
||||||
import org.leafygreens.kompendium.swagger.swaggerUI
|
|
||||||
|
|
||||||
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") {
|
||||||
@ -119,6 +120,11 @@ fun Application.mainModule() {
|
|||||||
call.respondText { "heya" }
|
call.respondText { "heya" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
route("custom_override") {
|
||||||
|
notarizedGet(testCustomOverride) {
|
||||||
|
call.respondText { DateTime.now().toString() }
|
||||||
|
}
|
||||||
|
}
|
||||||
authenticate("basic") {
|
authenticate("basic") {
|
||||||
route("/authenticated/single") {
|
route("/authenticated/single") {
|
||||||
notarizedGet(testAuthenticatedSingleGetInfo) {
|
notarizedGet(testAuthenticatedSingleGetInfo) {
|
@ -1,8 +1,9 @@
|
|||||||
package org.leafygreens.kompendium.playground
|
package io.bkbn.kompendium.playground
|
||||||
|
|
||||||
import org.leafygreens.kompendium.annotations.KompendiumField
|
import io.bkbn.kompendium.annotations.KompendiumField
|
||||||
import org.leafygreens.kompendium.annotations.KompendiumParam
|
import io.bkbn.kompendium.annotations.KompendiumParam
|
||||||
import org.leafygreens.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,
|
||||||
@ -16,6 +17,8 @@ data class JustQuery(
|
|||||||
|
|
||||||
data class ExampleNested(val nesty: String)
|
data class ExampleNested(val nesty: String)
|
||||||
|
|
||||||
|
data class ExampleGeneric<T>(val potato: T)
|
||||||
|
|
||||||
data class ExampleRequest(
|
data class ExampleRequest(
|
||||||
@KompendiumField(name = "field_name")
|
@KompendiumField(name = "field_name")
|
||||||
val fieldName: ExampleNested,
|
val fieldName: ExampleNested,
|
||||||
@ -28,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)
|
@ -1,9 +1,9 @@
|
|||||||
package org.leafygreens.kompendium.playground
|
package io.bkbn.kompendium.playground
|
||||||
|
|
||||||
import io.ktor.http.HttpStatusCode
|
import io.ktor.http.HttpStatusCode
|
||||||
import org.leafygreens.kompendium.models.meta.MethodInfo
|
import io.bkbn.kompendium.models.meta.MethodInfo
|
||||||
import org.leafygreens.kompendium.models.meta.RequestInfo
|
import io.bkbn.kompendium.models.meta.RequestInfo
|
||||||
import org.leafygreens.kompendium.models.meta.ResponseInfo
|
import io.bkbn.kompendium.models.meta.ResponseInfo
|
||||||
|
|
||||||
object PlaygroundToC {
|
object PlaygroundToC {
|
||||||
val testGetWithExamples = MethodInfo.GetInfo<Unit, ExampleResponse>(
|
val testGetWithExamples = MethodInfo.GetInfo<Unit, ExampleResponse>(
|
||||||
@ -37,7 +37,7 @@ object PlaygroundToC {
|
|||||||
canThrow = setOf(Exception::class)
|
canThrow = setOf(Exception::class)
|
||||||
)
|
)
|
||||||
|
|
||||||
val testIdGetInfo = MethodInfo.GetInfo<ExampleParams, ExampleResponse>(
|
val testIdGetInfo = MethodInfo.GetInfo<ExampleParams, ExampleGeneric<Int>>(
|
||||||
summary = "Get Test",
|
summary = "Get Test",
|
||||||
description = "Test for the getting",
|
description = "Test for the getting",
|
||||||
tags = setOf("test", "sample", "get"),
|
tags = setOf("test", "sample", "get"),
|
||||||
@ -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)
|
@ -1,11 +1,11 @@
|
|||||||
package org.leafygreens.kompendium.playground
|
package io.bkbn.kompendium.playground
|
||||||
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import org.leafygreens.kompendium.Kompendium
|
import io.bkbn.kompendium.Kompendium
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecInfo
|
import io.bkbn.kompendium.models.oas.OpenApiSpecInfo
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecInfoContact
|
import io.bkbn.kompendium.models.oas.OpenApiSpecInfoContact
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecInfoLicense
|
import io.bkbn.kompendium.models.oas.OpenApiSpecInfoLicense
|
||||||
import org.leafygreens.kompendium.models.oas.OpenApiSpecServer
|
import io.bkbn.kompendium.models.oas.OpenApiSpecServer
|
||||||
|
|
||||||
val oas = Kompendium.openApiSpec.copy(
|
val oas = Kompendium.openApiSpec.copy(
|
||||||
info = OpenApiSpecInfo(
|
info = OpenApiSpecInfo(
|
||||||
@ -20,7 +20,7 @@ val oas = Kompendium.openApiSpec.copy(
|
|||||||
),
|
),
|
||||||
license = OpenApiSpecInfoLicense(
|
license = OpenApiSpecInfoLicense(
|
||||||
name = "MIT",
|
name = "MIT",
|
||||||
url = URI("https://github.com/lg-backbone/kompendium/blob/main/LICENSE")
|
url = URI("https://github.com/bkbnio/kompendium/blob/main/LICENSE")
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
servers = mutableListOf(
|
servers = mutableListOf(
|
@ -1,6 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
|
signing
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -11,19 +12,20 @@ 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 {
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
name = "GithubPackages"
|
name = "GithubPackages"
|
||||||
url = uri("https://maven.pkg.github.com/lg-backbone/kompendium")
|
url = uri("https://maven.pkg.github.com/bkbnio/kompendium")
|
||||||
credentials {
|
credentials {
|
||||||
username = System.getenv("GITHUB_ACTOR")
|
username = System.getenv("GITHUB_ACTOR")
|
||||||
password = System.getenv("GITHUB_TOKEN")
|
password = System.getenv("GITHUB_TOKEN")
|
||||||
@ -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)
|
||||||
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package org.leafygreens.kompendium.swagger
|
package io.bkbn.kompendium.swagger
|
||||||
|
|
||||||
import io.ktor.application.call
|
import io.ktor.application.call
|
||||||
import io.ktor.response.respondRedirect
|
import io.ktor.response.respondRedirect
|
Reference in New Issue
Block a user