Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
c8d56e62a2 | |||
67bd6ad36f | |||
1a924058a1 | |||
8f81b4d795 | |||
9edd3a53ce | |||
91a6164663 | |||
5a7e052ac4 | |||
6ba3617e32 | |||
c32c91829b | |||
b021935b10 | |||
3d99bf35fd | |||
c5f8ace5d2 | |||
b0149c293e | |||
925172cf86 | |||
aa3290243b | |||
2e7dad444b | |||
6e56bf7425 | |||
dfc1593022 | |||
5fe98a04e8 |
5
.github/workflows/pr_checks.yml
vendored
5
.github/workflows/pr_checks.yml
vendored
@ -37,3 +37,8 @@ jobs:
|
|||||||
run: ./gradlew assemble
|
run: ./gradlew assemble
|
||||||
- name: Run Unit Tests
|
- name: Run Unit Tests
|
||||||
run: ./gradlew test
|
run: ./gradlew test
|
||||||
|
- name: Cache Coverage Results
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ./**/build/reports/jacoco
|
||||||
|
key: ${{ runner.os }}-unit-${{ env.GITHUB_SHA }}
|
||||||
|
23
.github/workflows/publish.yml
vendored
23
.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
|
||||||
@ -21,3 +24,23 @@ jobs:
|
|||||||
run: ./gradlew publishAllPublicationsToGithubPackagesRepository
|
run: ./gradlew publishAllPublicationsToGithubPackagesRepository
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
code-coverage:
|
||||||
|
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: Run Unit Tests
|
||||||
|
run: ./gradlew test
|
||||||
|
- name: Publish code coverage to Codacy
|
||||||
|
uses: codacy/codacy-coverage-reporter-action@v1
|
||||||
|
with:
|
||||||
|
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
||||||
|
26
.github/workflows/release.yml
vendored
26
.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
|
||||||
@ -20,6 +23,25 @@ jobs:
|
|||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
||||||
restore-keys: ${{ runner.os }}-gradle
|
restore-keys: ${{ runner.os }}-gradle
|
||||||
- name: Publish packages to Github
|
- name: Publish packages to Github
|
||||||
run: ./gradlew publish -Prelease=true
|
run: ./gradlew publishAllPublicationsToGithubPackagesRepository -Prelease=true
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
publish-to-nexus:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-java@v2
|
||||||
|
with:
|
||||||
|
distribution: 'adopt'
|
||||||
|
java-version: '11'
|
||||||
|
- name: Cache Gradle packages
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ~/.gradle/caches
|
||||||
|
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
||||||
|
restore-keys: ${{ runner.os }}-gradle
|
||||||
|
- name: Publish packages to Github
|
||||||
|
run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository -Prelease=true
|
||||||
|
env:
|
||||||
|
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USER }}
|
||||||
|
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
|
||||||
|
81
CHANGELOG.md
81
CHANGELOG.md
@ -1,5 +1,86 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [1.9.1] - October 17th, 2021
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Code Coverage removed from PR checks due to limitations with GitHub workflows
|
||||||
|
- Minor linting fixes
|
||||||
|
- Detekt now builds off of default config
|
||||||
|
|
||||||
|
## [1.9.0] - october 15th, 2021
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- ByteArray added to the set of default types
|
||||||
|
|
||||||
|
|
||||||
|
## [1.8.1] - October 4th, 2021
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Codacy integration
|
||||||
|
|
||||||
|
## [1.8.0] - October 4th, 2021
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Path calculation revamped to allow for simpler selector injection
|
||||||
|
- Kotlin version bumped to 1.5.31
|
||||||
|
- Ktor version bumped to 1.6.4
|
||||||
|
|
||||||
|
## [1.7.0] - August 14th, 2021
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added ability to inject an emergency `UndeclaredField` in the event of certain polymorphic serializers and such
|
||||||
|
|
||||||
|
## [1.6.0] - August 12th, 2021
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Ability to add custom type schema overrides for edge case types.
|
||||||
|
|
||||||
|
## [1.5.1] - August 12th, 2021
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Fixed bug where polymorphic types were not being rendered correctly when part of collections and maps
|
||||||
|
|
||||||
|
## [1.5.0] - July 25th, 2021
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Added support for BigInteger and BigDecimal in response types
|
||||||
|
|
||||||
|
## [1.4.0] - July 22nd, 2021
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Decreased jvmTarget version from 11 to 1.8
|
||||||
|
|
||||||
|
## [1.3.0] - June 4th, 2021
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Explicitly encode JSON object by default
|
||||||
|
|
||||||
|
## [1.2.3] - June 3rd, 2021
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Updates showing/explaining serializer agnostic approach
|
||||||
|
|
||||||
|
## [1.2.2] - May 23rd, 2021
|
||||||
|
|
||||||
|
This is just to get my repo back to normal now that I have confirmed sonatype publish is happening
|
||||||
|
|
||||||
|
## [1.2.0] - May 23rd, 2021
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Finally, successfully pushed to Maven Central!!!
|
||||||
|
|
||||||
## [1.1.0] - May 19th, 2021
|
## [1.1.0] - May 19th, 2021
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
101
README.md
101
README.md
@ -1,5 +1,9 @@
|
|||||||
# Kompendium
|
# Kompendium
|
||||||
|
|
||||||
|
[](https://www.codacy.com/gh/bkbnio/kompendium/dashboard?utm_source=github.com&utm_medium=referral&utm_content=bkbnio/kompendium&utm_campaign=Badge_Grade)
|
||||||
|
[](https://www.codacy.com/gh/bkbnio/kompendium/dashboard?utm_source=github.com&utm_medium=referral&utm_content=bkbnio/kompendium&utm_campaign=Badge_Coverage)
|
||||||
|
[](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 +12,27 @@ 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 {
|
||||||
|
implementation("io.bkbn:kompendium-core:1.8.1")
|
||||||
|
implementation("io.bkbn:kompendium-auth:1.8.1")
|
||||||
|
implementation("io.bkbn:kompendium-swagger-ui:1.8.1")
|
||||||
|
|
||||||
|
// Other dependencies...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The last two dependencies are optional.
|
||||||
|
|
||||||
|
If you want to get a little spicy 🤠 every merge of Kompendium is published to the GitHub package registry. Pulling
|
||||||
|
from GitHub is slightly more involved, but such is the price you pay for bleeding edge fake data generation.
|
||||||
|
|
||||||
```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 +40,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")
|
||||||
}
|
}
|
||||||
@ -30,11 +53,15 @@ repositories {
|
|||||||
|
|
||||||
// 3 Add the package like any normal dependency
|
// 3 Add the package like any normal dependency
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("io.bkbn:kompendium-core:1.0.0")
|
implementation("io.bkbn:kompendium-core:1.8.1")
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Local Development
|
||||||
|
|
||||||
|
Kompendium should run locally right out of the box, no configuration necessary (assuming you have JDK 1.8+ installed). New features can be built locally and published to your local maven repository with the `./gradlew publishToMavenLocal` command!
|
||||||
|
|
||||||
## In depth
|
## In depth
|
||||||
|
|
||||||
### Notarized Routes
|
### Notarized Routes
|
||||||
@ -76,12 +103,56 @@ 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.
|
||||||
|
|
||||||
|
### Undeclared Field
|
||||||
|
|
||||||
|
There is also a final `UndeclaredField` annotation. This should be used only in an absolutely emergency. This annotation
|
||||||
|
will allow you to inject a _single_ undeclared field that will be included as part of the schema.
|
||||||
|
|
||||||
|
Due to limitations in using repeated annotations, this can only be used once per class
|
||||||
|
|
||||||
|
This is a complete hack, and is included for odd scenarios like kotlinx serialization polymorphic adapters that expect a
|
||||||
|
`type` field in order to perform their analysis.
|
||||||
|
|
||||||
|
Use this _only_ when **all** else fails
|
||||||
|
|
||||||
### Polymorphism
|
### Polymorphism
|
||||||
|
|
||||||
Out of the box, Kompendium has support for sealed classes. At runtime, it will build a mapping of all available sub-classes
|
Speaking of polymorphism... out of the box, Kompendium has support for sealed classes and interfaces. At runtime, it will build a mapping of all available sub-classes
|
||||||
and build a spec that takes `anyOf` the implementations. This is currently a weak point of the entire library, and
|
and build a spec that takes `anyOf` the implementations. This is currently a weak point of the entire library, and
|
||||||
suggestions on better implementations are welcome 🤠
|
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.
|
||||||
|
|
||||||
|
### Route Handling
|
||||||
|
|
||||||
|
> ⚠️ Warning: Custom route handling is almost definitely an indication that either a new selector should be added to kompendium-core or that kompendium is in need of another module to handle a new ktor companion module. If you have encountered a route selector that is not already handled, please consider opening an [issue](https://github.com/bkbnio/kompendium/issues/new)
|
||||||
|
|
||||||
|
Kompendium does its best to handle all Ktor routes out of the gate. However, in keeping with the modular approach of
|
||||||
|
Ktor and Kompendium, this is not always possible.
|
||||||
|
|
||||||
|
Should you need to, custom route handlers can be registered via the
|
||||||
|
`Kompendium.addCustomRouteHandler` function.
|
||||||
|
|
||||||
|
The handler signature is as follows
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun <T : RouteSelector> addCustomRouteHandler(
|
||||||
|
selector: KClass<T>,
|
||||||
|
handler: PathCalculator.(Route, String) -> String
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
This function takes a selector, which _must_ be a KClass of the Ktor `RouteSelector` type. The handler is a function
|
||||||
|
that extends the Kompendium `PathCalculator`. This is necessary because it gives you access to `PathCalculator.calculate`,
|
||||||
|
which you are going to want in order to recursively calculate the remainder of the route :)
|
||||||
|
|
||||||
|
Its parameters are the `Route` itself, along with the "tail" of the Path (the path that has been calculated thus far).
|
||||||
|
|
||||||
|
Working examples `init` blocks of the `PathCalculator` and `KompendiumAuth` object.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
The full source code can be found in the `kompendium-playground` module. Here is a simple get endpoint example
|
The full source code can be found in the `kompendium-playground` module. Here is a simple get endpoint example
|
||||||
@ -191,6 +262,25 @@ routing {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Custom Type Overrides
|
||||||
|
|
||||||
|
Kompendium does its best to analyze types and to generate an OpenAPI format accordingly. However, there are certain
|
||||||
|
classes that just don't play nice with the standard reflection analysis that Kompendium performs.
|
||||||
|
Should you encounter a data type that Kompendium cannot comprehend, you will need to
|
||||||
|
add it explicitly. For example, adding the Joda Time `DateTime` object would be as simple as the following
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
Kompendium.addCustomTypeSchema(DateTime::class, FormatSchema("date-time", "string"))
|
||||||
|
```
|
||||||
|
|
||||||
|
Since `Kompendium` is an object, this needs to be declared once, ahead of the actual API instantiation. This way, this
|
||||||
|
type override can be cached ahead of reflection. Kompendium will then match all instances of this type and return the
|
||||||
|
specified schema.
|
||||||
|
|
||||||
|
So how do you know a type can and cannot be inferred? The safe bet is that it can be. So go ahead and give it a shot.
|
||||||
|
However, in the very odd scenario (almost always having to do with date/time libraries 😤) where it can't, you can rest
|
||||||
|
safely knowing that you have the option to inject a custom override should you need to.
|
||||||
|
|
||||||
## Limitations
|
## Limitations
|
||||||
|
|
||||||
### Kompendium as a singleton
|
### Kompendium as a singleton
|
||||||
@ -209,7 +299,6 @@ should have. There are several outstanding features that have been added to the
|
|||||||
|
|
||||||
- AsyncAPI Integration
|
- AsyncAPI Integration
|
||||||
- Field Validation
|
- Field Validation
|
||||||
- MavenCentral Release
|
|
||||||
|
|
||||||
If you have a feature that you would like to see implemented that is not on this list, or discover a 🐞, please open
|
If you have a feature that you would like to see implemented that is not on this list, or discover a 🐞, please open
|
||||||
an issue [here](https://github.com/bkbnio/kompendium/issues/new)
|
an issue [here](https://github.com/bkbnio/kompendium/issues/new)
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import com.adarshr.gradle.testlogger.theme.ThemeType
|
|
||||||
import com.adarshr.gradle.testlogger.TestLoggerExtension
|
import com.adarshr.gradle.testlogger.TestLoggerExtension
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
import com.adarshr.gradle.testlogger.theme.ThemeType
|
||||||
import io.gitlab.arturbosch.detekt.extensions.DetektExtension
|
import io.gitlab.arturbosch.detekt.extensions.DetektExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("org.jetbrains.kotlin.jvm") version "1.5.0" apply false
|
id("org.jetbrains.kotlin.jvm") version "1.5.31" apply false
|
||||||
id("io.gitlab.arturbosch.detekt") version "1.17.0-RC3" apply false
|
id("io.gitlab.arturbosch.detekt") version "1.18.1" 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 {
|
||||||
@ -29,13 +30,30 @@ allprojects {
|
|||||||
apply(plugin = "io.gitlab.arturbosch.detekt")
|
apply(plugin = "io.gitlab.arturbosch.detekt")
|
||||||
apply(plugin = "com.adarshr.test-logger")
|
apply(plugin = "com.adarshr.test-logger")
|
||||||
apply(plugin = "idea")
|
apply(plugin = "idea")
|
||||||
|
apply(plugin = "jacoco")
|
||||||
|
|
||||||
tasks.withType<KotlinCompile>().configureEach {
|
tasks.withType<KotlinCompile>().configureEach {
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "11"
|
jvmTarget = "1.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType<Test>() {
|
||||||
|
finalizedBy(tasks.withType(JacocoReport::class))
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<JacocoReport>() {
|
||||||
|
reports {
|
||||||
|
html.required.set(true)
|
||||||
|
xml.required.set(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configure<JacocoPluginExtension> {
|
||||||
|
toolVersion = "0.8.7"
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("MagicNumber")
|
||||||
configure<TestLoggerExtension> {
|
configure<TestLoggerExtension> {
|
||||||
theme = ThemeType.MOCHA
|
theme = ThemeType.MOCHA
|
||||||
setLogLevel("lifecycle")
|
setLogLevel("lifecycle")
|
||||||
@ -56,12 +74,22 @@ allprojects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
configure<DetektExtension> {
|
configure<DetektExtension> {
|
||||||
toolVersion = "1.17.0-RC3"
|
toolVersion = "1.18.1"
|
||||||
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/"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
702
detekt.yml
702
detekt.yml
@ -1,710 +1,20 @@
|
|||||||
build:
|
|
||||||
maxIssues: 0
|
|
||||||
excludeCorrectable: false
|
|
||||||
weights:
|
|
||||||
# complexity: 2
|
|
||||||
# LongParameterList: 1
|
|
||||||
# style: 1
|
|
||||||
# comments: 1
|
|
||||||
|
|
||||||
config:
|
|
||||||
validation: true
|
|
||||||
warningsAsErrors: false
|
|
||||||
# when writing own rules with new properties, exclude the property path e.g.: 'my_rule_set,.*>.*>[my_property]'
|
|
||||||
excludes: ''
|
|
||||||
|
|
||||||
processors:
|
|
||||||
active: true
|
|
||||||
exclude:
|
|
||||||
- 'DetektProgressListener'
|
|
||||||
|
|
||||||
console-reports:
|
|
||||||
active: true
|
|
||||||
exclude:
|
|
||||||
- 'ProjectStatisticsReport'
|
|
||||||
- 'ComplexityReport'
|
|
||||||
- 'NotificationReport'
|
|
||||||
- 'FileBasedFindingsReport'
|
|
||||||
|
|
||||||
output-reports:
|
|
||||||
active: true
|
|
||||||
|
|
||||||
comments:
|
|
||||||
active: true
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
AbsentOrWrongFileLicense:
|
|
||||||
active: false
|
|
||||||
licenseTemplateFile: 'license.template'
|
|
||||||
CommentOverPrivateFunction:
|
|
||||||
active: false
|
|
||||||
CommentOverPrivateProperty:
|
|
||||||
active: false
|
|
||||||
EndOfSentenceFormat:
|
|
||||||
active: false
|
|
||||||
endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)'
|
|
||||||
UndocumentedPublicClass:
|
|
||||||
active: false
|
|
||||||
searchInNestedClass: true
|
|
||||||
searchInInnerClass: true
|
|
||||||
searchInInnerObject: true
|
|
||||||
searchInInnerInterface: true
|
|
||||||
UndocumentedPublicFunction:
|
|
||||||
active: false
|
|
||||||
UndocumentedPublicProperty:
|
|
||||||
active: false
|
|
||||||
|
|
||||||
complexity:
|
complexity:
|
||||||
active: true
|
TooManyFunctions:
|
||||||
ComplexCondition:
|
|
||||||
active: true
|
|
||||||
threshold: 4
|
|
||||||
ComplexInterface:
|
|
||||||
active: false
|
active: false
|
||||||
threshold: 10
|
|
||||||
includeStaticDeclarations: false
|
|
||||||
includePrivateDeclarations: false
|
|
||||||
ComplexMethod:
|
|
||||||
active: true
|
|
||||||
threshold: 25
|
|
||||||
ignoreSingleWhenExpression: false
|
|
||||||
ignoreSimpleWhenEntries: false
|
|
||||||
ignoreNestingFunctions: false
|
|
||||||
nestingFunctions: [run, let, apply, with, also, use, forEach, isNotNull, ifNull]
|
|
||||||
LabeledExpression:
|
|
||||||
active: false
|
|
||||||
ignoredLabels: []
|
|
||||||
LargeClass:
|
|
||||||
active: true
|
|
||||||
threshold: 600
|
|
||||||
LongMethod:
|
|
||||||
active: true
|
|
||||||
threshold: 80
|
|
||||||
LongParameterList:
|
LongParameterList:
|
||||||
active: true
|
active: true
|
||||||
functionThreshold: 10
|
functionThreshold: 10
|
||||||
constructorThreshold: 10
|
constructorThreshold: 10
|
||||||
ignoreDefaultParameters: false
|
ComplexMethod:
|
||||||
ignoreDataClasses: true
|
threshold: 20
|
||||||
ignoreAnnotated: []
|
|
||||||
MethodOverloading:
|
|
||||||
active: false
|
|
||||||
threshold: 6
|
|
||||||
NamedArguments:
|
|
||||||
active: false
|
|
||||||
threshold: 3
|
|
||||||
NestedBlockDepth:
|
|
||||||
active: true
|
|
||||||
threshold: 6
|
|
||||||
ReplaceSafeCallChainWithRun:
|
|
||||||
active: false
|
|
||||||
StringLiteralDuplication:
|
|
||||||
active: false
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
threshold: 3
|
|
||||||
ignoreAnnotation: true
|
|
||||||
excludeStringsWithLessThan5Characters: true
|
|
||||||
ignoreStringsRegex: '$^'
|
|
||||||
TooManyFunctions:
|
|
||||||
active: false
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
thresholdInFiles: 11
|
|
||||||
thresholdInClasses: 11
|
|
||||||
thresholdInInterfaces: 11
|
|
||||||
thresholdInObjects: 11
|
|
||||||
thresholdInEnums: 11
|
|
||||||
ignoreDeprecated: false
|
|
||||||
ignorePrivate: false
|
|
||||||
ignoreOverridden: false
|
|
||||||
|
|
||||||
coroutines:
|
|
||||||
active: true
|
|
||||||
GlobalCoroutineUsage:
|
|
||||||
active: false
|
|
||||||
RedundantSuspendModifier:
|
|
||||||
active: false
|
|
||||||
SleepInsteadOfDelay:
|
|
||||||
active: false
|
|
||||||
SuspendFunWithFlowReturnType:
|
|
||||||
active: false
|
|
||||||
|
|
||||||
empty-blocks:
|
|
||||||
active: true
|
|
||||||
EmptyCatchBlock:
|
|
||||||
active: true
|
|
||||||
allowedExceptionNameRegex: '_|(ignore|expected).*'
|
|
||||||
EmptyClassBlock:
|
|
||||||
active: true
|
|
||||||
EmptyDefaultConstructor:
|
|
||||||
active: true
|
|
||||||
EmptyDoWhileBlock:
|
|
||||||
active: true
|
|
||||||
EmptyElseBlock:
|
|
||||||
active: true
|
|
||||||
EmptyFinallyBlock:
|
|
||||||
active: true
|
|
||||||
EmptyForBlock:
|
|
||||||
active: true
|
|
||||||
EmptyFunctionBlock:
|
|
||||||
active: true
|
|
||||||
ignoreOverridden: false
|
|
||||||
EmptyIfBlock:
|
|
||||||
active: true
|
|
||||||
EmptyInitBlock:
|
|
||||||
active: true
|
|
||||||
EmptyKtFile:
|
|
||||||
active: true
|
|
||||||
EmptySecondaryConstructor:
|
|
||||||
active: true
|
|
||||||
EmptyTryBlock:
|
|
||||||
active: true
|
|
||||||
EmptyWhenBlock:
|
|
||||||
active: true
|
|
||||||
EmptyWhileBlock:
|
|
||||||
active: true
|
|
||||||
|
|
||||||
exceptions:
|
|
||||||
active: true
|
|
||||||
ExceptionRaisedInUnexpectedLocation:
|
|
||||||
active: true
|
|
||||||
methodNames: [toString, hashCode, equals, finalize]
|
|
||||||
InstanceOfCheckForException:
|
|
||||||
active: false
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
NotImplementedDeclaration:
|
|
||||||
active: false
|
|
||||||
ObjectExtendsThrowable:
|
|
||||||
active: false
|
|
||||||
PrintStackTrace:
|
|
||||||
active: true
|
|
||||||
RethrowCaughtException:
|
|
||||||
active: true
|
|
||||||
ReturnFromFinally:
|
|
||||||
active: true
|
|
||||||
ignoreLabeled: false
|
|
||||||
SwallowedException:
|
|
||||||
active: true
|
|
||||||
ignoredExceptionTypes:
|
|
||||||
- InterruptedException
|
|
||||||
- NumberFormatException
|
|
||||||
- ParseException
|
|
||||||
- MalformedURLException
|
|
||||||
allowedExceptionNameRegex: '_|(ignore|expected).*'
|
|
||||||
ThrowingExceptionFromFinally:
|
|
||||||
active: true
|
|
||||||
ThrowingExceptionInMain:
|
|
||||||
active: false
|
|
||||||
ThrowingExceptionsWithoutMessageOrCause:
|
|
||||||
active: true
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
exceptions:
|
|
||||||
- IllegalArgumentException
|
|
||||||
- IllegalStateException
|
|
||||||
- IOException
|
|
||||||
ThrowingNewInstanceOfSameException:
|
|
||||||
active: true
|
|
||||||
TooGenericExceptionCaught:
|
|
||||||
active: true
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
exceptionNames:
|
|
||||||
- ArrayIndexOutOfBoundsException
|
|
||||||
- Error
|
|
||||||
- Exception
|
|
||||||
- IllegalMonitorStateException
|
|
||||||
- NullPointerException
|
|
||||||
- IndexOutOfBoundsException
|
|
||||||
- RuntimeException
|
|
||||||
- Throwable
|
|
||||||
allowedExceptionNameRegex: '_|(ignore|expected).*'
|
|
||||||
TooGenericExceptionThrown:
|
|
||||||
active: true
|
|
||||||
exceptionNames:
|
|
||||||
- Error
|
|
||||||
- Exception
|
|
||||||
- Throwable
|
|
||||||
- RuntimeException
|
|
||||||
|
|
||||||
formatting:
|
formatting:
|
||||||
active: true
|
|
||||||
android: false
|
|
||||||
autoCorrect: true
|
|
||||||
AnnotationOnSeparateLine:
|
|
||||||
active: false
|
|
||||||
autoCorrect: true
|
|
||||||
AnnotationSpacing:
|
|
||||||
active: false
|
|
||||||
autoCorrect: true
|
|
||||||
ArgumentListWrapping:
|
|
||||||
active: false
|
|
||||||
autoCorrect: true
|
|
||||||
ChainWrapping:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
CommentSpacing:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
EnumEntryNameCase:
|
|
||||||
active: false
|
|
||||||
autoCorrect: true
|
|
||||||
Filename:
|
|
||||||
active: true
|
|
||||||
FinalNewline:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
insertFinalNewLine: true
|
|
||||||
ImportOrdering:
|
|
||||||
active: false
|
|
||||||
autoCorrect: true
|
|
||||||
layout: 'idea'
|
|
||||||
Indentation:
|
|
||||||
active: false
|
|
||||||
autoCorrect: true
|
|
||||||
indentSize: 4
|
|
||||||
continuationIndentSize: 4
|
|
||||||
MaximumLineLength:
|
|
||||||
active: true
|
|
||||||
maxLineLength: 120
|
|
||||||
ModifierOrdering:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
MultiLineIfElse:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
NoBlankLineBeforeRbrace:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
NoConsecutiveBlankLines:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
NoEmptyClassBody:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
NoEmptyFirstLineInMethodBlock:
|
|
||||||
active: false
|
|
||||||
autoCorrect: true
|
|
||||||
NoLineBreakAfterElse:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
NoLineBreakBeforeAssignment:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
NoMultipleSpaces:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
NoSemicolons:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
NoTrailingSpaces:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
NoUnitReturn:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
NoUnusedImports:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
NoWildcardImports:
|
|
||||||
active: true
|
|
||||||
PackageName:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
ParameterListWrapping:
|
ParameterListWrapping:
|
||||||
active: false
|
active: false
|
||||||
autoCorrect: true
|
|
||||||
indentSize: 4
|
|
||||||
SpacingAroundAngleBrackets:
|
|
||||||
active: false
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingAroundColon:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingAroundComma:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingAroundCurly:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingAroundDot:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingAroundDoubleColon:
|
|
||||||
active: false
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingAroundKeyword:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingAroundOperators:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingAroundParens:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingAroundRangeOperator:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingAroundUnaryOperator:
|
|
||||||
active: false
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingBetweenDeclarationsWithAnnotations:
|
|
||||||
active: false
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingBetweenDeclarationsWithComments:
|
|
||||||
active: false
|
|
||||||
autoCorrect: true
|
|
||||||
StringTemplate:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
|
|
||||||
naming:
|
|
||||||
active: true
|
|
||||||
ClassNaming:
|
|
||||||
active: true
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
classPattern: '[A-Z][a-zA-Z0-9]*'
|
|
||||||
ConstructorParameterNaming:
|
|
||||||
active: false
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
parameterPattern: '[a-z][A-Za-z0-9]*'
|
|
||||||
privateParameterPattern: '[a-z][A-Za-z0-9]*'
|
|
||||||
excludeClassPattern: '$^'
|
|
||||||
ignoreOverridden: true
|
|
||||||
EnumNaming:
|
|
||||||
active: true
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
enumEntryPattern: '[A-Z][_a-zA-Z0-9]*'
|
|
||||||
ForbiddenClassName:
|
|
||||||
active: false
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
forbiddenName: []
|
|
||||||
FunctionMaxLength:
|
|
||||||
active: false
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
maximumFunctionNameLength: 30
|
|
||||||
FunctionMinLength:
|
|
||||||
active: false
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
minimumFunctionNameLength: 3
|
|
||||||
FunctionNaming:
|
|
||||||
active: true
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
functionPattern: '([a-z][a-zA-Z0-9]*)|(`.*`)'
|
|
||||||
excludeClassPattern: '$^'
|
|
||||||
ignoreOverridden: true
|
|
||||||
ignoreAnnotated: ['Composable']
|
|
||||||
FunctionParameterNaming:
|
|
||||||
active: true
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
parameterPattern: '[a-z][A-Za-z0-9]*'
|
|
||||||
excludeClassPattern: '$^'
|
|
||||||
ignoreOverridden: true
|
|
||||||
InvalidPackageDeclaration:
|
|
||||||
active: false
|
|
||||||
excludes: ['*.kts']
|
|
||||||
rootPackage: ''
|
|
||||||
MatchingDeclarationName:
|
|
||||||
active: true
|
|
||||||
mustBeFirst: true
|
|
||||||
MemberNameEqualsClassName:
|
|
||||||
active: true
|
|
||||||
ignoreOverridden: true
|
|
||||||
NonBooleanPropertyPrefixedWithIs:
|
|
||||||
active: false
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
ObjectPropertyNaming:
|
|
||||||
active: true
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
constantPattern: '[A-Za-z][_A-Za-z0-9]*'
|
|
||||||
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
|
|
||||||
privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*'
|
|
||||||
PackageNaming:
|
|
||||||
active: true
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
packagePattern: '[a-z]+(\.[a-z][A-Za-z0-9]*)*'
|
|
||||||
TopLevelPropertyNaming:
|
|
||||||
active: true
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
constantPattern: '[A-Z][_A-Z0-9]*'
|
|
||||||
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
|
|
||||||
privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*'
|
|
||||||
VariableMaxLength:
|
|
||||||
active: false
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
maximumVariableNameLength: 64
|
|
||||||
VariableMinLength:
|
|
||||||
active: false
|
|
||||||
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
minimumVariableNameLength: 1
|
|
||||||
VariableNaming:
|
|
||||||
active: true
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
variablePattern: '[a-z][A-Za-z0-9]*'
|
|
||||||
privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*'
|
|
||||||
excludeClassPattern: '$^'
|
|
||||||
ignoreOverridden: true
|
|
||||||
|
|
||||||
performance:
|
|
||||||
active: true
|
|
||||||
ArrayPrimitive:
|
|
||||||
active: true
|
|
||||||
ForEachOnRange:
|
|
||||||
active: true
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
SpreadOperator:
|
|
||||||
active: true
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
UnnecessaryTemporaryInstantiation:
|
|
||||||
active: true
|
|
||||||
|
|
||||||
potential-bugs:
|
|
||||||
active: true
|
|
||||||
Deprecation:
|
|
||||||
active: false
|
|
||||||
DontDowncastCollectionTypes:
|
|
||||||
active: false
|
|
||||||
DuplicateCaseInWhenExpression:
|
|
||||||
active: true
|
|
||||||
EqualsAlwaysReturnsTrueOrFalse:
|
|
||||||
active: true
|
|
||||||
EqualsWithHashCodeExist:
|
|
||||||
active: true
|
|
||||||
ExitOutsideMain:
|
|
||||||
active: false
|
|
||||||
ExplicitGarbageCollectionCall:
|
|
||||||
active: true
|
|
||||||
HasPlatformType:
|
|
||||||
active: false
|
|
||||||
IgnoredReturnValue:
|
|
||||||
active: false
|
|
||||||
restrictToAnnotatedMethods: true
|
|
||||||
returnValueAnnotations: ['*.CheckReturnValue', '*.CheckResult']
|
|
||||||
ImplicitDefaultLocale:
|
|
||||||
active: true
|
|
||||||
ImplicitUnitReturnType:
|
|
||||||
active: false
|
|
||||||
allowExplicitReturnType: true
|
|
||||||
InvalidRange:
|
|
||||||
active: true
|
|
||||||
IteratorHasNextCallsNextMethod:
|
|
||||||
active: true
|
|
||||||
IteratorNotThrowingNoSuchElementException:
|
|
||||||
active: true
|
|
||||||
LateinitUsage:
|
|
||||||
active: false
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
excludeAnnotatedProperties: []
|
|
||||||
ignoreOnClassesPattern: ''
|
|
||||||
MapGetWithNotNullAssertionOperator:
|
|
||||||
active: false
|
|
||||||
MissingWhenCase:
|
|
||||||
active: true
|
|
||||||
allowElseExpression: true
|
|
||||||
NullableToStringCall:
|
|
||||||
active: false
|
|
||||||
RedundantElseInWhen:
|
|
||||||
active: true
|
|
||||||
UnconditionalJumpStatementInLoop:
|
|
||||||
active: false
|
|
||||||
UnnecessaryNotNullOperator:
|
|
||||||
active: true
|
|
||||||
UnnecessarySafeCall:
|
|
||||||
active: true
|
|
||||||
UnreachableCatchBlock:
|
|
||||||
active: false
|
|
||||||
UnreachableCode:
|
|
||||||
active: true
|
|
||||||
UnsafeCallOnNullableType:
|
|
||||||
active: true
|
|
||||||
UnsafeCast:
|
|
||||||
active: true
|
|
||||||
UselessPostfixExpression:
|
|
||||||
active: false
|
|
||||||
WrongEqualsTypeParameter:
|
|
||||||
active: true
|
|
||||||
|
|
||||||
style:
|
style:
|
||||||
active: true
|
|
||||||
ClassOrdering:
|
|
||||||
active: false
|
|
||||||
CollapsibleIfStatements:
|
|
||||||
active: false
|
|
||||||
DataClassContainsFunctions:
|
|
||||||
active: false
|
|
||||||
conversionFunctionPrefix: 'to'
|
|
||||||
DataClassShouldBeImmutable:
|
|
||||||
active: false
|
|
||||||
DestructuringDeclarationWithTooManyEntries:
|
|
||||||
active: false
|
|
||||||
maxDestructuringEntries: 3
|
|
||||||
EqualsNullCall:
|
|
||||||
active: true
|
|
||||||
EqualsOnSignatureLine:
|
|
||||||
active: false
|
|
||||||
ExplicitCollectionElementAccessMethod:
|
|
||||||
active: false
|
|
||||||
ExplicitItLambdaParameter:
|
|
||||||
active: false
|
|
||||||
ExpressionBodySyntax:
|
|
||||||
active: false
|
|
||||||
includeLineWrapping: false
|
|
||||||
ForbiddenComment:
|
|
||||||
active: true
|
|
||||||
values: ['TODO:', 'FIXME:', 'STOPSHIP:']
|
|
||||||
allowedPatterns: ''
|
|
||||||
ForbiddenImport:
|
|
||||||
active: false
|
|
||||||
imports: []
|
|
||||||
forbiddenPatterns: ''
|
|
||||||
ForbiddenMethodCall:
|
|
||||||
active: false
|
|
||||||
methods: ['kotlin.io.println', 'kotlin.io.print']
|
|
||||||
ForbiddenPublicDataClass:
|
|
||||||
active: true
|
|
||||||
excludes: ['**']
|
|
||||||
ignorePackages: ['*.internal', '*.internal.*']
|
|
||||||
ForbiddenVoid:
|
|
||||||
active: false
|
|
||||||
ignoreOverridden: false
|
|
||||||
ignoreUsageInGenerics: false
|
|
||||||
FunctionOnlyReturningConstant:
|
|
||||||
active: true
|
|
||||||
ignoreOverridableFunction: true
|
|
||||||
ignoreActualFunction: true
|
|
||||||
excludedFunctions: 'describeContents'
|
|
||||||
excludeAnnotatedFunction: ['dagger.Provides']
|
|
||||||
LibraryCodeMustSpecifyReturnType:
|
|
||||||
active: true
|
|
||||||
excludes: ['**']
|
|
||||||
LibraryEntitiesShouldNotBePublic:
|
|
||||||
active: true
|
|
||||||
excludes: ['**']
|
|
||||||
LoopWithTooManyJumpStatements:
|
|
||||||
active: true
|
|
||||||
maxJumpCount: 1
|
|
||||||
MagicNumber:
|
|
||||||
active: true
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
ignoreNumbers: ['-1', '0', '1', '2']
|
|
||||||
ignoreHashCodeFunction: true
|
|
||||||
ignorePropertyDeclaration: false
|
|
||||||
ignoreLocalVariableDeclaration: false
|
|
||||||
ignoreConstantDeclaration: true
|
|
||||||
ignoreCompanionObjectPropertyDeclaration: true
|
|
||||||
ignoreAnnotation: false
|
|
||||||
ignoreNamedArgument: true
|
|
||||||
ignoreEnums: false
|
|
||||||
ignoreRanges: false
|
|
||||||
ignoreExtensionFunctions: true
|
|
||||||
MandatoryBracesIfStatements:
|
|
||||||
active: false
|
|
||||||
MandatoryBracesLoops:
|
|
||||||
active: false
|
|
||||||
MaxLineLength:
|
MaxLineLength:
|
||||||
|
excludes: ['**/test/**/*', '**/testIntegration/**/*']
|
||||||
active: true
|
active: true
|
||||||
maxLineLength: 120
|
maxLineLength: 120
|
||||||
excludePackageStatements: true
|
naming:
|
||||||
excludeImportStatements: true
|
ConstructorParameterNaming:
|
||||||
excludeCommentStatements: false
|
|
||||||
MayBeConst:
|
|
||||||
active: true
|
|
||||||
ModifierOrder:
|
|
||||||
active: true
|
|
||||||
MultilineLambdaItParameter:
|
|
||||||
active: false
|
active: false
|
||||||
NestedClassesVisibility:
|
|
||||||
active: true
|
|
||||||
NewLineAtEndOfFile:
|
|
||||||
active: true
|
|
||||||
NoTabs:
|
|
||||||
active: false
|
|
||||||
OptionalAbstractKeyword:
|
|
||||||
active: true
|
|
||||||
OptionalUnit:
|
|
||||||
active: false
|
|
||||||
OptionalWhenBraces:
|
|
||||||
active: false
|
|
||||||
PreferToOverPairSyntax:
|
|
||||||
active: false
|
|
||||||
ProtectedMemberInFinalClass:
|
|
||||||
active: true
|
|
||||||
RedundantExplicitType:
|
|
||||||
active: false
|
|
||||||
RedundantHigherOrderMapUsage:
|
|
||||||
active: false
|
|
||||||
RedundantVisibilityModifierRule:
|
|
||||||
active: false
|
|
||||||
ReturnCount:
|
|
||||||
active: true
|
|
||||||
max: 2
|
|
||||||
excludedFunctions: 'equals'
|
|
||||||
excludeLabeled: false
|
|
||||||
excludeReturnFromLambda: true
|
|
||||||
excludeGuardClauses: false
|
|
||||||
SafeCast:
|
|
||||||
active: true
|
|
||||||
SerialVersionUIDInSerializableClass:
|
|
||||||
active: true
|
|
||||||
SpacingBetweenPackageAndImports:
|
|
||||||
active: false
|
|
||||||
ThrowsCount:
|
|
||||||
active: true
|
|
||||||
max: 2
|
|
||||||
TrailingWhitespace:
|
|
||||||
active: false
|
|
||||||
UnderscoresInNumericLiterals:
|
|
||||||
active: false
|
|
||||||
acceptableDecimalLength: 5
|
|
||||||
UnnecessaryAbstractClass:
|
|
||||||
active: true
|
|
||||||
excludeAnnotatedClasses: ['dagger.Module']
|
|
||||||
UnnecessaryAnnotationUseSiteTarget:
|
|
||||||
active: false
|
|
||||||
UnnecessaryApply:
|
|
||||||
active: true
|
|
||||||
UnnecessaryFilter:
|
|
||||||
active: false
|
|
||||||
UnnecessaryInheritance:
|
|
||||||
active: true
|
|
||||||
UnnecessaryLet:
|
|
||||||
active: false
|
|
||||||
UnnecessaryParentheses:
|
|
||||||
active: false
|
|
||||||
UntilInsteadOfRangeTo:
|
|
||||||
active: false
|
|
||||||
UnusedImports:
|
|
||||||
active: false
|
|
||||||
UnusedPrivateClass:
|
|
||||||
active: true
|
|
||||||
UnusedPrivateMember:
|
|
||||||
active: true
|
|
||||||
allowedNames: '(_|ignored|expected|serialVersionUID)'
|
|
||||||
UseArrayLiteralsInAnnotations:
|
|
||||||
active: false
|
|
||||||
UseCheckNotNull:
|
|
||||||
active: false
|
|
||||||
UseCheckOrError:
|
|
||||||
active: false
|
|
||||||
UseDataClass:
|
|
||||||
active: false
|
|
||||||
excludeAnnotatedClasses: []
|
|
||||||
allowVars: false
|
|
||||||
UseEmptyCounterpart:
|
|
||||||
active: false
|
|
||||||
UseIfEmptyOrIfBlank:
|
|
||||||
active: false
|
|
||||||
UseIfInsteadOfWhen:
|
|
||||||
active: false
|
|
||||||
UseIsNullOrEmpty:
|
|
||||||
active: false
|
|
||||||
UseRequire:
|
|
||||||
active: false
|
|
||||||
UseRequireNotNull:
|
|
||||||
active: false
|
|
||||||
UselessCallOnNotNull:
|
|
||||||
active: true
|
|
||||||
UtilityClassWithPublicConstructor:
|
|
||||||
active: true
|
|
||||||
VarCouldBeVal:
|
|
||||||
active: true
|
|
||||||
WildcardImport:
|
|
||||||
active: true
|
|
||||||
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
|
|
||||||
excludeImports: ['java.util.*', 'kotlinx.android.synthetic.*']
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Kompendium
|
# Kompendium
|
||||||
project.version=1.1.0
|
project.version=1.9.1
|
||||||
# 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.6.4"
|
||||||
|
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"]
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
|
signing
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -10,14 +11,16 @@ dependencies {
|
|||||||
implementation(libs.bundles.ktorAuth)
|
implementation(libs.bundles.ktorAuth)
|
||||||
implementation(projects.kompendiumCore)
|
implementation(projects.kompendiumCore)
|
||||||
|
|
||||||
|
testImplementation(libs.ktor.jackson)
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-test")
|
testImplementation("org.jetbrains.kotlin:kotlin-test")
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
|
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
|
||||||
testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.12.0")
|
testImplementation(libs.jackson.module.kotlin)
|
||||||
testImplementation("io.ktor:ktor-server-test-host:1.5.3")
|
testImplementation(libs.ktor.server.test.host)
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
|
withJavadocJar()
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
@ -35,6 +38,41 @@ publishing {
|
|||||||
create<MavenPublication>("kompendium") {
|
create<MavenPublication>("kompendium") {
|
||||||
from(components["kotlin"])
|
from(components["kotlin"])
|
||||||
artifact(tasks.sourcesJar)
|
artifact(tasks.sourcesJar)
|
||||||
|
artifact(tasks.javadocJar)
|
||||||
|
groupId = project.group.toString()
|
||||||
|
artifactId = project.name.toLowerCase()
|
||||||
|
version = project.version.toString()
|
||||||
|
|
||||||
|
pom {
|
||||||
|
name.set("Kompendium")
|
||||||
|
description.set("A minimally invasive OpenAPI spec generator for Ktor")
|
||||||
|
url.set("https://github.com/bkbnio/Kompendium")
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name.set("MIT License")
|
||||||
|
url.set("https://mit-license.org/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
developers {
|
||||||
|
developer {
|
||||||
|
id.set("bkbnio")
|
||||||
|
name.set("Ryan Brink")
|
||||||
|
email.set("admin@bkbn.io")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scm {
|
||||||
|
connection.set("scm:git:git://github.com/bkbnio/Kompendium.git")
|
||||||
|
developerConnection.set("scm:git:ssh://github.com/bkbnio/Kompendium.git")
|
||||||
|
url.set("https://github.com/bkbnio/Kompendium.git")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signing {
|
||||||
|
val signingKey: String? by project
|
||||||
|
val signingPassword: String? by project
|
||||||
|
useInMemoryPgpKeys(signingKey, signingPassword)
|
||||||
|
sign(publishing.publications)
|
||||||
|
}
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
package io.bkbn.kompendium.auth
|
|
||||||
|
|
||||||
import io.ktor.auth.AuthenticationRouteSelector
|
|
||||||
import io.ktor.routing.Route
|
|
||||||
import io.bkbn.kompendium.path.CorePathCalculator
|
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
|
|
||||||
class AuthPathCalculator : CorePathCalculator() {
|
|
||||||
|
|
||||||
private val logger = LoggerFactory.getLogger(javaClass)
|
|
||||||
|
|
||||||
override fun handleCustomSelectors(route: Route, tail: String): String = when (route.selector) {
|
|
||||||
is AuthenticationRouteSelector -> {
|
|
||||||
logger.debug("Found authentication route selector ${route.selector}")
|
|
||||||
super.calculate(route.parent, tail)
|
|
||||||
}
|
|
||||||
else -> super.handleCustomSelectors(route, tail)
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,11 +7,14 @@ import io.ktor.auth.jwt.jwt
|
|||||||
import io.ktor.auth.jwt.JWTAuthenticationProvider
|
import io.ktor.auth.jwt.JWTAuthenticationProvider
|
||||||
import io.bkbn.kompendium.Kompendium
|
import io.bkbn.kompendium.Kompendium
|
||||||
import io.bkbn.kompendium.models.oas.OpenApiSpecSchemaSecurity
|
import io.bkbn.kompendium.models.oas.OpenApiSpecSchemaSecurity
|
||||||
|
import io.ktor.auth.AuthenticationRouteSelector
|
||||||
|
|
||||||
object KompendiumAuth {
|
object KompendiumAuth {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
Kompendium.pathCalculator = AuthPathCalculator()
|
Kompendium.addCustomRouteHandler(AuthenticationRouteSelector::class) { route, tail ->
|
||||||
|
calculate(route.parent, tail)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Authentication.Configuration.notarizedBasic(
|
fun Authentication.Configuration.notarizedBasic(
|
||||||
|
@ -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,20 +1,25 @@
|
|||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
|
signing
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
|
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
|
||||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||||
|
implementation(libs.jackson.module.kotlin)
|
||||||
implementation(libs.bundles.ktor)
|
implementation(libs.bundles.ktor)
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-test")
|
testImplementation("org.jetbrains.kotlin:kotlin-test")
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
|
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
|
||||||
testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.12.0")
|
testImplementation(libs.ktor.serialization)
|
||||||
testImplementation("io.ktor:ktor-server-test-host:1.5.3")
|
testImplementation(libs.kotlinx.serialization.json)
|
||||||
|
testImplementation(libs.ktor.jackson)
|
||||||
|
testImplementation(libs.ktor.server.test.host)
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
|
withJavadocJar()
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
@ -32,6 +37,41 @@ publishing {
|
|||||||
create<MavenPublication>("kompendium") {
|
create<MavenPublication>("kompendium") {
|
||||||
from(components["kotlin"])
|
from(components["kotlin"])
|
||||||
artifact(tasks.sourcesJar)
|
artifact(tasks.sourcesJar)
|
||||||
|
artifact(tasks.javadocJar)
|
||||||
|
groupId = project.group.toString()
|
||||||
|
artifactId = project.name.toLowerCase()
|
||||||
|
version = project.version.toString()
|
||||||
|
|
||||||
|
pom {
|
||||||
|
name.set("Kompendium")
|
||||||
|
description.set("A minimally invasive OpenAPI spec generator for Ktor")
|
||||||
|
url.set("https://github.com/bkbnio/Kompendium")
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name.set("MIT License")
|
||||||
|
url.set("https://mit-license.org/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
developers {
|
||||||
|
developer {
|
||||||
|
id.set("bkbnio")
|
||||||
|
name.set("Ryan Brink")
|
||||||
|
email.set("admin@bkbn.io")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scm {
|
||||||
|
connection.set("scm:git:git://github.com/bkbnio/Kompendium.git")
|
||||||
|
developerConnection.set("scm:git:ssh://github.com/bkbnio/Kompendium.git")
|
||||||
|
url.set("https://github.com/bkbnio/Kompendium.git")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signing {
|
||||||
|
val signingKey: String? by project
|
||||||
|
val signingPassword: String? by project
|
||||||
|
useInMemoryPgpKeys(signingKey, signingPassword)
|
||||||
|
sign(publishing.publications)
|
||||||
|
}
|
||||||
|
@ -4,8 +4,12 @@ import io.bkbn.kompendium.models.meta.ErrorMap
|
|||||||
import io.bkbn.kompendium.models.meta.SchemaMap
|
import io.bkbn.kompendium.models.meta.SchemaMap
|
||||||
import io.bkbn.kompendium.models.oas.OpenApiSpec
|
import io.bkbn.kompendium.models.oas.OpenApiSpec
|
||||||
import io.bkbn.kompendium.models.oas.OpenApiSpecInfo
|
import io.bkbn.kompendium.models.oas.OpenApiSpecInfo
|
||||||
import io.bkbn.kompendium.path.CorePathCalculator
|
import io.bkbn.kompendium.models.oas.TypedSchema
|
||||||
|
import io.bkbn.kompendium.path.IPathCalculator
|
||||||
import io.bkbn.kompendium.path.PathCalculator
|
import io.bkbn.kompendium.path.PathCalculator
|
||||||
|
import io.ktor.routing.Route
|
||||||
|
import io.ktor.routing.RouteSelector
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maintains all state for the Kompendium library
|
* Maintains all state for the Kompendium library
|
||||||
@ -21,7 +25,7 @@ object Kompendium {
|
|||||||
paths = mutableMapOf()
|
paths = mutableMapOf()
|
||||||
)
|
)
|
||||||
|
|
||||||
var pathCalculator: PathCalculator = CorePathCalculator()
|
fun calculatePath(route: Route) = PathCalculator.calculate(route)
|
||||||
|
|
||||||
fun resetSchema() {
|
fun resetSchema() {
|
||||||
openApiSpec = OpenApiSpec(
|
openApiSpec = OpenApiSpec(
|
||||||
@ -31,4 +35,15 @@ object Kompendium {
|
|||||||
)
|
)
|
||||||
cache = emptyMap()
|
cache = emptyMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addCustomTypeSchema(clazz: KClass<*>, schema: TypedSchema) {
|
||||||
|
cache = cache.plus(clazz.simpleName!! to schema)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : RouteSelector> addCustomRouteHandler(
|
||||||
|
selector: KClass<T>,
|
||||||
|
handler: IPathCalculator.(Route, String) -> String
|
||||||
|
) {
|
||||||
|
PathCalculator.addCustomRouteHandler(selector, handler)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package io.bkbn.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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,23 +47,8 @@ object KompendiumPreFlight {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun addToCache(paramType: KType, requestType: KType, responseType: KType) {
|
fun addToCache(paramType: KType, requestType: KType, responseType: KType) {
|
||||||
gatherSubTypes(requestType).forEach {
|
Kompendium.cache = Kontent.generateKontent(requestType, Kompendium.cache)
|
||||||
Kompendium.cache = Kontent.generateKontent(it, Kompendium.cache)
|
Kompendium.cache = Kontent.generateKontent(responseType, Kompendium.cache)
|
||||||
}
|
|
||||||
gatherSubTypes(responseType).forEach {
|
|
||||||
Kompendium.cache = Kontent.generateKontent(it, Kompendium.cache)
|
|
||||||
}
|
|
||||||
Kompendium.cache = Kontent.generateParameterKontent(paramType, Kompendium.cache)
|
Kompendium.cache = Kontent.generateParameterKontent(paramType, Kompendium.cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun gatherSubTypes(type: KType): List<KType> {
|
|
||||||
val classifier = type.classifier as KClass<*>
|
|
||||||
return if (classifier.isSealed) {
|
|
||||||
classifier.sealedSubclasses.map {
|
|
||||||
it.createType(type.arguments)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
listOf(type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.bkbn.kompendium
|
package io.bkbn.kompendium
|
||||||
|
|
||||||
|
import io.bkbn.kompendium.annotations.UndeclaredField
|
||||||
import io.bkbn.kompendium.models.meta.SchemaMap
|
import io.bkbn.kompendium.models.meta.SchemaMap
|
||||||
import io.bkbn.kompendium.models.oas.AnyOfReferencedSchema
|
import io.bkbn.kompendium.models.oas.AnyOfReferencedSchema
|
||||||
import io.bkbn.kompendium.models.oas.ArraySchema
|
import io.bkbn.kompendium.models.oas.ArraySchema
|
||||||
@ -14,6 +15,9 @@ import io.bkbn.kompendium.util.Helpers.genericNameAdapter
|
|||||||
import io.bkbn.kompendium.util.Helpers.getReferenceSlug
|
import io.bkbn.kompendium.util.Helpers.getReferenceSlug
|
||||||
import io.bkbn.kompendium.util.Helpers.getSimpleSlug
|
import io.bkbn.kompendium.util.Helpers.getSimpleSlug
|
||||||
import io.bkbn.kompendium.util.Helpers.logged
|
import io.bkbn.kompendium.util.Helpers.logged
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import java.math.BigDecimal
|
||||||
|
import java.math.BigInteger
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
@ -22,7 +26,6 @@ import kotlin.reflect.full.isSubclassOf
|
|||||||
import kotlin.reflect.full.memberProperties
|
import kotlin.reflect.full.memberProperties
|
||||||
import kotlin.reflect.jvm.javaField
|
import kotlin.reflect.jvm.javaField
|
||||||
import kotlin.reflect.typeOf
|
import kotlin.reflect.typeOf
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for generating the schema map that is used to power all object references across the API Spec.
|
* Responsible for generating the schema map that is used to power all object references across the API Spec.
|
||||||
@ -55,7 +58,22 @@ object Kontent {
|
|||||||
type: KType,
|
type: KType,
|
||||||
cache: SchemaMap = emptyMap()
|
cache: SchemaMap = emptyMap()
|
||||||
): SchemaMap {
|
): SchemaMap {
|
||||||
return generateKTypeKontent(type, cache)
|
var newCache = cache
|
||||||
|
gatherSubTypes(type).forEach {
|
||||||
|
newCache = generateKTypeKontent(it, newCache)
|
||||||
|
}
|
||||||
|
return newCache
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun gatherSubTypes(type: KType): List<KType> {
|
||||||
|
val classifier = type.classifier as KClass<*>
|
||||||
|
return if (classifier.isSealed) {
|
||||||
|
classifier.sealedSubclasses.map {
|
||||||
|
it.createType(type.arguments)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
listOf(type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,6 +124,9 @@ object Kontent {
|
|||||||
String::class -> cache.plus(clazz.simpleName!! to SimpleSchema("string"))
|
String::class -> cache.plus(clazz.simpleName!! to SimpleSchema("string"))
|
||||||
Boolean::class -> cache.plus(clazz.simpleName!! to SimpleSchema("boolean"))
|
Boolean::class -> cache.plus(clazz.simpleName!! to SimpleSchema("boolean"))
|
||||||
UUID::class -> cache.plus(clazz.simpleName!! to FormatSchema("uuid", "string"))
|
UUID::class -> cache.plus(clazz.simpleName!! to FormatSchema("uuid", "string"))
|
||||||
|
BigDecimal::class -> cache.plus(clazz.simpleName!! to FormatSchema("double", "number"))
|
||||||
|
BigInteger::class -> cache.plus(clazz.simpleName!! to FormatSchema("int64", "integer"))
|
||||||
|
ByteArray::class -> cache.plus(clazz.simpleName!! to FormatSchema("byte", "string"))
|
||||||
else -> when {
|
else -> when {
|
||||||
clazz.isSubclassOf(Collection::class) -> handleCollectionType(type, clazz, cache)
|
clazz.isSubclassOf(Collection::class) -> handleCollectionType(type, clazz, cache)
|
||||||
clazz.isSubclassOf(Enum::class) -> handleEnumType(clazz, cache)
|
clazz.isSubclassOf(Enum::class) -> handleEnumType(clazz, cache)
|
||||||
@ -120,6 +141,8 @@ object Kontent {
|
|||||||
* @param clazz Class of the object to analyze
|
* @param clazz Class of the object to analyze
|
||||||
* @param cache Existing schema map to append to
|
* @param cache Existing schema map to append to
|
||||||
*/
|
*/
|
||||||
|
// TODO Fix as part of this issue https://github.com/bkbnio/kompendium/issues/80
|
||||||
|
@Suppress("LongMethod", "ComplexMethod")
|
||||||
private fun handleComplexType(type: KType, clazz: KClass<*>, cache: SchemaMap): SchemaMap {
|
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
|
// This needs to be simple because it will be stored under it's appropriate reference component implicitly
|
||||||
val slug = type.getSimpleSlug()
|
val slug = type.getSimpleSlug()
|
||||||
@ -185,8 +208,14 @@ object Kontent {
|
|||||||
}
|
}
|
||||||
Pair(prop.name, propSchema)
|
Pair(prop.name, propSchema)
|
||||||
}
|
}
|
||||||
|
logger.debug("Looking for undeclared fields")
|
||||||
|
val undeclaredFieldMap = clazz.annotations.filterIsInstance<UndeclaredField>().associate {
|
||||||
|
val undeclaredType = it.clazz.createType()
|
||||||
|
newCache = generateKontent(undeclaredType, newCache)
|
||||||
|
it.field to ReferencedSchema(undeclaredType.getReferenceSlug())
|
||||||
|
}
|
||||||
logger.debug("$slug contains $fieldMap")
|
logger.debug("$slug contains $fieldMap")
|
||||||
val schema = ObjectSchema(fieldMap)
|
val schema = ObjectSchema(fieldMap.plus(undeclaredFieldMap))
|
||||||
logger.debug("$slug schema: $schema")
|
logger.debug("$slug schema: $schema")
|
||||||
newCache.plus(slug to schema)
|
newCache.plus(slug to schema)
|
||||||
}
|
}
|
||||||
@ -216,11 +245,20 @@ object Kontent {
|
|||||||
if (keyType?.classifier != String::class) {
|
if (keyType?.classifier != String::class) {
|
||||||
error("Invalid Map $type: OpenAPI dictionaries must have keys of type String")
|
error("Invalid Map $type: OpenAPI dictionaries must have keys of type String")
|
||||||
}
|
}
|
||||||
val valClassName = (valType?.classifier as KClass<*>).simpleName
|
val valClass = valType?.classifier as KClass<*>
|
||||||
|
val valClassName = valClass.simpleName
|
||||||
val referenceName = genericNameAdapter(type, clazz)
|
val referenceName = genericNameAdapter(type, clazz)
|
||||||
val valueReference = ReferencedSchema("$COMPONENT_SLUG/$valClassName")
|
val valueReference = when (valClass.isSealed) {
|
||||||
|
true -> {
|
||||||
|
val subTypes = gatherSubTypes(valType)
|
||||||
|
AnyOfReferencedSchema(subTypes.map {
|
||||||
|
ReferencedSchema(("$COMPONENT_SLUG/${it.getSimpleSlug()}"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
false -> ReferencedSchema("$COMPONENT_SLUG/$valClassName")
|
||||||
|
}
|
||||||
val schema = DictionarySchema(additionalProperties = valueReference)
|
val schema = DictionarySchema(additionalProperties = valueReference)
|
||||||
val updatedCache = generateKTypeKontent(valType, cache)
|
val updatedCache = generateKontent(valType, cache)
|
||||||
return updatedCache.plus(referenceName to schema)
|
return updatedCache.plus(referenceName to schema)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,9 +274,17 @@ object Kontent {
|
|||||||
val collectionClass = collectionType.classifier as KClass<*>
|
val collectionClass = collectionType.classifier as KClass<*>
|
||||||
logger.debug("Obtained collection class: $collectionClass")
|
logger.debug("Obtained collection class: $collectionClass")
|
||||||
val referenceName = genericNameAdapter(type, clazz)
|
val referenceName = genericNameAdapter(type, clazz)
|
||||||
val valueReference = ReferencedSchema("${COMPONENT_SLUG}/${collectionClass.simpleName}")
|
val valueReference = when (collectionClass.isSealed) {
|
||||||
|
true -> {
|
||||||
|
val subTypes = gatherSubTypes(collectionType)
|
||||||
|
AnyOfReferencedSchema(subTypes.map {
|
||||||
|
ReferencedSchema(("$COMPONENT_SLUG/${it.getSimpleSlug()}"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
false -> ReferencedSchema("$COMPONENT_SLUG/${collectionClass.simpleName}")
|
||||||
|
}
|
||||||
val schema = ArraySchema(items = valueReference)
|
val schema = ArraySchema(items = valueReference)
|
||||||
val updatedCache = generateKTypeKontent(collectionType, cache)
|
val updatedCache = generateKontent(collectionType, cache)
|
||||||
return updatedCache.plus(referenceName to schema)
|
return updatedCache.plus(referenceName to schema)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ object Notarized {
|
|||||||
noinline body: PipelineInterceptor<Unit, ApplicationCall>
|
noinline body: PipelineInterceptor<Unit, ApplicationCall>
|
||||||
): Route =
|
): Route =
|
||||||
KompendiumPreFlight.methodNotarizationPreFlight<TParam, Unit, TResp>() { paramType, requestType, responseType ->
|
KompendiumPreFlight.methodNotarizationPreFlight<TParam, Unit, TResp>() { paramType, requestType, responseType ->
|
||||||
val path = Kompendium.pathCalculator.calculate(this)
|
val path = Kompendium.calculatePath(this)
|
||||||
Kompendium.openApiSpec.paths.getOrPut(path) { OpenApiSpecPathItem() }
|
Kompendium.openApiSpec.paths.getOrPut(path) { OpenApiSpecPathItem() }
|
||||||
Kompendium.openApiSpec.paths[path]?.get = parseMethodInfo(info, paramType, requestType, responseType)
|
Kompendium.openApiSpec.paths[path]?.get = parseMethodInfo(info, paramType, requestType, responseType)
|
||||||
return method(HttpMethod.Get) { handle(body) }
|
return method(HttpMethod.Get) { handle(body) }
|
||||||
@ -55,7 +55,7 @@ object Notarized {
|
|||||||
noinline body: PipelineInterceptor<Unit, ApplicationCall>
|
noinline body: PipelineInterceptor<Unit, ApplicationCall>
|
||||||
): Route =
|
): Route =
|
||||||
KompendiumPreFlight.methodNotarizationPreFlight<TParam, TReq, TResp>() { paramType, requestType, responseType ->
|
KompendiumPreFlight.methodNotarizationPreFlight<TParam, TReq, TResp>() { paramType, requestType, responseType ->
|
||||||
val path = Kompendium.pathCalculator.calculate(this)
|
val path = Kompendium.calculatePath(this)
|
||||||
Kompendium.openApiSpec.paths.getOrPut(path) { OpenApiSpecPathItem() }
|
Kompendium.openApiSpec.paths.getOrPut(path) { OpenApiSpecPathItem() }
|
||||||
Kompendium.openApiSpec.paths[path]?.post = parseMethodInfo(info, paramType, requestType, responseType)
|
Kompendium.openApiSpec.paths[path]?.post = parseMethodInfo(info, paramType, requestType, responseType)
|
||||||
return method(HttpMethod.Post) { handle(body) }
|
return method(HttpMethod.Post) { handle(body) }
|
||||||
@ -74,7 +74,7 @@ object Notarized {
|
|||||||
noinline body: PipelineInterceptor<Unit, ApplicationCall>,
|
noinline body: PipelineInterceptor<Unit, ApplicationCall>,
|
||||||
): Route =
|
): Route =
|
||||||
KompendiumPreFlight.methodNotarizationPreFlight<TParam, TReq, TResp>() { paramType, requestType, responseType ->
|
KompendiumPreFlight.methodNotarizationPreFlight<TParam, TReq, TResp>() { paramType, requestType, responseType ->
|
||||||
val path = Kompendium.pathCalculator.calculate(this)
|
val path = Kompendium.calculatePath(this)
|
||||||
Kompendium.openApiSpec.paths.getOrPut(path) { OpenApiSpecPathItem() }
|
Kompendium.openApiSpec.paths.getOrPut(path) { OpenApiSpecPathItem() }
|
||||||
Kompendium.openApiSpec.paths[path]?.put =
|
Kompendium.openApiSpec.paths[path]?.put =
|
||||||
parseMethodInfo(info, paramType, requestType, responseType)
|
parseMethodInfo(info, paramType, requestType, responseType)
|
||||||
@ -93,7 +93,7 @@ object Notarized {
|
|||||||
noinline body: PipelineInterceptor<Unit, ApplicationCall>
|
noinline body: PipelineInterceptor<Unit, ApplicationCall>
|
||||||
): Route =
|
): Route =
|
||||||
KompendiumPreFlight.methodNotarizationPreFlight<TParam, Unit, TResp> { paramType, requestType, responseType ->
|
KompendiumPreFlight.methodNotarizationPreFlight<TParam, Unit, TResp> { paramType, requestType, responseType ->
|
||||||
val path = Kompendium.pathCalculator.calculate(this)
|
val path = Kompendium.calculatePath(this)
|
||||||
Kompendium.openApiSpec.paths.getOrPut(path) { OpenApiSpecPathItem() }
|
Kompendium.openApiSpec.paths.getOrPut(path) { OpenApiSpecPathItem() }
|
||||||
Kompendium.openApiSpec.paths[path]?.delete = parseMethodInfo(info, paramType, requestType, responseType)
|
Kompendium.openApiSpec.paths[path]?.delete = parseMethodInfo(info, paramType, requestType, responseType)
|
||||||
return method(HttpMethod.Delete) { handle(body) }
|
return method(HttpMethod.Delete) { handle(body) }
|
||||||
@ -112,5 +112,4 @@ object Notarized {
|
|||||||
info.parseErrorInfo(errorType, responseType)
|
info.parseErrorInfo(errorType, responseType)
|
||||||
exception(handler)
|
exception(handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package io.bkbn.kompendium.annotations
|
||||||
|
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Repeatable
|
||||||
|
annotation class UndeclaredField(val field: String, val clazz: KClass<*>)
|
@ -1,7 +1,6 @@
|
|||||||
package io.bkbn.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 AnyOfReferencedSchema -> error("Cannot add default to anyOf reference")
|
||||||
is ReferencedSchema -> this.copy(default = default)
|
is ReferencedSchema -> this.copy(default = default)
|
||||||
@ -12,7 +11,6 @@ sealed class OpenApiSpecComponentSchema(open val default: Any? = null) {
|
|||||||
is FormatSchema -> this.copy(default = default)
|
is FormatSchema -> this.copy(default = default)
|
||||||
is ArraySchema -> this.copy(default = default)
|
is ArraySchema -> this.copy(default = default)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
package io.bkbn.kompendium.path
|
|
||||||
|
|
||||||
import io.ktor.routing.PathSegmentConstantRouteSelector
|
|
||||||
import io.ktor.routing.PathSegmentParameterRouteSelector
|
|
||||||
import io.ktor.routing.RootRouteSelector
|
|
||||||
import io.ktor.routing.Route
|
|
||||||
import io.ktor.util.InternalAPI
|
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default [PathCalculator] meant to be overridden as necessary
|
|
||||||
*/
|
|
||||||
open class CorePathCalculator : PathCalculator {
|
|
||||||
|
|
||||||
private val logger = LoggerFactory.getLogger(javaClass)
|
|
||||||
|
|
||||||
@OptIn(InternalAPI::class)
|
|
||||||
override fun calculate(
|
|
||||||
route: Route?,
|
|
||||||
tail: String
|
|
||||||
): String = when (route) {
|
|
||||||
null -> tail
|
|
||||||
else -> when (route.selector) {
|
|
||||||
is RootRouteSelector -> {
|
|
||||||
logger.debug("Root route detected, returning path: $tail")
|
|
||||||
tail
|
|
||||||
}
|
|
||||||
is PathSegmentParameterRouteSelector -> {
|
|
||||||
logger.debug("Found segment parameter ${route.selector}, continuing to parent")
|
|
||||||
val newTail = "/${route.selector}$tail"
|
|
||||||
calculate(route.parent, newTail)
|
|
||||||
}
|
|
||||||
is PathSegmentConstantRouteSelector -> {
|
|
||||||
logger.debug("Found segment constant ${route.selector}, continuing to parent")
|
|
||||||
val newTail = "/${route.selector}$tail"
|
|
||||||
calculate(route.parent, newTail)
|
|
||||||
}
|
|
||||||
else -> when (route.selector.javaClass.simpleName) {
|
|
||||||
"TrailingSlashRouteSelector" -> {
|
|
||||||
logger.debug("Found trailing slash route selector")
|
|
||||||
val newTail = tail.ifBlank { "/" }
|
|
||||||
calculate(route.parent, newTail)
|
|
||||||
}
|
|
||||||
else -> handleCustomSelectors(route, tail)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handleCustomSelectors(route: Route, tail: String): String = error("Unknown selector ${route.selector}")
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,13 @@
|
|||||||
|
package io.bkbn.kompendium.path
|
||||||
|
|
||||||
|
import io.ktor.routing.Route
|
||||||
|
import io.ktor.routing.RouteSelector
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
interface IPathCalculator {
|
||||||
|
fun calculate(route: Route?, tail: String = ""): String
|
||||||
|
fun <T : RouteSelector> addCustomRouteHandler(
|
||||||
|
selector: KClass<T>,
|
||||||
|
handler: IPathCalculator.(Route, String) -> String
|
||||||
|
)
|
||||||
|
}
|
@ -1,20 +1,54 @@
|
|||||||
package io.bkbn.kompendium.path
|
package io.bkbn.kompendium.path
|
||||||
|
|
||||||
|
import io.ktor.routing.PathSegmentConstantRouteSelector
|
||||||
|
import io.ktor.routing.PathSegmentParameterRouteSelector
|
||||||
|
import io.ktor.routing.RootRouteSelector
|
||||||
import io.ktor.routing.Route
|
import io.ktor.routing.Route
|
||||||
|
import io.ktor.routing.RouteSelector
|
||||||
|
import io.ktor.routing.TrailingSlashRouteSelector
|
||||||
|
import io.ktor.util.InternalAPI
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extensible interface for calculating Ktor paths
|
* Responsible for calculating a url path from a provided [Route]
|
||||||
*/
|
*/
|
||||||
interface PathCalculator {
|
@OptIn(InternalAPI::class)
|
||||||
|
internal object PathCalculator: IPathCalculator {
|
||||||
|
|
||||||
/**
|
private val pathHandler: RouteHandlerMap = mutableMapOf()
|
||||||
* Core route calculation method
|
|
||||||
*/
|
|
||||||
fun calculate(route: Route?, tail: String = ""): String
|
|
||||||
|
|
||||||
/**
|
init {
|
||||||
* Used to handle any custom selectors that may be missed by the base route calculation
|
addCustomRouteHandler(RootRouteSelector::class) { _, tail -> tail }
|
||||||
*/
|
addCustomRouteHandler(PathSegmentParameterRouteSelector::class) { route, tail ->
|
||||||
fun handleCustomSelectors(route: Route, tail: String): String
|
val newTail = "/${route.selector}$tail"
|
||||||
|
calculate(route.parent, newTail)
|
||||||
|
}
|
||||||
|
addCustomRouteHandler(PathSegmentConstantRouteSelector::class) { route, tail ->
|
||||||
|
val newTail = "/${route.selector}$tail"
|
||||||
|
calculate(route.parent, newTail)
|
||||||
|
}
|
||||||
|
addCustomRouteHandler(TrailingSlashRouteSelector::class) { route, tail ->
|
||||||
|
val newTail = tail.ifBlank { "/" }
|
||||||
|
calculate(route.parent, newTail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(InternalAPI::class)
|
||||||
|
override fun calculate(
|
||||||
|
route: Route?,
|
||||||
|
tail: String
|
||||||
|
): String = when (route) {
|
||||||
|
null -> tail
|
||||||
|
else -> when (pathHandler.containsKey(route.selector::class)) {
|
||||||
|
true -> pathHandler[route.selector::class]!!.invoke(this, route, tail)
|
||||||
|
else -> error("No handler has been registered for ${route.selector}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : RouteSelector> addCustomRouteHandler(
|
||||||
|
selector: KClass<T>,
|
||||||
|
handler: IPathCalculator.(Route, String) -> String
|
||||||
|
) {
|
||||||
|
pathHandler[selector] = handler
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package io.bkbn.kompendium.path
|
||||||
|
|
||||||
|
import io.ktor.routing.Route
|
||||||
|
import io.ktor.routing.RouteSelector
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
typealias RouteHandlerMap = MutableMap<KClass<out RouteSelector>, IPathCalculator.(Route, String) -> String>
|
@ -1,20 +1,26 @@
|
|||||||
package io.bkbn.kompendium.routes
|
package io.bkbn.kompendium.routes
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import com.fasterxml.jackson.databind.SerializationFeature
|
||||||
|
import io.bkbn.kompendium.models.oas.OpenApiSpec
|
||||||
import io.ktor.application.call
|
import io.ktor.application.call
|
||||||
import io.ktor.response.respond
|
import io.ktor.response.respondText
|
||||||
import io.ktor.routing.Routing
|
import io.ktor.routing.Routing
|
||||||
import io.ktor.routing.get
|
import io.ktor.routing.get
|
||||||
import io.ktor.routing.route
|
import io.ktor.routing.route
|
||||||
import io.bkbn.kompendium.models.oas.OpenApiSpec
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides an out-of-the-box route to return the generated [OpenApiSpec]
|
* Provides an out-of-the-box route to return the generated [OpenApiSpec]
|
||||||
* @param oas spec that is returned
|
* @param oas spec that is returned
|
||||||
*/
|
*/
|
||||||
fun Routing.openApi(oas: OpenApiSpec) {
|
fun Routing.openApi(oas: OpenApiSpec) {
|
||||||
|
val om = ObjectMapper()
|
||||||
|
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
||||||
|
.enable(SerializationFeature.INDENT_OUTPUT)
|
||||||
route("/openapi.json") {
|
route("/openapi.json") {
|
||||||
get {
|
get {
|
||||||
call.respond(oas)
|
call.respondText { om.writeValueAsString(oas) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,11 @@ import io.bkbn.kompendium.routes.openApi
|
|||||||
import io.bkbn.kompendium.routes.redoc
|
import io.bkbn.kompendium.routes.redoc
|
||||||
import io.bkbn.kompendium.util.TestHelpers.getFileSnapshot
|
import io.bkbn.kompendium.util.TestHelpers.getFileSnapshot
|
||||||
import io.bkbn.kompendium.util.complexType
|
import io.bkbn.kompendium.util.complexType
|
||||||
import io.bkbn.kompendium.util.configModule
|
import io.bkbn.kompendium.util.jacksonConfigModule
|
||||||
import io.bkbn.kompendium.util.emptyGet
|
import io.bkbn.kompendium.util.emptyGet
|
||||||
import io.bkbn.kompendium.util.genericPolymorphicResponse
|
import io.bkbn.kompendium.util.genericPolymorphicResponse
|
||||||
import io.bkbn.kompendium.util.genericPolymorphicResponseMultipleImpls
|
import io.bkbn.kompendium.util.genericPolymorphicResponseMultipleImpls
|
||||||
|
import io.bkbn.kompendium.util.kotlinxConfigModule
|
||||||
import io.bkbn.kompendium.util.nestedUnderRootModule
|
import io.bkbn.kompendium.util.nestedUnderRootModule
|
||||||
import io.bkbn.kompendium.util.nonRequiredParamsGet
|
import io.bkbn.kompendium.util.nonRequiredParamsGet
|
||||||
import io.bkbn.kompendium.util.notarizedDeleteModule
|
import io.bkbn.kompendium.util.notarizedDeleteModule
|
||||||
@ -31,6 +32,9 @@ import io.bkbn.kompendium.util.notarizedGetWithNotarizedException
|
|||||||
import io.bkbn.kompendium.util.notarizedPostModule
|
import io.bkbn.kompendium.util.notarizedPostModule
|
||||||
import io.bkbn.kompendium.util.notarizedPutModule
|
import io.bkbn.kompendium.util.notarizedPutModule
|
||||||
import io.bkbn.kompendium.util.pathParsingTestModule
|
import io.bkbn.kompendium.util.pathParsingTestModule
|
||||||
|
import io.bkbn.kompendium.util.polymorphicCollectionResponse
|
||||||
|
import io.bkbn.kompendium.util.polymorphicInterfaceResponse
|
||||||
|
import io.bkbn.kompendium.util.polymorphicMapResponse
|
||||||
import io.bkbn.kompendium.util.polymorphicResponse
|
import io.bkbn.kompendium.util.polymorphicResponse
|
||||||
import io.bkbn.kompendium.util.primitives
|
import io.bkbn.kompendium.util.primitives
|
||||||
import io.bkbn.kompendium.util.returnsList
|
import io.bkbn.kompendium.util.returnsList
|
||||||
@ -39,6 +43,7 @@ import io.bkbn.kompendium.util.simpleGenericResponse
|
|||||||
import io.bkbn.kompendium.util.statusPageModule
|
import io.bkbn.kompendium.util.statusPageModule
|
||||||
import io.bkbn.kompendium.util.statusPageMultiExceptions
|
import io.bkbn.kompendium.util.statusPageMultiExceptions
|
||||||
import io.bkbn.kompendium.util.trailingSlash
|
import io.bkbn.kompendium.util.trailingSlash
|
||||||
|
import io.bkbn.kompendium.util.undeclaredType
|
||||||
import io.bkbn.kompendium.util.withDefaultParameter
|
import io.bkbn.kompendium.util.withDefaultParameter
|
||||||
import io.bkbn.kompendium.util.withExamples
|
import io.bkbn.kompendium.util.withExamples
|
||||||
|
|
||||||
@ -57,7 +62,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Notarized Get records all expected information`() {
|
fun `Notarized Get records all expected information`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
kotlinxConfigModule()
|
||||||
docs()
|
docs()
|
||||||
notarizedGetModule()
|
notarizedGetModule()
|
||||||
}) {
|
}) {
|
||||||
@ -73,7 +78,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Notarized Get does not interrupt the pipeline`() {
|
fun `Notarized Get does not interrupt the pipeline`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
notarizedGetModule()
|
notarizedGetModule()
|
||||||
}) {
|
}) {
|
||||||
@ -89,7 +94,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Notarized Post records all expected information`() {
|
fun `Notarized Post records all expected information`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
notarizedPostModule()
|
notarizedPostModule()
|
||||||
}) {
|
}) {
|
||||||
@ -105,7 +110,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Notarized post does not interrupt the pipeline`() {
|
fun `Notarized post does not interrupt the pipeline`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
kotlinxConfigModule()
|
||||||
docs()
|
docs()
|
||||||
notarizedPostModule()
|
notarizedPostModule()
|
||||||
}) {
|
}) {
|
||||||
@ -121,7 +126,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Notarized Put records all expected information`() {
|
fun `Notarized Put records all expected information`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
notarizedPutModule()
|
notarizedPutModule()
|
||||||
}) {
|
}) {
|
||||||
@ -138,7 +143,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Notarized put does not interrupt the pipeline`() {
|
fun `Notarized put does not interrupt the pipeline`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
notarizedPutModule()
|
notarizedPutModule()
|
||||||
}) {
|
}) {
|
||||||
@ -154,7 +159,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Notarized delete records all expected information`() {
|
fun `Notarized delete records all expected information`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
notarizedDeleteModule()
|
notarizedDeleteModule()
|
||||||
}) {
|
}) {
|
||||||
@ -170,7 +175,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Notarized delete does not interrupt the pipeline`() {
|
fun `Notarized delete does not interrupt the pipeline`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
notarizedDeleteModule()
|
notarizedDeleteModule()
|
||||||
}) {
|
}) {
|
||||||
@ -185,7 +190,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Path parser stores the expected path`() {
|
fun `Path parser stores the expected path`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
pathParsingTestModule()
|
pathParsingTestModule()
|
||||||
}) {
|
}) {
|
||||||
@ -201,7 +206,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Can notarize the root route`() {
|
fun `Can notarize the root route`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
rootModule()
|
rootModule()
|
||||||
}) {
|
}) {
|
||||||
@ -217,7 +222,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Can call the root route`() {
|
fun `Can call the root route`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
kotlinxConfigModule()
|
||||||
docs()
|
docs()
|
||||||
rootModule()
|
rootModule()
|
||||||
}) {
|
}) {
|
||||||
@ -233,7 +238,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Nested under root module does not append trailing slash`() {
|
fun `Nested under root module does not append trailing slash`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
nestedUnderRootModule()
|
nestedUnderRootModule()
|
||||||
}) {
|
}) {
|
||||||
@ -249,7 +254,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Can notarize a trailing slash route`() {
|
fun `Can notarize a trailing slash route`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
trailingSlash()
|
trailingSlash()
|
||||||
}) {
|
}) {
|
||||||
@ -265,7 +270,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Can call a trailing slash route`() {
|
fun `Can call a trailing slash route`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
trailingSlash()
|
trailingSlash()
|
||||||
}) {
|
}) {
|
||||||
@ -281,7 +286,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Can notarize a complex type`() {
|
fun `Can notarize a complex type`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
complexType()
|
complexType()
|
||||||
}) {
|
}) {
|
||||||
@ -297,7 +302,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Can notarize primitives`() {
|
fun `Can notarize primitives`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
primitives()
|
primitives()
|
||||||
}) {
|
}) {
|
||||||
@ -313,7 +318,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Can notarize a top level list response`() {
|
fun `Can notarize a top level list response`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
returnsList()
|
returnsList()
|
||||||
}) {
|
}) {
|
||||||
@ -329,7 +334,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Can notarize route with no request params and no response body`() {
|
fun `Can notarize route with no request params and no response body`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
kotlinxConfigModule()
|
||||||
docs()
|
docs()
|
||||||
emptyGet()
|
emptyGet()
|
||||||
}) {
|
}) {
|
||||||
@ -345,7 +350,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Can notarize route with non-required params`() {
|
fun `Can notarize route with non-required params`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
nonRequiredParamsGet()
|
nonRequiredParamsGet()
|
||||||
}) {
|
}) {
|
||||||
@ -361,7 +366,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Generates the expected redoc`() {
|
fun `Generates the expected redoc`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
returnsList()
|
returnsList()
|
||||||
}) {
|
}) {
|
||||||
@ -378,7 +383,7 @@ internal class KompendiumTest {
|
|||||||
fun `Generates additional responses when passed a throwable`() {
|
fun `Generates additional responses when passed a throwable`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
statusPageModule()
|
statusPageModule()
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
notarizedGetWithNotarizedException()
|
notarizedGetWithNotarizedException()
|
||||||
}) {
|
}) {
|
||||||
@ -395,7 +400,7 @@ internal class KompendiumTest {
|
|||||||
fun `Generates additional responses when passed multiple throwables`() {
|
fun `Generates additional responses when passed multiple throwables`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
statusPageMultiExceptions()
|
statusPageMultiExceptions()
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
notarizedGetWithMultipleThrowables()
|
notarizedGetWithMultipleThrowables()
|
||||||
}) {
|
}) {
|
||||||
@ -411,7 +416,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Can generate example response and request bodies`() {
|
fun `Can generate example response and request bodies`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
kotlinxConfigModule()
|
||||||
docs()
|
docs()
|
||||||
withExamples()
|
withExamples()
|
||||||
}) {
|
}) {
|
||||||
@ -427,7 +432,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Can generate a default parameter value`() {
|
fun `Can generate a default parameter value`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
withDefaultParameter()
|
withDefaultParameter()
|
||||||
}) {
|
}) {
|
||||||
@ -443,7 +448,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Can generate a polymorphic response type`() {
|
fun `Can generate a polymorphic response type`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
polymorphicResponse()
|
polymorphicResponse()
|
||||||
}) {
|
}) {
|
||||||
@ -456,10 +461,58 @@ internal class KompendiumTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Can generate a collection with polymorphic response type`() {
|
||||||
|
withTestApplication({
|
||||||
|
jacksonConfigModule()
|
||||||
|
docs()
|
||||||
|
polymorphicCollectionResponse()
|
||||||
|
}) {
|
||||||
|
// do
|
||||||
|
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
|
||||||
|
|
||||||
|
// expect
|
||||||
|
val expected = getFileSnapshot("polymorphic_list_response.json").trim()
|
||||||
|
assertEquals(expected, json, "The received json spec should match the expected content")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Can generate a map with a polymorphic response type`() {
|
||||||
|
withTestApplication({
|
||||||
|
jacksonConfigModule()
|
||||||
|
docs()
|
||||||
|
polymorphicMapResponse()
|
||||||
|
}) {
|
||||||
|
// do
|
||||||
|
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
|
||||||
|
|
||||||
|
// expect
|
||||||
|
val expected = getFileSnapshot("polymorphic_map_response.json").trim()
|
||||||
|
assertEquals(expected, json, "The received json spec should match the expected content")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Can generate a polymorphic response from a sealed interface`() {
|
||||||
|
withTestApplication({
|
||||||
|
jacksonConfigModule()
|
||||||
|
docs()
|
||||||
|
polymorphicInterfaceResponse()
|
||||||
|
}) {
|
||||||
|
// do
|
||||||
|
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
|
||||||
|
|
||||||
|
// expect
|
||||||
|
val expected = getFileSnapshot("sealed_interface_response.json").trim()
|
||||||
|
assertEquals(expected, json, "The received json spec should match the expected content")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Can generate a response type with a generic type`() {
|
fun `Can generate a response type with a generic type`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
simpleGenericResponse()
|
simpleGenericResponse()
|
||||||
}) {
|
}) {
|
||||||
@ -475,7 +528,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Can generate a polymorphic response type with generics`() {
|
fun `Can generate a polymorphic response type with generics`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
jacksonConfigModule()
|
||||||
docs()
|
docs()
|
||||||
genericPolymorphicResponse()
|
genericPolymorphicResponse()
|
||||||
}) {
|
}) {
|
||||||
@ -491,7 +544,7 @@ internal class KompendiumTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Absolute Psycho Inheritance Test`() {
|
fun `Absolute Psycho Inheritance Test`() {
|
||||||
withTestApplication({
|
withTestApplication({
|
||||||
configModule()
|
kotlinxConfigModule()
|
||||||
docs()
|
docs()
|
||||||
genericPolymorphicResponseMultipleImpls()
|
genericPolymorphicResponseMultipleImpls()
|
||||||
}) {
|
}) {
|
||||||
@ -504,6 +557,22 @@ internal class KompendiumTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Can add an undeclared field`() {
|
||||||
|
withTestApplication({
|
||||||
|
kotlinxConfigModule()
|
||||||
|
docs()
|
||||||
|
undeclaredType()
|
||||||
|
}) {
|
||||||
|
// do
|
||||||
|
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
|
||||||
|
|
||||||
|
// expect
|
||||||
|
val expected = getFileSnapshot("undeclared_field.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(
|
||||||
title = "Test API",
|
title = "Test API",
|
||||||
|
@ -13,15 +13,7 @@ import io.bkbn.kompendium.models.oas.DictionarySchema
|
|||||||
import io.bkbn.kompendium.models.oas.FormatSchema
|
import io.bkbn.kompendium.models.oas.FormatSchema
|
||||||
import io.bkbn.kompendium.models.oas.ObjectSchema
|
import io.bkbn.kompendium.models.oas.ObjectSchema
|
||||||
import io.bkbn.kompendium.models.oas.ReferencedSchema
|
import io.bkbn.kompendium.models.oas.ReferencedSchema
|
||||||
import io.bkbn.kompendium.util.ComplexRequest
|
import io.bkbn.kompendium.util.*
|
||||||
import io.bkbn.kompendium.util.TestInvalidMap
|
|
||||||
import io.bkbn.kompendium.util.TestNestedModel
|
|
||||||
import io.bkbn.kompendium.util.TestSimpleModel
|
|
||||||
import io.bkbn.kompendium.util.TestSimpleWithEnumList
|
|
||||||
import io.bkbn.kompendium.util.TestSimpleWithEnums
|
|
||||||
import io.bkbn.kompendium.util.TestSimpleWithList
|
|
||||||
import io.bkbn.kompendium.util.TestSimpleWithMap
|
|
||||||
import io.bkbn.kompendium.util.TestWithUUID
|
|
||||||
|
|
||||||
@ExperimentalStdlibApi
|
@ExperimentalStdlibApi
|
||||||
internal class KontentTest {
|
internal class KontentTest {
|
||||||
@ -45,6 +37,29 @@ 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
|
||||||
|
fun `Object with ByteArray type`() {
|
||||||
|
// do
|
||||||
|
val result = generateKontent<TestByteArrayModel>()
|
||||||
|
|
||||||
|
// expect
|
||||||
|
assertEquals(2, result.count())
|
||||||
|
assertTrue { result.containsKey(TestByteArrayModel::class.simpleName) }
|
||||||
|
assertEquals(FormatSchema("byte", "string"), result["ByteArray"])
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Objects reference their base types in the cache`() {
|
fun `Objects reference their base types in the cache`() {
|
||||||
// do
|
// do
|
||||||
|
@ -4,9 +4,16 @@ import java.util.UUID
|
|||||||
import io.bkbn.kompendium.annotations.KompendiumField
|
import io.bkbn.kompendium.annotations.KompendiumField
|
||||||
import io.bkbn.kompendium.annotations.KompendiumParam
|
import io.bkbn.kompendium.annotations.KompendiumParam
|
||||||
import io.bkbn.kompendium.annotations.ParamType
|
import io.bkbn.kompendium.annotations.ParamType
|
||||||
|
import io.bkbn.kompendium.annotations.UndeclaredField
|
||||||
|
import java.math.BigDecimal
|
||||||
|
import java.math.BigInteger
|
||||||
|
|
||||||
data class TestSimpleModel(val a: String, val b: Int)
|
data class TestSimpleModel(val a: String, val b: Int)
|
||||||
|
|
||||||
|
data class TestBigNumberModel(val a: BigDecimal, val b: BigInteger)
|
||||||
|
|
||||||
|
data class TestByteArrayModel(val a: ByteArray)
|
||||||
|
|
||||||
data class TestNestedModel(val inner: TestSimpleModel)
|
data class TestNestedModel(val inner: TestSimpleModel)
|
||||||
|
|
||||||
data class TestSimpleWithEnums(val a: String, val b: SimpleEnum)
|
data class TestSimpleWithEnums(val a: String, val b: SimpleEnum)
|
||||||
@ -80,7 +87,21 @@ sealed class FlibbityGibbit
|
|||||||
data class SimpleGibbit(val a: String) : FlibbityGibbit()
|
data class SimpleGibbit(val a: String) : FlibbityGibbit()
|
||||||
data class ComplexGibbit(val b: String, val c: Int) : FlibbityGibbit()
|
data class ComplexGibbit(val b: String, val c: Int) : FlibbityGibbit()
|
||||||
|
|
||||||
|
sealed interface SlammaJamma
|
||||||
|
|
||||||
|
data class OneJamma(val a: Int) : SlammaJamma
|
||||||
|
data class AnothaJamma(val b: Float) : SlammaJamma
|
||||||
|
//data class InsaneJamma(val c: SlammaJamma) : SlammaJamma // 👀
|
||||||
|
|
||||||
sealed interface Flibbity<T>
|
sealed interface Flibbity<T>
|
||||||
|
|
||||||
data class Gibbity<T>(val a: T): Flibbity<T>
|
data class Gibbity<T>(val a: T) : Flibbity<T>
|
||||||
data class Bibbity<T>(val b: String, val f: T) : Flibbity<T>
|
data class Bibbity<T>(val b: String, val f: T) : Flibbity<T>
|
||||||
|
|
||||||
|
enum class Hehe {
|
||||||
|
HAHA,
|
||||||
|
HOHO
|
||||||
|
}
|
||||||
|
|
||||||
|
@UndeclaredField("nowYouDont", Hehe::class)
|
||||||
|
data class Mysterious(val nowYouSeeMe: String)
|
||||||
|
@ -21,8 +21,9 @@ import io.ktor.response.respond
|
|||||||
import io.ktor.response.respondText
|
import io.ktor.response.respondText
|
||||||
import io.ktor.routing.route
|
import io.ktor.routing.route
|
||||||
import io.ktor.routing.routing
|
import io.ktor.routing.routing
|
||||||
|
import io.ktor.serialization.json
|
||||||
|
|
||||||
fun Application.configModule() {
|
fun Application.jacksonConfigModule() {
|
||||||
install(ContentNegotiation) {
|
install(ContentNegotiation) {
|
||||||
jackson {
|
jackson {
|
||||||
enable(SerializationFeature.INDENT_OUTPUT)
|
enable(SerializationFeature.INDENT_OUTPUT)
|
||||||
@ -31,6 +32,12 @@ fun Application.configModule() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Application.kotlinxConfigModule() {
|
||||||
|
install(ContentNegotiation) {
|
||||||
|
json()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun Application.statusPageModule() {
|
fun Application.statusPageModule() {
|
||||||
install(StatusPages) {
|
install(StatusPages) {
|
||||||
notarizedException<Exception, ExceptionResponse>(
|
notarizedException<Exception, ExceptionResponse>(
|
||||||
@ -278,6 +285,36 @@ fun Application.polymorphicResponse() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Application.polymorphicCollectionResponse() {
|
||||||
|
routing {
|
||||||
|
route("/test/polymorphiclist") {
|
||||||
|
notarizedGet(TestResponseInfo.polymorphicListResponse) {
|
||||||
|
call.respond(HttpStatusCode.OK, listOf(SimpleGibbit("hi")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Application.polymorphicMapResponse() {
|
||||||
|
routing {
|
||||||
|
route("/test/polymorphicmap") {
|
||||||
|
notarizedGet(TestResponseInfo.polymorphicMapResponse) {
|
||||||
|
call.respond(HttpStatusCode.OK, listOf(SimpleGibbit("hi")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Application.polymorphicInterfaceResponse() {
|
||||||
|
routing {
|
||||||
|
route("/test/polymorphicmap") {
|
||||||
|
notarizedGet(TestResponseInfo.polymorphicInterfaceResponse) {
|
||||||
|
call.respond(HttpStatusCode.OK, listOf(SimpleGibbit("hi")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun Application.genericPolymorphicResponse() {
|
fun Application.genericPolymorphicResponse() {
|
||||||
routing {
|
routing {
|
||||||
route("/test/polymorphic") {
|
route("/test/polymorphic") {
|
||||||
@ -303,6 +340,16 @@ fun Application.genericPolymorphicResponseMultipleImpls() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Application.undeclaredType() {
|
||||||
|
routing {
|
||||||
|
route("/test/polymorphic") {
|
||||||
|
notarizedGet(TestResponseInfo.undeclaredResponseType) {
|
||||||
|
call.respond(HttpStatusCode.OK, Mysterious("hi"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun Application.simpleGenericResponse() {
|
fun Application.simpleGenericResponse() {
|
||||||
routing {
|
routing {
|
||||||
route("/test/polymorphic") {
|
route("/test/polymorphic") {
|
||||||
|
@ -78,6 +78,21 @@ object TestResponseInfo {
|
|||||||
description = "Polymorphic response",
|
description = "Polymorphic response",
|
||||||
responseInfo = simpleOkResponse()
|
responseInfo = simpleOkResponse()
|
||||||
)
|
)
|
||||||
|
val polymorphicListResponse = GetInfo<Unit, List<FlibbityGibbit>>(
|
||||||
|
summary = "Oh so many gibbits",
|
||||||
|
description = "Polymorphic list response",
|
||||||
|
responseInfo = simpleOkResponse()
|
||||||
|
)
|
||||||
|
val polymorphicMapResponse = GetInfo<Unit, Map<String, FlibbityGibbit>>(
|
||||||
|
summary = "By gawd that's a lot of gibbits",
|
||||||
|
description = "Polymorphic list response",
|
||||||
|
responseInfo = simpleOkResponse()
|
||||||
|
)
|
||||||
|
val polymorphicInterfaceResponse = GetInfo<Unit, SlammaJamma>(
|
||||||
|
summary = "Come on and slam",
|
||||||
|
description = "and welcome to the jam",
|
||||||
|
responseInfo = simpleOkResponse()
|
||||||
|
)
|
||||||
val genericPolymorphicResponse = GetInfo<Unit, Flibbity<TestNested>>(
|
val genericPolymorphicResponse = GetInfo<Unit, Flibbity<TestNested>>(
|
||||||
summary = "More flibbity",
|
summary = "More flibbity",
|
||||||
description = "Polymorphic with generics",
|
description = "Polymorphic with generics",
|
||||||
@ -88,6 +103,11 @@ object TestResponseInfo {
|
|||||||
description = "Polymorphic with generics but like... crazier",
|
description = "Polymorphic with generics but like... crazier",
|
||||||
responseInfo = simpleOkResponse()
|
responseInfo = simpleOkResponse()
|
||||||
)
|
)
|
||||||
|
val undeclaredResponseType = GetInfo<Unit, Mysterious>(
|
||||||
|
summary = "spooky class",
|
||||||
|
description = "break this glass in scenario of emergency",
|
||||||
|
responseInfo = simpleOkResponse()
|
||||||
|
)
|
||||||
val genericResponse = GetInfo<Unit, TestGeneric<Int>>(
|
val genericResponse = GetInfo<Unit, TestGeneric<Int>>(
|
||||||
summary = "Single Generic",
|
summary = "Single Generic",
|
||||||
description = "Simple generic data class",
|
description = "Simple generic data class",
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -62,24 +62,25 @@
|
|||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"SimpleEnum" : {
|
"SimpleEnum" : {
|
||||||
"enum" : [ "ONE", "TWO" ],
|
"type" : "string",
|
||||||
"type" : "string"
|
"enum" : [ "ONE", "TWO" ]
|
||||||
},
|
},
|
||||||
"CrazyItem" : {
|
"CrazyItem" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"enumeration" : {
|
"enumeration" : {
|
||||||
"$ref" : "#/components/schemas/SimpleEnum"
|
"$ref" : "#/components/schemas/SimpleEnum"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Map-String-CrazyItem" : {
|
"Map-String-CrazyItem" : {
|
||||||
|
"type" : "object",
|
||||||
"additionalProperties" : {
|
"additionalProperties" : {
|
||||||
"$ref" : "#/components/schemas/CrazyItem"
|
"$ref" : "#/components/schemas/CrazyItem"
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"NestedComplexItem" : {
|
"NestedComplexItem" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"alias" : {
|
"alias" : {
|
||||||
"$ref" : "#/components/schemas/Map-String-CrazyItem"
|
"$ref" : "#/components/schemas/Map-String-CrazyItem"
|
||||||
@ -87,16 +88,16 @@
|
|||||||
"name" : {
|
"name" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"List-NestedComplexItem" : {
|
"List-NestedComplexItem" : {
|
||||||
|
"type" : "array",
|
||||||
"items" : {
|
"items" : {
|
||||||
"$ref" : "#/components/schemas/NestedComplexItem"
|
"$ref" : "#/components/schemas/NestedComplexItem"
|
||||||
},
|
}
|
||||||
"type" : "array"
|
|
||||||
},
|
},
|
||||||
"ComplexRequest" : {
|
"ComplexRequest" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"amazingField" : {
|
"amazingField" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
@ -107,14 +108,14 @@
|
|||||||
"tables" : {
|
"tables" : {
|
||||||
"$ref" : "#/components/schemas/List-NestedComplexItem"
|
"$ref" : "#/components/schemas/List-NestedComplexItem"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Int" : {
|
"Int" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"TestCreatedResponse" : {
|
"TestCreatedResponse" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"c" : {
|
"c" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
@ -122,8 +123,7 @@
|
|||||||
"id" : {
|
"id" : {
|
||||||
"$ref" : "#/components/schemas/Int"
|
"$ref" : "#/components/schemas/Int"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -80,22 +80,23 @@
|
|||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"TestNested" : {
|
"TestNested" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"nesty" : {
|
"nesty" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Gibbity-TestNested" : {
|
"Gibbity-TestNested" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"a" : {
|
"a" : {
|
||||||
"$ref" : "#/components/schemas/TestNested"
|
"$ref" : "#/components/schemas/TestNested"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Bibbity-TestNested" : {
|
"Bibbity-TestNested" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"b" : {
|
"b" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
@ -103,22 +104,22 @@
|
|||||||
"f" : {
|
"f" : {
|
||||||
"$ref" : "#/components/schemas/TestNested"
|
"$ref" : "#/components/schemas/TestNested"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"SimpleGibbit" : {
|
"SimpleGibbit" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"a" : {
|
"a" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Int" : {
|
"Int" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"ComplexGibbit" : {
|
"ComplexGibbit" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"b" : {
|
"b" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
@ -126,10 +127,10 @@
|
|||||||
"c" : {
|
"c" : {
|
||||||
"$ref" : "#/components/schemas/Int"
|
"$ref" : "#/components/schemas/Int"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Gibbity-FlibbityGibbit" : {
|
"Gibbity-FlibbityGibbit" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"a" : {
|
"a" : {
|
||||||
"anyOf" : [ {
|
"anyOf" : [ {
|
||||||
@ -138,10 +139,10 @@
|
|||||||
"$ref" : "#/components/schemas/ComplexGibbit"
|
"$ref" : "#/components/schemas/ComplexGibbit"
|
||||||
} ]
|
} ]
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Bibbity-FlibbityGibbit" : {
|
"Bibbity-FlibbityGibbit" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"b" : {
|
"b" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
@ -153,8 +154,7 @@
|
|||||||
"$ref" : "#/components/schemas/ComplexGibbit"
|
"$ref" : "#/components/schemas/ComplexGibbit"
|
||||||
} ]
|
} ]
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -86,31 +86,32 @@
|
|||||||
"components" : {
|
"components" : {
|
||||||
"schemas" : {
|
"schemas" : {
|
||||||
"Long" : {
|
"Long" : {
|
||||||
"format" : "int64",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int64"
|
||||||
},
|
},
|
||||||
"List-Long" : {
|
"List-Long" : {
|
||||||
|
"type" : "array",
|
||||||
"items" : {
|
"items" : {
|
||||||
"$ref" : "#/components/schemas/Long"
|
"$ref" : "#/components/schemas/Long"
|
||||||
},
|
}
|
||||||
"type" : "array"
|
|
||||||
},
|
},
|
||||||
"Double" : {
|
"Double" : {
|
||||||
"format" : "double",
|
"type" : "number",
|
||||||
"type" : "number"
|
"format" : "double"
|
||||||
},
|
},
|
||||||
"String" : {
|
"String" : {
|
||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"TestNested" : {
|
"TestNested" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"nesty" : {
|
"nesty" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"TestRequest" : {
|
"TestRequest" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"aaa" : {
|
"aaa" : {
|
||||||
"$ref" : "#/components/schemas/List-Long"
|
"$ref" : "#/components/schemas/List-Long"
|
||||||
@ -121,16 +122,15 @@
|
|||||||
"fieldName" : {
|
"fieldName" : {
|
||||||
"$ref" : "#/components/schemas/TestNested"
|
"$ref" : "#/components/schemas/TestNested"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"TestResponse" : {
|
"TestResponse" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"c" : {
|
"c" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -51,10 +51,11 @@
|
|||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"Int" : {
|
"Int" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"TestGeneric-Int" : {
|
"TestGeneric-Int" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"messy" : {
|
"messy" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
@ -62,8 +63,7 @@
|
|||||||
"potato" : {
|
"potato" : {
|
||||||
"$ref" : "#/components/schemas/Int"
|
"$ref" : "#/components/schemas/Int"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -40,8 +40,8 @@
|
|||||||
"name" : "aa",
|
"name" : "aa",
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"required" : true,
|
"required" : true,
|
||||||
"deprecated" : false
|
"deprecated" : false
|
||||||
@ -68,16 +68,16 @@
|
|||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"TestResponse" : {
|
"TestResponse" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"c" : {
|
"c" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Int" : {
|
"Int" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -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",
|
||||||
|
@ -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",
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -40,8 +40,8 @@
|
|||||||
"name" : "aa",
|
"name" : "aa",
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"required" : true,
|
"required" : true,
|
||||||
"deprecated" : false
|
"deprecated" : false
|
||||||
@ -61,8 +61,8 @@
|
|||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"Int" : {
|
"Int" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -40,8 +40,8 @@
|
|||||||
"name" : "aa",
|
"name" : "aa",
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"required" : true,
|
"required" : true,
|
||||||
"deprecated" : false
|
"deprecated" : false
|
||||||
@ -68,16 +68,16 @@
|
|||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"TestResponse" : {
|
"TestResponse" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"c" : {
|
"c" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Int" : {
|
"Int" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -40,8 +40,8 @@
|
|||||||
"name" : "aa",
|
"name" : "aa",
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"required" : true,
|
"required" : true,
|
||||||
"deprecated" : false
|
"deprecated" : false
|
||||||
@ -78,24 +78,24 @@
|
|||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"ExceptionResponse" : {
|
"ExceptionResponse" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"message" : {
|
"message" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"TestResponse" : {
|
"TestResponse" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"c" : {
|
"c" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Int" : {
|
"Int" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -40,8 +40,8 @@
|
|||||||
"name" : "aa",
|
"name" : "aa",
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"required" : true,
|
"required" : true,
|
||||||
"deprecated" : false
|
"deprecated" : false
|
||||||
@ -81,24 +81,24 @@
|
|||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"ExceptionResponse" : {
|
"ExceptionResponse" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"message" : {
|
"message" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"TestResponse" : {
|
"TestResponse" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"c" : {
|
"c" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Int" : {
|
"Int" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -40,8 +40,8 @@
|
|||||||
"name" : "aa",
|
"name" : "aa",
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"required" : true,
|
"required" : true,
|
||||||
"deprecated" : false
|
"deprecated" : false
|
||||||
@ -76,31 +76,32 @@
|
|||||||
"components" : {
|
"components" : {
|
||||||
"schemas" : {
|
"schemas" : {
|
||||||
"Long" : {
|
"Long" : {
|
||||||
"format" : "int64",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int64"
|
||||||
},
|
},
|
||||||
"List-Long" : {
|
"List-Long" : {
|
||||||
|
"type" : "array",
|
||||||
"items" : {
|
"items" : {
|
||||||
"$ref" : "#/components/schemas/Long"
|
"$ref" : "#/components/schemas/Long"
|
||||||
},
|
}
|
||||||
"type" : "array"
|
|
||||||
},
|
},
|
||||||
"Double" : {
|
"Double" : {
|
||||||
"format" : "double",
|
"type" : "number",
|
||||||
"type" : "number"
|
"format" : "double"
|
||||||
},
|
},
|
||||||
"String" : {
|
"String" : {
|
||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"TestNested" : {
|
"TestNested" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"nesty" : {
|
"nesty" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"TestRequest" : {
|
"TestRequest" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"aaa" : {
|
"aaa" : {
|
||||||
"$ref" : "#/components/schemas/List-Long"
|
"$ref" : "#/components/schemas/List-Long"
|
||||||
@ -111,14 +112,14 @@
|
|||||||
"fieldName" : {
|
"fieldName" : {
|
||||||
"$ref" : "#/components/schemas/TestNested"
|
"$ref" : "#/components/schemas/TestNested"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Int" : {
|
"Int" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"TestCreatedResponse" : {
|
"TestCreatedResponse" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"c" : {
|
"c" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
@ -126,8 +127,7 @@
|
|||||||
"id" : {
|
"id" : {
|
||||||
"$ref" : "#/components/schemas/Int"
|
"$ref" : "#/components/schemas/Int"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -59,8 +59,8 @@
|
|||||||
"components" : {
|
"components" : {
|
||||||
"schemas" : {
|
"schemas" : {
|
||||||
"Int" : {
|
"Int" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"Boolean" : {
|
"Boolean" : {
|
||||||
"type" : "boolean"
|
"type" : "boolean"
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -40,8 +40,8 @@
|
|||||||
"name" : "aa",
|
"name" : "aa",
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"required" : true,
|
"required" : true,
|
||||||
"deprecated" : false
|
"deprecated" : false
|
||||||
@ -76,31 +76,32 @@
|
|||||||
"components" : {
|
"components" : {
|
||||||
"schemas" : {
|
"schemas" : {
|
||||||
"Long" : {
|
"Long" : {
|
||||||
"format" : "int64",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int64"
|
||||||
},
|
},
|
||||||
"List-Long" : {
|
"List-Long" : {
|
||||||
|
"type" : "array",
|
||||||
"items" : {
|
"items" : {
|
||||||
"$ref" : "#/components/schemas/Long"
|
"$ref" : "#/components/schemas/Long"
|
||||||
},
|
}
|
||||||
"type" : "array"
|
|
||||||
},
|
},
|
||||||
"Double" : {
|
"Double" : {
|
||||||
"format" : "double",
|
"type" : "number",
|
||||||
"type" : "number"
|
"format" : "double"
|
||||||
},
|
},
|
||||||
"String" : {
|
"String" : {
|
||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"TestNested" : {
|
"TestNested" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"nesty" : {
|
"nesty" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"TestRequest" : {
|
"TestRequest" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"aaa" : {
|
"aaa" : {
|
||||||
"$ref" : "#/components/schemas/List-Long"
|
"$ref" : "#/components/schemas/List-Long"
|
||||||
@ -111,14 +112,14 @@
|
|||||||
"fieldName" : {
|
"fieldName" : {
|
||||||
"$ref" : "#/components/schemas/TestNested"
|
"$ref" : "#/components/schemas/TestNested"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Int" : {
|
"Int" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"TestCreatedResponse" : {
|
"TestCreatedResponse" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"c" : {
|
"c" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
@ -126,8 +127,7 @@
|
|||||||
"id" : {
|
"id" : {
|
||||||
"$ref" : "#/components/schemas/Int"
|
"$ref" : "#/components/schemas/Int"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -40,8 +40,8 @@
|
|||||||
"name" : "aa",
|
"name" : "aa",
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"required" : true,
|
"required" : true,
|
||||||
"deprecated" : false
|
"deprecated" : false
|
||||||
@ -68,16 +68,16 @@
|
|||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"TestResponse" : {
|
"TestResponse" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"c" : {
|
"c" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Int" : {
|
"Int" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -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" : [ ]
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -55,18 +55,19 @@
|
|||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"SimpleGibbit" : {
|
"SimpleGibbit" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"a" : {
|
"a" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Int" : {
|
"Int" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"ComplexGibbit" : {
|
"ComplexGibbit" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"b" : {
|
"b" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
@ -74,8 +75,7 @@
|
|||||||
"c" : {
|
"c" : {
|
||||||
"$ref" : "#/components/schemas/Int"
|
"$ref" : "#/components/schemas/Int"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -55,22 +55,23 @@
|
|||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"TestNested" : {
|
"TestNested" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"nesty" : {
|
"nesty" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Gibbity-TestNested" : {
|
"Gibbity-TestNested" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"a" : {
|
"a" : {
|
||||||
"$ref" : "#/components/schemas/TestNested"
|
"$ref" : "#/components/schemas/TestNested"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Bibbity-TestNested" : {
|
"Bibbity-TestNested" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"b" : {
|
"b" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
@ -78,8 +79,7 @@
|
|||||||
"f" : {
|
"f" : {
|
||||||
"$ref" : "#/components/schemas/TestNested"
|
"$ref" : "#/components/schemas/TestNested"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -32,9 +32,9 @@
|
|||||||
"name" : "a",
|
"name" : "a",
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"format" : "int32",
|
"default" : 100,
|
||||||
"type" : "integer",
|
"type" : "integer",
|
||||||
"default" : 100
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"required" : true,
|
"required" : true,
|
||||||
"deprecated" : false
|
"deprecated" : false
|
||||||
@ -65,16 +65,16 @@
|
|||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"TestResponse" : {
|
"TestResponse" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"c" : {
|
"c" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Int" : {
|
"Int" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"Boolean" : {
|
"Boolean" : {
|
||||||
"type" : "boolean"
|
"type" : "boolean"
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -40,8 +40,8 @@
|
|||||||
"name" : "aa",
|
"name" : "aa",
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"required" : true,
|
"required" : true,
|
||||||
"deprecated" : false
|
"deprecated" : false
|
||||||
@ -68,22 +68,22 @@
|
|||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"TestResponse" : {
|
"TestResponse" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"c" : {
|
"c" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"List-TestResponse" : {
|
"List-TestResponse" : {
|
||||||
|
"type" : "array",
|
||||||
"items" : {
|
"items" : {
|
||||||
"$ref" : "#/components/schemas/TestResponse"
|
"$ref" : "#/components/schemas/TestResponse"
|
||||||
},
|
}
|
||||||
"type" : "array"
|
|
||||||
},
|
},
|
||||||
"Int" : {
|
"Int" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"info" : {
|
"info" : {
|
||||||
"title" : "Test API",
|
"title" : "Test API",
|
||||||
"version" : "1.33.7",
|
"version" : "1.33.7",
|
||||||
"description" : "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
"description" : "An amazing, fully-ish 😉 generated API spec",
|
||||||
"termsOfService" : "https://example.com",
|
"termsOfService" : "https://example.com",
|
||||||
"contact" : {
|
"contact" : {
|
||||||
"name" : "Homer Simpson",
|
"name" : "Homer Simpson",
|
||||||
@ -40,8 +40,8 @@
|
|||||||
"name" : "aa",
|
"name" : "aa",
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
},
|
},
|
||||||
"required" : true,
|
"required" : true,
|
||||||
"deprecated" : false
|
"deprecated" : false
|
||||||
@ -68,16 +68,16 @@
|
|||||||
"type" : "string"
|
"type" : "string"
|
||||||
},
|
},
|
||||||
"TestResponse" : {
|
"TestResponse" : {
|
||||||
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"c" : {
|
"c" : {
|
||||||
"$ref" : "#/components/schemas/String"
|
"$ref" : "#/components/schemas/String"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"type" : "object"
|
|
||||||
},
|
},
|
||||||
"Int" : {
|
"Int" : {
|
||||||
"format" : "int32",
|
"type" : "integer",
|
||||||
"type" : "integer"
|
"format" : "int32"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes" : { }
|
"securitySchemes" : { }
|
||||||
|
@ -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",
|
||||||
@ -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" : { }
|
||||||
|
73
kompendium-core/src/test/resources/undeclared_field.json
Normal file
73
kompendium-core/src/test/resources/undeclared_field.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" : "spooky class",
|
||||||
|
"description" : "break this glass in scenario of emergency",
|
||||||
|
"parameters" : [ ],
|
||||||
|
"responses" : {
|
||||||
|
"200" : {
|
||||||
|
"description" : "A successful endeavor",
|
||||||
|
"content" : {
|
||||||
|
"application/json" : {
|
||||||
|
"schema" : {
|
||||||
|
"$ref" : "#/components/schemas/Mysterious"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deprecated" : false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components" : {
|
||||||
|
"schemas" : {
|
||||||
|
"String" : {
|
||||||
|
"type" : "string"
|
||||||
|
},
|
||||||
|
"Hehe" : {
|
||||||
|
"type" : "string",
|
||||||
|
"enum" : [ "HAHA", "HOHO" ]
|
||||||
|
},
|
||||||
|
"Mysterious" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"nowYouSeeMe" : {
|
||||||
|
"$ref" : "#/components/schemas/String"
|
||||||
|
},
|
||||||
|
"nowYouDont" : {
|
||||||
|
"$ref" : "#/components/schemas/Hehe"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"securitySchemes" : { }
|
||||||
|
},
|
||||||
|
"security" : [ ],
|
||||||
|
"tags" : [ ]
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
|
kotlin("plugin.serialization") version "1.5.0"
|
||||||
application
|
application
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11,9 +12,14 @@ dependencies {
|
|||||||
implementation(projects.kompendiumSwaggerUi)
|
implementation(projects.kompendiumSwaggerUi)
|
||||||
|
|
||||||
implementation(libs.bundles.ktor)
|
implementation(libs.bundles.ktor)
|
||||||
|
implementation(libs.ktor.jackson)
|
||||||
|
implementation(libs.kotlinx.serialization.json)
|
||||||
|
implementation(libs.ktor.serialization)
|
||||||
implementation(libs.bundles.ktorAuth)
|
implementation(libs.bundles.ktorAuth)
|
||||||
implementation(libs.bundles.logging)
|
implementation(libs.bundles.logging)
|
||||||
|
|
||||||
|
implementation("joda-time:joda-time:2.10.10")
|
||||||
|
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-test")
|
testImplementation("org.jetbrains.kotlin:kotlin-test")
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
|
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,28 @@
|
|||||||
package io.bkbn.kompendium.playground
|
package io.bkbn.kompendium.playground
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude
|
import io.bkbn.kompendium.Kompendium
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature
|
import io.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.playground.PlaygroundToC.testUndeclaredFields
|
||||||
|
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 +32,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 io.bkbn.kompendium.Notarized.notarizedDelete
|
import org.joda.time.DateTime
|
||||||
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.playground.PlaygroundToC.testAuthenticatedSingleGetInfo
|
|
||||||
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
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
|
Kompendium.addCustomTypeSchema(DateTime::class, FormatSchema("date-time", "string"))
|
||||||
|
|
||||||
embeddedServer(
|
embeddedServer(
|
||||||
Netty,
|
Netty,
|
||||||
port = 8081,
|
port = 8081,
|
||||||
@ -52,10 +57,7 @@ var featuresInstalled = false
|
|||||||
fun Application.configModule() {
|
fun Application.configModule() {
|
||||||
if (!featuresInstalled) {
|
if (!featuresInstalled) {
|
||||||
install(ContentNegotiation) {
|
install(ContentNegotiation) {
|
||||||
jackson {
|
json()
|
||||||
enable(SerializationFeature.INDENT_OUTPUT)
|
|
||||||
setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
install(Authentication) {
|
install(Authentication) {
|
||||||
notarizedBasic("basic") {
|
notarizedBasic("basic") {
|
||||||
@ -91,46 +93,56 @@ fun Application.mainModule() {
|
|||||||
openApi(oas)
|
openApi(oas)
|
||||||
redoc(oas)
|
redoc(oas)
|
||||||
swaggerUI()
|
swaggerUI()
|
||||||
// route("/potato/spud") {
|
route("/potato/spud") {
|
||||||
// notarizedGet(testGetWithExamples) {
|
notarizedGet(testGetWithExamples) {
|
||||||
// call.respond(HttpStatusCode.OK)
|
call.respond(HttpStatusCode.OK)
|
||||||
// }
|
}
|
||||||
// notarizedPost(testPostWithExamples) {
|
notarizedPost(testPostWithExamples) {
|
||||||
// call.respond(HttpStatusCode.Created, ExampleResponse("hey"))
|
call.respond(HttpStatusCode.Created, ExampleResponse("hey"))
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
route("/test") {
|
route("/test") {
|
||||||
route("/{id}") {
|
route("/{id}") {
|
||||||
notarizedGet(testIdGetInfo) {
|
notarizedGet(testIdGetInfo) {
|
||||||
call.respondText("get by id")
|
call.respondText("get by id")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// route("/single") {
|
route("/single") {
|
||||||
// notarizedGet(testSingleGetInfo) {
|
notarizedGet(testSingleGetInfo) {
|
||||||
// call.respondText("get single")
|
call.respondText("get single")
|
||||||
// }
|
}
|
||||||
// notarizedPost(testSinglePostInfo) {
|
notarizedPost(testSinglePostInfo) {
|
||||||
// call.respondText("test post")
|
call.respondText("test post")
|
||||||
// }
|
}
|
||||||
// notarizedPut(testSinglePutInfo) {
|
notarizedPut(testSinglePutInfo) {
|
||||||
// call.respondText { "hey" }
|
call.respondText { "hey" }
|
||||||
// }
|
}
|
||||||
// notarizedDelete(testSingleDeleteInfo) {
|
notarizedDelete(testSingleDeleteInfo) {
|
||||||
// call.respondText { "heya" }
|
call.respondText { "heya" }
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// authenticate("basic") {
|
route("custom_override") {
|
||||||
// route("/authenticated/single") {
|
notarizedGet(testCustomOverride) {
|
||||||
// notarizedGet(testAuthenticatedSingleGetInfo) {
|
call.respondText { DateTime.now().toString() }
|
||||||
// call.respond(HttpStatusCode.OK)
|
}
|
||||||
// }
|
}
|
||||||
// }
|
authenticate("basic") {
|
||||||
// }
|
route("/authenticated/single") {
|
||||||
|
notarizedGet(testAuthenticatedSingleGetInfo) {
|
||||||
|
call.respond(HttpStatusCode.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
route("/error") {
|
||||||
|
notarizedGet(testSingleGetInfoWithThrowable) {
|
||||||
|
error("bad things just happened")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
route("/undeclared") {
|
||||||
|
notarizedGet(testUndeclaredFields) {
|
||||||
|
call.respondText { "hi" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// route("/error") {
|
|
||||||
// notarizedGet(testSingleGetInfoWithThrowable) {
|
|
||||||
// error("bad things just happened")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ package io.bkbn.kompendium.playground
|
|||||||
import io.bkbn.kompendium.annotations.KompendiumField
|
import io.bkbn.kompendium.annotations.KompendiumField
|
||||||
import io.bkbn.kompendium.annotations.KompendiumParam
|
import io.bkbn.kompendium.annotations.KompendiumParam
|
||||||
import io.bkbn.kompendium.annotations.ParamType
|
import io.bkbn.kompendium.annotations.ParamType
|
||||||
|
import io.bkbn.kompendium.annotations.UndeclaredField
|
||||||
|
import org.joda.time.DateTime
|
||||||
|
|
||||||
data class ExampleParams(
|
data class ExampleParams(
|
||||||
@KompendiumParam(ParamType.PATH) val id: Int,
|
@KompendiumParam(ParamType.PATH) val id: Int,
|
||||||
@ -30,3 +32,13 @@ 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)
|
||||||
|
|
||||||
|
enum class Testerino {
|
||||||
|
First,
|
||||||
|
Second
|
||||||
|
}
|
||||||
|
|
||||||
|
@UndeclaredField("type", Testerino::class)
|
||||||
|
data class SimpleYetMysterious(val exists: Boolean)
|
||||||
|
@ -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)
|
||||||
@ -100,4 +109,13 @@ object PlaygroundToC {
|
|||||||
),
|
),
|
||||||
securitySchemes = setOf("basic")
|
securitySchemes = setOf("basic")
|
||||||
)
|
)
|
||||||
|
val testUndeclaredFields = MethodInfo.GetInfo<Unit, SimpleYetMysterious>(
|
||||||
|
summary = "Tests adding undeclared fields",
|
||||||
|
description = "vvv mysterious",
|
||||||
|
tags = setOf("mysterious"),
|
||||||
|
responseInfo = ResponseInfo(
|
||||||
|
status = HttpStatusCode.OK,
|
||||||
|
description = "good tings"
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
|
signing
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -11,12 +12,13 @@ dependencies {
|
|||||||
implementation(libs.webjars.swagger.ui)
|
implementation(libs.webjars.swagger.ui)
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-test")
|
testImplementation("org.jetbrains.kotlin:kotlin-test")
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
|
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
|
||||||
testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.12.0")
|
testImplementation(libs.jackson.module.kotlin)
|
||||||
testImplementation("io.ktor:ktor-server-test-host:1.5.3")
|
testImplementation(libs.ktor.server.test.host)
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
|
withJavadocJar()
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
@ -34,6 +36,41 @@ publishing {
|
|||||||
create<MavenPublication>("kompendium") {
|
create<MavenPublication>("kompendium") {
|
||||||
from(components["kotlin"])
|
from(components["kotlin"])
|
||||||
artifact(tasks.sourcesJar)
|
artifact(tasks.sourcesJar)
|
||||||
|
artifact(tasks.javadocJar)
|
||||||
|
groupId = project.group.toString()
|
||||||
|
artifactId = project.name.toLowerCase()
|
||||||
|
version = project.version.toString()
|
||||||
|
|
||||||
|
pom {
|
||||||
|
name.set("Kompendium")
|
||||||
|
description.set("A minimally invasive OpenAPI spec generator for Ktor")
|
||||||
|
url.set("https://github.com/bkbnio/Kompendium")
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name.set("MIT License")
|
||||||
|
url.set("https://mit-license.org/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
developers {
|
||||||
|
developer {
|
||||||
|
id.set("bkbnio")
|
||||||
|
name.set("Ryan Brink")
|
||||||
|
email.set("admin@bkbn.io")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scm {
|
||||||
|
connection.set("scm:git:git://github.com/bkbnio/Kompendium.git")
|
||||||
|
developerConnection.set("scm:git:ssh://github.com/bkbnio/Kompendium.git")
|
||||||
|
url.set("https://github.com/bkbnio/Kompendium.git")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signing {
|
||||||
|
val signingKey: String? by project
|
||||||
|
val signingPassword: String? by project
|
||||||
|
useInMemoryPgpKeys(signingKey, signingPassword)
|
||||||
|
sign(publishing.publications)
|
||||||
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
rootProject.name = "kompendium"
|
rootProject.name = "kompendium"
|
||||||
|
|
||||||
include("kompendium-core")
|
include("kompendium-core")
|
||||||
include("kompendium-auth")
|
include("kompendium-auth")
|
||||||
include("kompendium-swagger-ui")
|
include("kompendium-swagger-ui")
|
||||||
|
Reference in New Issue
Block a user