Compare commits
138 Commits
Author | SHA1 | Date | |
---|---|---|---|
178db951a5 | |||
fa5ada8f64 | |||
4345833b75 | |||
3158195bd9 | |||
70586a7cc6 | |||
6f4e268b91 | |||
a1638f930a | |||
0120feb168 | |||
1da3ad5db9 | |||
a8019bc4f8 | |||
ecf0d42ee1 | |||
d76927ba3c | |||
2c43d4d274 | |||
3111b63916 | |||
1759be5ba3 | |||
622dd6a5e7 | |||
6d6836927f | |||
9109a249e4 | |||
60552b8abb | |||
70345494ab | |||
b3dcf7dc8b | |||
b1aa2e497a | |||
d6b852d297 | |||
42ea128aa3 | |||
8df32d7af6 | |||
3f21879417 | |||
cf238beccb | |||
3b5324ded1 | |||
95ae274f1d | |||
fdcc64d29c | |||
4daf6e000e | |||
ba19389f16 | |||
e43627fa09 | |||
f1d252954b | |||
39d5c8b258 | |||
28b844da6c | |||
76e6b0a278 | |||
8ea6a001c2 | |||
190b3c4abe | |||
52e54b75b9 | |||
07bdeda364 | |||
bf31dd213c | |||
d6d3ca517e | |||
e589d917c8 | |||
196fba790a | |||
4d2c392b05 | |||
db696309c8 | |||
3326f10576 | |||
700cda2f46 | |||
3b50e67ff3 | |||
ee875b6fce | |||
c312b201b3 | |||
0d4b1ddd03 | |||
8ae74705ba | |||
99f5cb5b86 | |||
e89636fa58 | |||
7cd0e6154b | |||
62080f3248 | |||
2007b1bb8c | |||
5beeade430 | |||
2e29b46f0f | |||
90b1f47dbb | |||
c73c9b4605 | |||
48969a8fcc | |||
72b61fa765 | |||
18c2cdf5ae | |||
72af88406c | |||
0a8cf54220 | |||
6f3b97da6c | |||
22dc0b8eea | |||
d61e0f85dd | |||
072858a4f5 | |||
6999f7d2c8 | |||
ab68770e1a | |||
c24cafcaf1 | |||
947a507af9 | |||
95eb39803d | |||
9b55593d8c | |||
a74d2e41a9 | |||
bd15060fb0 | |||
69ceae5b66 | |||
9e8b35d26d | |||
37b8dfffd1 | |||
a3ddffbc5d | |||
c0e84207ed | |||
79d183750c | |||
35b1a829ff | |||
39a67b9786 | |||
d0951e5631 | |||
13fbde1315 | |||
ecd4e03081 | |||
9b2b4c6aa8 | |||
0722b59d87 | |||
6ace967b60 | |||
ddbeb88929 | |||
227e914b7b | |||
3648c69ce4 | |||
ca63d4b0eb | |||
8032e23cce | |||
514fd70e0c | |||
26c481e1a4 | |||
7a1e57f50c | |||
af9197e6b5 | |||
ecd9415662 | |||
cbfdacb596 | |||
ad2ccf92a1 | |||
e520364785 | |||
5de3939b9b | |||
a3dfb09942 | |||
6da21b0cbe | |||
f7473564b9 | |||
6e3f310214 | |||
7c5f30ff50 | |||
371424b3ce | |||
5ba5645201 | |||
8b3444e647 | |||
66473203ba | |||
5fe9fffdee | |||
2364aaa754 | |||
de877d9cbb | |||
f742ea5485 | |||
bae3a16e30 | |||
1355d4dd75 | |||
b5b4795f4c | |||
d5dc41ccf5 | |||
d2dc18fd6a | |||
a0770054ca | |||
1d8e1bc60d | |||
89ac0e19dd | |||
9d972355fd | |||
7cee839119 | |||
d2aa6e84d2 | |||
31fa5e40c8 | |||
f919a6a4b1 | |||
019b2cf4db | |||
64c352064e | |||
c50f7f7ccc | |||
c8f64a50b0 |
1
.gitbook.yaml
Normal file
@ -0,0 +1 @@
|
||||
root: ./docs/
|
12
.github/workflows/autoupdate.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
name: autoupdate
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
jobs:
|
||||
autoupdate:
|
||||
name: autoupdate
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: docker://chinthakagodawita/autoupdate-action:v1
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
10
.github/workflows/pr_checks.yml
vendored
@ -4,9 +4,9 @@ jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '17'
|
||||
@ -18,9 +18,9 @@ jobs:
|
||||
unit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '17'
|
||||
@ -28,4 +28,4 @@ jobs:
|
||||
uses: burrunan/gradle-cache-action@v1
|
||||
with:
|
||||
gradle-version: wrapper
|
||||
arguments: test koverCollectReports
|
||||
arguments: test koverMergedReport
|
||||
|
4
.github/workflows/publish.yml
vendored
@ -11,8 +11,8 @@ jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '17'
|
||||
|
31
.github/workflows/release.yml
vendored
@ -11,12 +11,12 @@ jobs:
|
||||
publish-to-nexus:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '17'
|
||||
- name: Publlish to Maven Central
|
||||
- name: Publish to Maven Central
|
||||
uses: burrunan/gradle-cache-action@v1
|
||||
with:
|
||||
gradle-version: wrapper
|
||||
@ -26,28 +26,3 @@ jobs:
|
||||
env:
|
||||
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USER }}
|
||||
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
|
||||
build-documentation:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- publish-to-nexus
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
|
||||
- uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: '17'
|
||||
- name: Build New Documentation
|
||||
uses: burrunan/gradle-cache-action@v1
|
||||
with:
|
||||
gradle-version: wrapper
|
||||
arguments: dokkaHtmlMultiModule
|
||||
properties: |
|
||||
release=true
|
||||
- name: Push New Documentation
|
||||
uses: EndBug/add-and-commit@v8
|
||||
with:
|
||||
default_author: github_actions
|
||||
new_branch: main
|
||||
message: 'doc: Added Latest Documentation ✨'
|
||||
|
145
CHANGELOG.md
@ -12,35 +12,176 @@
|
||||
|
||||
## Released
|
||||
|
||||
## [2.1.0] - February 18th, 2022
|
||||
## [3.4.0] - October 26th, 2022
|
||||
|
||||
### Added
|
||||
- Ability to override serializer via custom route
|
||||
|
||||
- Support for custom docs path
|
||||
|
||||
## [3.3.1] - September 26th, 2022
|
||||
|
||||
### Added
|
||||
|
||||
- Better exception thrown when unidentified type is encountered
|
||||
|
||||
## [3.3.0] - September 15th, 2022
|
||||
|
||||
### Added
|
||||
- Support for @Transient annotation
|
||||
- Support for @SerialName annotation on fields
|
||||
- Supports for un-backed fields, by excluding them from the generated schema.
|
||||
|
||||
### Changed
|
||||
- Actually turned on detekt formatting 🤦
|
||||
- Removed some rouge print statements
|
||||
|
||||
## Released
|
||||
|
||||
## [3.2.0] - August 23rd, 2022
|
||||
|
||||
### Added
|
||||
|
||||
- `SchemaConfigurator` to allow for advanced json schema configuration such as field level overrides and transient
|
||||
omission
|
||||
|
||||
## [3.1.0] - August 18th, 2022
|
||||
|
||||
### Added
|
||||
|
||||
- Ability to automatically detect authentication via route
|
||||
|
||||
### Fixed
|
||||
|
||||
- Improved stack trace output
|
||||
|
||||
## [3.0.0] - August 16th, 2022
|
||||
|
||||
### Added
|
||||
|
||||
- Ktor 2 Support 🎉
|
||||
- OpenAPI 3.1 Standard
|
||||
- JsonSchema Generator
|
||||
- `NotarizedRoute` plugin
|
||||
|
||||
### Removed
|
||||
|
||||
- SwaggerUI module removed (due to lack of OpenAPI 3.1 support)
|
||||
- Kompendium Annotations removed (field renames, undeclared fields, etc. will be follow-up work)
|
||||
|
||||
## [2.3.5] - June 7th, 2022
|
||||
|
||||
### Added
|
||||
|
||||
### Changed
|
||||
|
||||
- Fix serialization for api key location in api key auth configuration
|
||||
|
||||
### Remove
|
||||
|
||||
## [2.3.4] - April 7th, 2022
|
||||
|
||||
### Changed
|
||||
|
||||
- Put request body info now nullable
|
||||
|
||||
## [2.3.3] - April 1st, 2022
|
||||
|
||||
### Added
|
||||
|
||||
- Added tests for Swagger UI module that verify that plugin generates correct responses for Swagger UI WEB resources (
|
||||
tests should detect future incompatible changes in new versions of `org.webjars.swagger-ui`)
|
||||
|
||||
### Changed
|
||||
|
||||
- Fixed broken Swagger UI plugin (`org.webjars.swagger-ui` WEB resources structure changed in version 4.9.X).
|
||||
Issue: https://github.com/bkbnio/kompendium/issues/236
|
||||
|
||||
## [2.3.2] - March 30th, 2022
|
||||
|
||||
### Changed
|
||||
|
||||
- Fixed bug where nullable enum fields caused runtime exceptions
|
||||
|
||||
## [2.3.1] - March 5th, 2022
|
||||
|
||||
### Changed
|
||||
|
||||
- Can now apply `@FreeFormObject` to top level types
|
||||
|
||||
## [2.3.0] - March 1st, 2022
|
||||
|
||||
### Added
|
||||
|
||||
- Brand new SwaggerUI support as a KTor plugin with WebJar under the hood and flexible configuration
|
||||
|
||||
### Changed
|
||||
|
||||
- Playground example `SwaggerPlaygound` now demonstrates new SwaggerUI KTor plugin usage (including OAuth security)
|
||||
|
||||
### Remove
|
||||
|
||||
- Deprecated Swagger Webjar approach was removed from codebase
|
||||
|
||||
## [2.2.1] - February 26th, 2022
|
||||
|
||||
- Fix to support sealed class typed Maps
|
||||
|
||||
## [2.2.0] - February 25th, 2022
|
||||
|
||||
### Changed
|
||||
|
||||
- Fixed support Location classes located in other non-location classes
|
||||
- Fixed formatting of a custom `SimpleSchema`
|
||||
- Multipart form-data multiple file request support
|
||||
|
||||
## [2.1.1] - February 19th, 2022
|
||||
|
||||
### Changed
|
||||
|
||||
- Fixed sealed typed collections schema generation
|
||||
- Nullability no longer breaks object schema comparison
|
||||
|
||||
## [2.1.0] - February 18th, 2022
|
||||
|
||||
### Added
|
||||
|
||||
- Ability to override serializer via custom route
|
||||
|
||||
### Changed
|
||||
|
||||
- All complex types are now represented by reference schemas
|
||||
- Deprecated `@Referenced` since all complex types now create references
|
||||
|
||||
## [2.0.4] - February 10th, 2022
|
||||
|
||||
### Added
|
||||
|
||||
- Custom Type example to playground
|
||||
|
||||
### Changed
|
||||
|
||||
- Cleaned up and broke out handlers into separate classes
|
||||
- Serializer cleanup
|
||||
- Tests now run against Jackson, Gson and kotlinx on every run
|
||||
- Swagger UI bumped from v3 to v4
|
||||
|
||||
## [2.0.3] - February 7th, 2022
|
||||
|
||||
### Changed
|
||||
|
||||
- Fixed swagger documentation bug
|
||||
- Deprecated Swagger Webjar approach
|
||||
|
||||
## [2.0.2] - February 4th, 2022
|
||||
|
||||
### Added
|
||||
|
||||
- `@Referenced` annotation enabling support for recursive models
|
||||
|
||||
## [2.0.1] - January 23rd, 2022
|
||||
|
||||
### Change
|
||||
|
||||
- Fix bug in documentation publishing pipeline
|
||||
|
||||
## [2.0.0] - January 23rd, 2022
|
||||
|
@ -20,9 +20,7 @@ To get an overview of the project, read the [README](README.md). Here are some r
|
||||
|
||||
## Getting started
|
||||
|
||||
The best way to get started with Kompendium is to read the [docs](https://bkbnio.github.io/kompendium). Kompendium generates
|
||||
our documentation using [Dokka](https://github.com/Kotlin/dokka). This means that the docs live side-by-side with the source
|
||||
code itself, and leverage the KDoc format to provide syntax highlighting, dynamic linking and more!
|
||||
The best way to get started with Kompendium is to read the [docs](https://bkbn.gitbook.io/kompendium).
|
||||
|
||||
If live examples are more your thing, inside the `kompendium-playground` module, you will find a collection of starter
|
||||
examples ranging from simple CRUD and authentication examples, to more advanced topics like polymorphic serialization
|
||||
|
41
Project.md
@ -1,41 +0,0 @@
|
||||
# Kompendium
|
||||
|
||||
Welcome to Kompendium, the straight-forward, minimally-invasive OpenAPI generator for Ktor.
|
||||
|
||||
## How to install
|
||||
|
||||
Kompendium publishes all releases to Maven Central. As such, using the release versions of `Kompendium` is as simple as
|
||||
declaring it as an implementation dependency in your `build.gradle.kts`
|
||||
|
||||
```kotlin
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("io.bkbn:kompendium-core:latest.release")
|
||||
}
|
||||
```
|
||||
|
||||
In addition to publishing releases to Maven Central, a snapshot version gets published to GitHub Packages on every merge
|
||||
to `main`. These can be consumed by adding the repository to your gradle build file. Instructions can be
|
||||
found [here](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-gradle-registry#using-a-published-package)
|
||||
|
||||
## Setting up the Kompendium Plugin
|
||||
|
||||
Kompendium is instantiated as a Ktor Feature/Plugin. It can be added to your API as follows
|
||||
|
||||
```kotlin
|
||||
private fun Application.mainModule() {
|
||||
// Installs the Kompendium Plugin and sets up baseline server metadata
|
||||
install(Kompendium) {
|
||||
spec = OpenApiSpec(/*..*/)
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## Notarization
|
||||
|
||||
The concept of notarizing routes / exceptions / etc. is central to Kompendium. More details on _how_ to notarize your
|
||||
API can be found in the kompendium-core module.
|
50
README.md
@ -2,52 +2,4 @@
|
||||
|
||||
[](https://search.maven.org/search?q=io.bkbn%20kompendium)
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [What Is Kompendium](#what-is-kompendium)
|
||||
- [How to Install](#how-to-install)
|
||||
- [Library Details](#library-details)
|
||||
- [Local Development](#local-development)
|
||||
- [The Playground](#the-playground)
|
||||
|
||||
## What is Kompendium
|
||||
|
||||
Kompendium is intended to be a minimally invasive OpenApi Specification generator for Ktor. Minimally invasive meaning
|
||||
that users will use only Ktor native functions when implementing their API, and will supplement with Kompendium code in
|
||||
order to generate the appropriate spec.
|
||||
|
||||
## How to install
|
||||
|
||||
Kompendium publishes all releases to Maven Central. As such, using the release versions of `Kompendium` is as simple as
|
||||
declaring it as an implementation dependency in your `build.gradle.kts`
|
||||
|
||||
```kotlin
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("io.bkbn:kompendium-core:latest.release")
|
||||
}
|
||||
```
|
||||
|
||||
In addition to publishing releases to Maven Central, a snapshot version gets published to GitHub Packages on every merge
|
||||
to `main`. These can be consumed by adding the repository to your gradle build file. Instructions can be
|
||||
found [here](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-gradle-registry#using-a-published-package)
|
||||
|
||||
# Library Details
|
||||
|
||||
Library documentation lives alongside the source code, and is generated into a static site via Dokka. Can be viewed [here](https://bkbnio.github.io/kompendium)
|
||||
|
||||
## Local Development
|
||||
|
||||
Kompendium should run locally right out of the box, no configuration necessary (assuming you have JDK 11+ installed).
|
||||
New features can be built locally and published to your local maven repository with the `./gradlew publishToMavenLocal`
|
||||
command!
|
||||
|
||||
## The Playground
|
||||
|
||||
This repo contains a `playground` module that contains a number of working examples showcasing the capabilities of
|
||||
Kompendium.
|
||||
|
||||
Feel free to check it out, or even create your own example!
|
||||
Documentation is stored in the `docs` folder and is hosted [here](https://bkbn.gitbook.io/kompendium)
|
||||
|
@ -1,12 +1,11 @@
|
||||
plugins {
|
||||
kotlin("jvm") version "1.6.10" apply false
|
||||
kotlin("plugin.serialization") version "1.6.10" apply false
|
||||
id("io.bkbn.sourdough.library.jvm") version "0.6.0" apply false
|
||||
id("io.bkbn.sourdough.application.jvm") version "0.6.0" apply false
|
||||
id("io.bkbn.sourdough.root") version "0.6.0"
|
||||
kotlin("jvm") version "1.7.20" apply false
|
||||
kotlin("plugin.serialization") version "1.7.20" apply false
|
||||
id("io.bkbn.sourdough.library.jvm") version "0.12.0" apply false
|
||||
id("io.bkbn.sourdough.application.jvm") version "0.12.0" apply false
|
||||
id("io.bkbn.sourdough.root") version "0.12.0"
|
||||
id("com.github.jakemarsden.git-hooks") version "0.0.2"
|
||||
id("org.jetbrains.dokka") version "1.6.10"
|
||||
id("org.jetbrains.kotlinx.kover") version "0.5.0"
|
||||
id("org.jetbrains.kotlinx.kover") version "0.6.1"
|
||||
id("io.github.gradle-nexus.publish-plugin") version "1.1.0"
|
||||
}
|
||||
|
||||
|
72
core/build.gradle.kts
Normal file
@ -0,0 +1,72 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
kotlin("plugin.serialization")
|
||||
id("io.bkbn.sourdough.library.jvm")
|
||||
id("io.gitlab.arturbosch.detekt")
|
||||
id("com.adarshr.test-logger")
|
||||
id("maven-publish")
|
||||
id("java-library")
|
||||
id("signing")
|
||||
id("java-test-fixtures")
|
||||
id("org.jetbrains.kotlinx.kover")
|
||||
}
|
||||
|
||||
sourdoughLibrary {
|
||||
libraryName.set("Kompendium Core")
|
||||
libraryDescription.set("Core functionality for the Kompendium library")
|
||||
compilerArgs.set(listOf("-opt-in=kotlin.RequiresOptIn"))
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// VERSIONS
|
||||
val kotestVersion: String by project
|
||||
val ktorVersion: String by project
|
||||
val detektVersion: String by project
|
||||
|
||||
// IMPLEMENTATION
|
||||
|
||||
api(projects.kompendiumOas)
|
||||
api(projects.kompendiumJsonSchema)
|
||||
|
||||
implementation("io.ktor:ktor-server-core:$ktorVersion")
|
||||
implementation("io.ktor:ktor-server-cio:$ktorVersion")
|
||||
implementation("io.ktor:ktor-server-html-builder:$ktorVersion")
|
||||
implementation("io.ktor:ktor-server-content-negotiation:$ktorVersion")
|
||||
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
|
||||
implementation("ch.qos.logback:logback-classic:1.4.4")
|
||||
|
||||
// Formatting
|
||||
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:$detektVersion")
|
||||
|
||||
// TEST FIXTURES
|
||||
|
||||
testFixturesApi("io.kotest:kotest-runner-junit5-jvm:$kotestVersion")
|
||||
testFixturesApi("io.kotest:kotest-assertions-core-jvm:$kotestVersion")
|
||||
testFixturesApi("io.kotest:kotest-property-jvm:$kotestVersion")
|
||||
testFixturesApi("io.kotest:kotest-assertions-json-jvm:$kotestVersion")
|
||||
testFixturesApi("io.kotest:kotest-assertions-ktor-jvm:4.4.3")
|
||||
|
||||
testFixturesApi("io.ktor:ktor-server-core:$ktorVersion")
|
||||
testFixturesApi("io.ktor:ktor-server-test-host:$ktorVersion")
|
||||
testFixturesApi("io.ktor:ktor-serialization:$ktorVersion")
|
||||
testFixturesApi("io.ktor:ktor-serialization-jackson:$ktorVersion")
|
||||
testFixturesApi("io.ktor:ktor-serialization-gson:$ktorVersion")
|
||||
testFixturesApi("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
|
||||
testFixturesApi("io.ktor:ktor-server-content-negotiation:$ktorVersion")
|
||||
testFixturesApi("io.ktor:ktor-server-auth:$ktorVersion")
|
||||
testFixturesApi("io.ktor:ktor-server-auth-jwt:$ktorVersion")
|
||||
testFixturesApi("io.ktor:ktor-client:$ktorVersion")
|
||||
testFixturesApi("io.ktor:ktor-client-cio:$ktorVersion")
|
||||
|
||||
testFixturesApi("dev.forst:ktor-api-key:2.1.2")
|
||||
|
||||
testFixturesApi("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1")
|
||||
}
|
||||
|
||||
testing {
|
||||
suites {
|
||||
named("test", JvmTestSuite::class) {
|
||||
useJUnitJupiter()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package io.bkbn.kompendium.core.attribute
|
||||
|
||||
import io.bkbn.kompendium.json.schema.SchemaConfigurator
|
||||
import io.bkbn.kompendium.oas.OpenApiSpec
|
||||
import io.ktor.util.AttributeKey
|
||||
|
||||
object KompendiumAttributes {
|
||||
val openApiSpec = AttributeKey<OpenApiSpec>("OpenApiSpec")
|
||||
val schemaConfigurator = AttributeKey<SchemaConfigurator>("SchemaConfigurator")
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package io.bkbn.kompendium.core.metadata
|
||||
|
||||
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||
import io.bkbn.kompendium.oas.payload.Parameter
|
||||
|
||||
class DeleteInfo private constructor(
|
||||
override val response: ResponseInfo,
|
||||
override val errors: MutableList<ResponseInfo>,
|
||||
override val tags: Set<String>,
|
||||
override val summary: String,
|
||||
override val description: String,
|
||||
override val externalDocumentation: ExternalDocumentation?,
|
||||
override val operationId: String?,
|
||||
override val deprecated: Boolean,
|
||||
override val parameters: List<Parameter>
|
||||
) : MethodInfo {
|
||||
|
||||
companion object {
|
||||
fun builder(init: Builder.() -> Unit): DeleteInfo {
|
||||
val builder = Builder()
|
||||
builder.init()
|
||||
return builder.build()
|
||||
}
|
||||
}
|
||||
|
||||
class Builder : MethodInfo.Builder<DeleteInfo>() {
|
||||
override fun build() = DeleteInfo(
|
||||
response = response ?: error("Response info must be present"),
|
||||
errors = errors,
|
||||
tags = tags,
|
||||
summary = summary ?: error("Summary must be present"),
|
||||
description = description ?: error("Description must be present"),
|
||||
externalDocumentation = externalDocumentation,
|
||||
operationId = operationId,
|
||||
deprecated = deprecated,
|
||||
parameters = parameters
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package io.bkbn.kompendium.core.metadata
|
||||
|
||||
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||
import io.bkbn.kompendium.oas.payload.Parameter
|
||||
|
||||
class GetInfo private constructor(
|
||||
override val response: ResponseInfo,
|
||||
override val errors: MutableList<ResponseInfo>,
|
||||
override val tags: Set<String>,
|
||||
override val summary: String,
|
||||
override val description: String,
|
||||
override val externalDocumentation: ExternalDocumentation?,
|
||||
override val operationId: String?,
|
||||
override val deprecated: Boolean,
|
||||
override val parameters: List<Parameter>
|
||||
) : MethodInfo {
|
||||
|
||||
companion object {
|
||||
fun builder(init: Builder.() -> Unit): GetInfo {
|
||||
val builder = Builder()
|
||||
builder.init()
|
||||
return builder.build()
|
||||
}
|
||||
}
|
||||
|
||||
class Builder : MethodInfo.Builder<GetInfo>() {
|
||||
override fun build() = GetInfo(
|
||||
response = response ?: error("You must provide a response in order to notarize a GET"),
|
||||
errors = errors,
|
||||
tags = tags,
|
||||
summary = summary ?: error("You must provide a summary in order to notarize a GET"),
|
||||
description = description ?: error("You must provide a description in order to notarize a GET"),
|
||||
externalDocumentation = externalDocumentation,
|
||||
operationId = operationId,
|
||||
deprecated = deprecated,
|
||||
parameters = parameters
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package io.bkbn.kompendium.core.metadata
|
||||
|
||||
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||
import io.bkbn.kompendium.oas.payload.Parameter
|
||||
|
||||
class HeadInfo private constructor(
|
||||
override val response: ResponseInfo,
|
||||
override val errors: MutableList<ResponseInfo>,
|
||||
override val tags: Set<String>,
|
||||
override val summary: String,
|
||||
override val description: String,
|
||||
override val externalDocumentation: ExternalDocumentation?,
|
||||
override val operationId: String?,
|
||||
override val deprecated: Boolean,
|
||||
override val parameters: List<Parameter>
|
||||
) : MethodInfo {
|
||||
|
||||
companion object {
|
||||
fun builder(init: Builder.() -> Unit): HeadInfo {
|
||||
val builder = Builder()
|
||||
builder.init()
|
||||
return builder.build()
|
||||
}
|
||||
}
|
||||
|
||||
class Builder : MethodInfo.Builder<HeadInfo>() {
|
||||
override fun build() = HeadInfo(
|
||||
response = response ?: error("Response info must be present"),
|
||||
errors = errors,
|
||||
tags = tags,
|
||||
summary = summary ?: error("Summary must be present"),
|
||||
description = description ?: error("Description must be present"),
|
||||
externalDocumentation = externalDocumentation,
|
||||
operationId = operationId,
|
||||
deprecated = deprecated,
|
||||
parameters = parameters
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package io.bkbn.kompendium.core.metadata
|
||||
|
||||
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||
import io.bkbn.kompendium.oas.payload.Parameter
|
||||
|
||||
sealed interface MethodInfo {
|
||||
val response: ResponseInfo
|
||||
val errors: List<ResponseInfo>
|
||||
val tags: Set<String>
|
||||
val summary: String
|
||||
val description: String
|
||||
val externalDocumentation: ExternalDocumentation?
|
||||
get() = null
|
||||
val operationId: String?
|
||||
get() = null
|
||||
val deprecated: Boolean
|
||||
get() = false
|
||||
val parameters: List<Parameter>
|
||||
get() = emptyList()
|
||||
|
||||
abstract class Builder<T : MethodInfo> {
|
||||
internal var response: ResponseInfo? = null
|
||||
internal var summary: String? = null
|
||||
internal var description: String? = null
|
||||
internal var externalDocumentation: ExternalDocumentation? = null
|
||||
internal var operationId: String? = null
|
||||
internal var deprecated: Boolean = false
|
||||
internal var tags: Set<String> = emptySet()
|
||||
internal var parameters: List<Parameter> = emptyList()
|
||||
internal var errors: MutableList<ResponseInfo> = mutableListOf()
|
||||
|
||||
fun response(init: ResponseInfo.Builder.() -> Unit) = apply {
|
||||
val builder = ResponseInfo.Builder()
|
||||
builder.init()
|
||||
this.response = builder.build()
|
||||
}
|
||||
|
||||
fun canRespond(init: ResponseInfo.Builder.() -> Unit) = apply {
|
||||
val builder = ResponseInfo.Builder()
|
||||
builder.init()
|
||||
errors.add(builder.build())
|
||||
}
|
||||
|
||||
fun canRespond(responses: List<ResponseInfo>) = apply {
|
||||
errors.addAll(responses)
|
||||
}
|
||||
|
||||
fun summary(s: String) = apply { this.summary = s }
|
||||
|
||||
fun description(s: String) = apply { this.description = s }
|
||||
|
||||
fun externalDocumentation(docs: ExternalDocumentation) = apply { this.externalDocumentation = docs }
|
||||
|
||||
fun operationId(id: String) = apply { this.operationId = id }
|
||||
|
||||
fun isDeprecated() = apply { this.deprecated = true }
|
||||
|
||||
fun tags(vararg tags: String) = apply { this.tags = tags.toSet() }
|
||||
|
||||
fun parameters(vararg parameters: Parameter) = apply { this.parameters = parameters.toList() }
|
||||
|
||||
abstract fun build(): T
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package io.bkbn.kompendium.core.metadata
|
||||
|
||||
sealed interface MethodInfoWithRequest : MethodInfo {
|
||||
val request: RequestInfo
|
||||
|
||||
abstract class Builder<T : MethodInfoWithRequest> : MethodInfo.Builder<T>() {
|
||||
internal var request: RequestInfo? = null
|
||||
|
||||
fun request(init: RequestInfo.Builder.() -> Unit) = apply {
|
||||
val builder = RequestInfo.Builder()
|
||||
builder.init()
|
||||
this.request = builder.build()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package io.bkbn.kompendium.core.metadata
|
||||
|
||||
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||
import io.bkbn.kompendium.oas.payload.Parameter
|
||||
|
||||
class OptionsInfo private constructor(
|
||||
override val response: ResponseInfo,
|
||||
override val errors: MutableList<ResponseInfo>,
|
||||
override val tags: Set<String>,
|
||||
override val summary: String,
|
||||
override val description: String,
|
||||
override val externalDocumentation: ExternalDocumentation?,
|
||||
override val operationId: String?,
|
||||
override val deprecated: Boolean,
|
||||
override val parameters: List<Parameter>
|
||||
) : MethodInfo {
|
||||
|
||||
companion object {
|
||||
fun builder(init: Builder.() -> Unit): OptionsInfo {
|
||||
val builder = Builder()
|
||||
builder.init()
|
||||
return builder.build()
|
||||
}
|
||||
}
|
||||
|
||||
class Builder : MethodInfo.Builder<OptionsInfo>() {
|
||||
override fun build() = OptionsInfo(
|
||||
response = response ?: error("Response info must be provided!"),
|
||||
errors = errors,
|
||||
tags = tags,
|
||||
summary = summary ?: error("Summary must be provided!"),
|
||||
description = description ?: error("Description must be provided!"),
|
||||
externalDocumentation = externalDocumentation,
|
||||
operationId = operationId,
|
||||
deprecated = deprecated,
|
||||
parameters = parameters
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package io.bkbn.kompendium.core.metadata
|
||||
|
||||
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||
import io.bkbn.kompendium.oas.payload.Parameter
|
||||
|
||||
class PatchInfo private constructor(
|
||||
override val request: RequestInfo,
|
||||
override val errors: MutableList<ResponseInfo>,
|
||||
override val response: ResponseInfo,
|
||||
override val tags: Set<String>,
|
||||
override val summary: String,
|
||||
override val description: String,
|
||||
override val externalDocumentation: ExternalDocumentation?,
|
||||
override val operationId: String?,
|
||||
override val deprecated: Boolean,
|
||||
override val parameters: List<Parameter>
|
||||
) : MethodInfoWithRequest {
|
||||
|
||||
companion object {
|
||||
fun builder(init: Builder.() -> Unit): PatchInfo {
|
||||
val builder = Builder()
|
||||
builder.init()
|
||||
return builder.build()
|
||||
}
|
||||
}
|
||||
|
||||
class Builder : MethodInfoWithRequest.Builder<PatchInfo>() {
|
||||
override fun build() = PatchInfo(
|
||||
request = request ?: error("request info must be present"),
|
||||
errors = errors,
|
||||
response = response ?: error("response info must be present"),
|
||||
tags = tags,
|
||||
summary = summary ?: error("Summary must be present"),
|
||||
description = description ?: error("Description must be present"),
|
||||
externalDocumentation = externalDocumentation,
|
||||
operationId = operationId,
|
||||
deprecated = deprecated,
|
||||
parameters = parameters
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package io.bkbn.kompendium.core.metadata
|
||||
|
||||
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||
import io.bkbn.kompendium.oas.payload.Parameter
|
||||
|
||||
class PostInfo private constructor(
|
||||
override val request: RequestInfo,
|
||||
override val errors: MutableList<ResponseInfo>,
|
||||
override val response: ResponseInfo,
|
||||
override val tags: Set<String>,
|
||||
override val summary: String,
|
||||
override val description: String,
|
||||
override val externalDocumentation: ExternalDocumentation?,
|
||||
override val operationId: String?,
|
||||
override val deprecated: Boolean,
|
||||
override val parameters: List<Parameter>
|
||||
) : MethodInfoWithRequest {
|
||||
|
||||
companion object {
|
||||
fun builder(init: Builder.() -> Unit): PostInfo {
|
||||
val builder = Builder()
|
||||
builder.init()
|
||||
return builder.build()
|
||||
}
|
||||
}
|
||||
|
||||
class Builder : MethodInfoWithRequest.Builder<PostInfo>() {
|
||||
override fun build() = PostInfo(
|
||||
request = request ?: error("request info must be present"),
|
||||
errors = errors,
|
||||
response = response ?: error("response info must be present"),
|
||||
tags = tags,
|
||||
summary = summary ?: error("Summary must be present"),
|
||||
description = description ?: error("Description must be present"),
|
||||
externalDocumentation = externalDocumentation,
|
||||
operationId = operationId,
|
||||
deprecated = deprecated,
|
||||
parameters = parameters
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package io.bkbn.kompendium.core.metadata
|
||||
|
||||
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||
import io.bkbn.kompendium.oas.payload.Parameter
|
||||
|
||||
class PutInfo private constructor(
|
||||
override val request: RequestInfo,
|
||||
override val errors: MutableList<ResponseInfo>,
|
||||
override val response: ResponseInfo,
|
||||
override val tags: Set<String>,
|
||||
override val summary: String,
|
||||
override val description: String,
|
||||
override val externalDocumentation: ExternalDocumentation?,
|
||||
override val operationId: String?,
|
||||
override val deprecated: Boolean,
|
||||
override val parameters: List<Parameter>
|
||||
) : MethodInfoWithRequest {
|
||||
|
||||
companion object {
|
||||
fun builder(init: Builder.() -> Unit): PutInfo {
|
||||
val builder = Builder()
|
||||
builder.init()
|
||||
return builder.build()
|
||||
}
|
||||
}
|
||||
|
||||
class Builder : MethodInfoWithRequest.Builder<PutInfo>() {
|
||||
override fun build() = PutInfo(
|
||||
request = request ?: error("request info must be present"),
|
||||
errors = errors,
|
||||
response = response ?: error("response info must be present"),
|
||||
tags = tags,
|
||||
summary = summary ?: error("Summary must be present"),
|
||||
description = description ?: error("Description must be present"),
|
||||
externalDocumentation = externalDocumentation,
|
||||
operationId = operationId,
|
||||
deprecated = deprecated,
|
||||
parameters = parameters
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package io.bkbn.kompendium.core.metadata
|
||||
|
||||
import io.bkbn.kompendium.oas.payload.MediaType
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
class RequestInfo private constructor(
|
||||
val requestType: KType,
|
||||
val description: String,
|
||||
val examples: Map<String, MediaType.Example>?
|
||||
) {
|
||||
|
||||
companion object {
|
||||
fun builder(init: Builder.() -> Unit): RequestInfo {
|
||||
val builder = Builder()
|
||||
builder.init()
|
||||
return builder.build()
|
||||
}
|
||||
}
|
||||
|
||||
class Builder {
|
||||
private var requestType: KType? = null
|
||||
private var description: String? = null
|
||||
private var examples: Map<String, MediaType.Example>? = null
|
||||
|
||||
fun requestType(t: KType) = apply {
|
||||
this.requestType = t
|
||||
}
|
||||
|
||||
inline fun <reified T> requestType() = apply { requestType(typeOf<T>()) }
|
||||
|
||||
fun description(s: String) = apply { this.description = s }
|
||||
|
||||
fun examples(vararg e: Pair<String, Any>) = apply {
|
||||
this.examples = e.toMap().mapValues { (_, v) -> MediaType.Example(v) }
|
||||
}
|
||||
|
||||
fun build() = RequestInfo(
|
||||
requestType = requestType ?: error("Request type must be present"),
|
||||
description = description ?: error("Description must be present"),
|
||||
examples = examples
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package io.bkbn.kompendium.core.metadata
|
||||
|
||||
import io.bkbn.kompendium.oas.payload.MediaType
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
class ResponseInfo private constructor(
|
||||
val responseCode: HttpStatusCode,
|
||||
val responseType: KType,
|
||||
val description: String,
|
||||
val examples: Map<String, MediaType.Example>?
|
||||
) {
|
||||
|
||||
companion object {
|
||||
fun builder(init: Builder.() -> Unit): ResponseInfo {
|
||||
val builder = Builder()
|
||||
builder.init()
|
||||
return builder.build()
|
||||
}
|
||||
}
|
||||
|
||||
class Builder {
|
||||
private var responseCode: HttpStatusCode? = null
|
||||
private var responseType: KType? = null
|
||||
private var description: String? = null
|
||||
private var examples: Map<String, MediaType.Example>? = null
|
||||
|
||||
fun responseCode(code: HttpStatusCode) = apply {
|
||||
this.responseCode = code
|
||||
}
|
||||
|
||||
fun responseType(t: KType) = apply {
|
||||
this.responseType = t
|
||||
}
|
||||
|
||||
inline fun <reified T> responseType() = apply { responseType(typeOf<T>()) }
|
||||
|
||||
fun description(s: String) = apply { this.description = s }
|
||||
|
||||
fun examples(vararg e: Pair<String, Any>) = apply {
|
||||
this.examples = e.toMap().mapValues { (_, v) -> MediaType.Example(v) }
|
||||
}
|
||||
|
||||
fun build() = ResponseInfo(
|
||||
responseCode = responseCode ?: error("You must provide a response code in order to build a Response!"),
|
||||
responseType = responseType ?: error("You must provide a response type in order to build a Response!"),
|
||||
description = description ?: error("You must provide a description in order to build a Response!"),
|
||||
examples = examples
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package io.bkbn.kompendium.core.plugin
|
||||
|
||||
import io.bkbn.kompendium.core.attribute.KompendiumAttributes
|
||||
import io.bkbn.kompendium.json.schema.SchemaConfigurator
|
||||
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||
import io.bkbn.kompendium.json.schema.util.Helpers.getSimpleSlug
|
||||
import io.bkbn.kompendium.oas.OpenApiSpec
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.server.application.call
|
||||
import io.ktor.server.application.createApplicationPlugin
|
||||
import io.ktor.server.response.respond
|
||||
import io.ktor.server.routing.Routing
|
||||
import io.ktor.server.routing.application
|
||||
import io.ktor.server.routing.get
|
||||
import io.ktor.server.routing.route
|
||||
import io.ktor.server.routing.routing
|
||||
import kotlin.reflect.KType
|
||||
|
||||
object NotarizedApplication {
|
||||
|
||||
class Config {
|
||||
lateinit var spec: OpenApiSpec
|
||||
var openApiJson: Routing.() -> Unit = {
|
||||
route("/openapi.json") {
|
||||
get {
|
||||
call.respond(HttpStatusCode.OK, this@route.application.attributes[KompendiumAttributes.openApiSpec])
|
||||
}
|
||||
}
|
||||
}
|
||||
var customTypes: Map<KType, JsonSchema> = emptyMap()
|
||||
var schemaConfigurator: SchemaConfigurator = SchemaConfigurator.Default()
|
||||
}
|
||||
|
||||
operator fun invoke() = createApplicationPlugin(
|
||||
name = "NotarizedApplication",
|
||||
createConfiguration = ::Config
|
||||
) {
|
||||
val spec = pluginConfig.spec
|
||||
val routing = application.routing { }
|
||||
pluginConfig.openApiJson(routing)
|
||||
pluginConfig.customTypes.forEach { (type, schema) ->
|
||||
spec.components.schemas[type.getSimpleSlug()] = schema
|
||||
}
|
||||
application.attributes.put(KompendiumAttributes.openApiSpec, spec)
|
||||
application.attributes.put(KompendiumAttributes.schemaConfigurator, pluginConfig.schemaConfigurator)
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
package io.bkbn.kompendium.core.plugin
|
||||
|
||||
import io.bkbn.kompendium.core.attribute.KompendiumAttributes
|
||||
import io.bkbn.kompendium.core.metadata.DeleteInfo
|
||||
import io.bkbn.kompendium.core.metadata.GetInfo
|
||||
import io.bkbn.kompendium.core.metadata.HeadInfo
|
||||
import io.bkbn.kompendium.core.metadata.OptionsInfo
|
||||
import io.bkbn.kompendium.core.metadata.PatchInfo
|
||||
import io.bkbn.kompendium.core.metadata.PostInfo
|
||||
import io.bkbn.kompendium.core.metadata.PutInfo
|
||||
import io.bkbn.kompendium.core.util.Helpers.addToSpec
|
||||
import io.bkbn.kompendium.core.util.SpecConfig
|
||||
import io.bkbn.kompendium.oas.path.Path
|
||||
import io.bkbn.kompendium.oas.path.PathOperation
|
||||
import io.bkbn.kompendium.oas.payload.Parameter
|
||||
import io.ktor.server.application.ApplicationCallPipeline
|
||||
import io.ktor.server.application.Hook
|
||||
import io.ktor.server.application.createRouteScopedPlugin
|
||||
import io.ktor.server.routing.Route
|
||||
|
||||
object NotarizedRoute {
|
||||
|
||||
class Config : SpecConfig {
|
||||
override var tags: Set<String> = emptySet()
|
||||
override var parameters: List<Parameter> = emptyList()
|
||||
override var get: GetInfo? = null
|
||||
override var post: PostInfo? = null
|
||||
override var put: PutInfo? = null
|
||||
override var delete: DeleteInfo? = null
|
||||
override var patch: PatchInfo? = null
|
||||
override var head: HeadInfo? = null
|
||||
override var options: OptionsInfo? = null
|
||||
override var security: Map<String, List<String>>? = null
|
||||
internal var path: Path? = null
|
||||
}
|
||||
|
||||
private object InstallHook : Hook<(ApplicationCallPipeline) -> Unit> {
|
||||
override fun install(pipeline: ApplicationCallPipeline, handler: (ApplicationCallPipeline) -> Unit) {
|
||||
handler(pipeline)
|
||||
}
|
||||
}
|
||||
|
||||
operator fun invoke() = createRouteScopedPlugin(
|
||||
name = "NotarizedRoute",
|
||||
createConfiguration = ::Config
|
||||
) {
|
||||
|
||||
// This is required in order to introspect the route path and authentication
|
||||
on(InstallHook) {
|
||||
val route = it as? Route ?: return@on
|
||||
val spec = application.attributes[KompendiumAttributes.openApiSpec]
|
||||
val routePath = route.calculateRoutePath()
|
||||
val authMethods = route.collectAuthMethods()
|
||||
pluginConfig.path?.addDefaultAuthMethods(authMethods)
|
||||
require(spec.paths[routePath] == null) {
|
||||
"""
|
||||
The specified path ${Parameter.Location.path} has already been documented!
|
||||
Please make sure that all notarized paths are unique
|
||||
""".trimIndent()
|
||||
}
|
||||
spec.paths[routePath] = pluginConfig.path
|
||||
?: error("This indicates a bug in Kompendium. Please file a GitHub issue!")
|
||||
}
|
||||
|
||||
val spec = application.attributes[KompendiumAttributes.openApiSpec]
|
||||
val serializableReader = application.attributes[KompendiumAttributes.schemaConfigurator]
|
||||
|
||||
val path = Path()
|
||||
path.parameters = pluginConfig.parameters
|
||||
|
||||
pluginConfig.get?.addToSpec(path, spec, pluginConfig, serializableReader)
|
||||
pluginConfig.delete?.addToSpec(path, spec, pluginConfig, serializableReader)
|
||||
pluginConfig.head?.addToSpec(path, spec, pluginConfig, serializableReader)
|
||||
pluginConfig.options?.addToSpec(path, spec, pluginConfig, serializableReader)
|
||||
pluginConfig.post?.addToSpec(path, spec, pluginConfig, serializableReader)
|
||||
pluginConfig.put?.addToSpec(path, spec, pluginConfig, serializableReader)
|
||||
pluginConfig.patch?.addToSpec(path, spec, pluginConfig, serializableReader)
|
||||
|
||||
pluginConfig.path = path
|
||||
}
|
||||
|
||||
private fun Route.calculateRoutePath() = toString().replace(Regex("/\\(.+\\)"), "")
|
||||
private fun Route.collectAuthMethods() = toString()
|
||||
.split("/")
|
||||
.filter { it.contains(Regex("\\(authenticate .*\\)")) }
|
||||
.map { it.replace("(authenticate ", "").replace(")", "") }
|
||||
.map { it.split(", ") }
|
||||
.flatten()
|
||||
|
||||
private fun Path.addDefaultAuthMethods(methods: List<String>) {
|
||||
get?.addDefaultAuthMethods(methods)
|
||||
put?.addDefaultAuthMethods(methods)
|
||||
post?.addDefaultAuthMethods(methods)
|
||||
delete?.addDefaultAuthMethods(methods)
|
||||
options?.addDefaultAuthMethods(methods)
|
||||
head?.addDefaultAuthMethods(methods)
|
||||
patch?.addDefaultAuthMethods(methods)
|
||||
trace?.addDefaultAuthMethods(methods)
|
||||
}
|
||||
|
||||
private fun PathOperation.addDefaultAuthMethods(methods: List<String>) {
|
||||
methods.forEach { m ->
|
||||
if (security == null || security?.all { s -> !s.containsKey(m) } == true) {
|
||||
if (security == null) {
|
||||
security = mutableListOf(mapOf(m to emptyList()))
|
||||
} else {
|
||||
security?.add(mapOf(m to emptyList()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
package io.bkbn.kompendium.core.routes
|
||||
|
||||
import io.ktor.application.call
|
||||
import io.ktor.html.respondHtml
|
||||
import io.ktor.routing.Routing
|
||||
import io.ktor.routing.get
|
||||
import io.ktor.routing.route
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.server.application.call
|
||||
import io.ktor.server.html.respondHtml
|
||||
import io.ktor.server.routing.Route
|
||||
import io.ktor.server.routing.get
|
||||
import io.ktor.server.routing.route
|
||||
import kotlinx.html.body
|
||||
import kotlinx.html.head
|
||||
import kotlinx.html.link
|
||||
@ -15,14 +16,15 @@ import kotlinx.html.title
|
||||
import kotlinx.html.unsafe
|
||||
|
||||
/**
|
||||
* Provides an out-of-the-box route to view docs using ReDoc
|
||||
* Provides an out-of-the-box route to view docs using ReDoc on the specified [path].
|
||||
* @param pageTitle Webpage title you wish to be displayed on your docs
|
||||
* @param route path to docs resource
|
||||
* @param specUrl url to point ReDoc to the OpenAPI json document
|
||||
*/
|
||||
fun Routing.redoc(pageTitle: String = "Docs", specUrl: String = "/openapi.json") {
|
||||
route("/docs") {
|
||||
fun Route.redoc(pageTitle: String = "Docs", path: String = "/docs", specUrl: String = "/openapi.json") {
|
||||
route(path) {
|
||||
get {
|
||||
call.respondHtml {
|
||||
call.respondHtml(HttpStatusCode.OK) {
|
||||
head {
|
||||
title {
|
||||
+pageTitle
|
||||
@ -45,7 +47,7 @@ fun Routing.redoc(pageTitle: String = "Docs", specUrl: String = "/openapi.json")
|
||||
}
|
||||
}
|
||||
body {
|
||||
unsafe { +"<redoc spec-url='${specUrl}'></redoc>" }
|
||||
unsafe { +"<redoc spec-url='$specUrl'></redoc>" }
|
||||
script {
|
||||
src = "https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"
|
||||
}
|
116
core/src/main/kotlin/io/bkbn/kompendium/core/util/Helpers.kt
Normal file
@ -0,0 +1,116 @@
|
||||
package io.bkbn.kompendium.core.util
|
||||
|
||||
import io.bkbn.kompendium.core.metadata.DeleteInfo
|
||||
import io.bkbn.kompendium.core.metadata.GetInfo
|
||||
import io.bkbn.kompendium.core.metadata.HeadInfo
|
||||
import io.bkbn.kompendium.core.metadata.MethodInfo
|
||||
import io.bkbn.kompendium.core.metadata.MethodInfoWithRequest
|
||||
import io.bkbn.kompendium.core.metadata.OptionsInfo
|
||||
import io.bkbn.kompendium.core.metadata.PatchInfo
|
||||
import io.bkbn.kompendium.core.metadata.PostInfo
|
||||
import io.bkbn.kompendium.core.metadata.PutInfo
|
||||
import io.bkbn.kompendium.core.metadata.ResponseInfo
|
||||
import io.bkbn.kompendium.json.schema.SchemaConfigurator
|
||||
import io.bkbn.kompendium.json.schema.SchemaGenerator
|
||||
import io.bkbn.kompendium.json.schema.definition.ReferenceDefinition
|
||||
import io.bkbn.kompendium.json.schema.util.Helpers.getReferenceSlug
|
||||
import io.bkbn.kompendium.json.schema.util.Helpers.getSimpleSlug
|
||||
import io.bkbn.kompendium.oas.OpenApiSpec
|
||||
import io.bkbn.kompendium.oas.path.Path
|
||||
import io.bkbn.kompendium.oas.path.PathOperation
|
||||
import io.bkbn.kompendium.oas.payload.MediaType
|
||||
import io.bkbn.kompendium.oas.payload.Request
|
||||
import io.bkbn.kompendium.oas.payload.Response
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
|
||||
object Helpers {
|
||||
|
||||
fun MethodInfo.addToSpec(path: Path, spec: OpenApiSpec, config: SpecConfig, schemaConfigurator: SchemaConfigurator) {
|
||||
SchemaGenerator.fromTypeOrUnit(
|
||||
this.response.responseType,
|
||||
spec.components.schemas, schemaConfigurator
|
||||
)?.let { schema ->
|
||||
spec.components.schemas[this.response.responseType.getSimpleSlug()] = schema
|
||||
}
|
||||
|
||||
errors.forEach { error ->
|
||||
SchemaGenerator.fromTypeOrUnit(error.responseType, spec.components.schemas, schemaConfigurator)?.let { schema ->
|
||||
spec.components.schemas[error.responseType.getSimpleSlug()] = schema
|
||||
}
|
||||
}
|
||||
|
||||
when (this) {
|
||||
is MethodInfoWithRequest -> {
|
||||
SchemaGenerator.fromTypeOrUnit(
|
||||
this.request.requestType,
|
||||
spec.components.schemas,
|
||||
schemaConfigurator
|
||||
)?.let { schema ->
|
||||
spec.components.schemas[this.request.requestType.getSimpleSlug()] = schema
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
|
||||
val operations = this.toPathOperation(config)
|
||||
|
||||
when (this) {
|
||||
is DeleteInfo -> path.delete = operations
|
||||
is GetInfo -> path.get = operations
|
||||
is HeadInfo -> path.head = operations
|
||||
is PatchInfo -> path.patch = operations
|
||||
is PostInfo -> path.post = operations
|
||||
is PutInfo -> path.put = operations
|
||||
is OptionsInfo -> path.options = operations
|
||||
}
|
||||
}
|
||||
|
||||
private fun MethodInfo.toPathOperation(config: SpecConfig) = PathOperation(
|
||||
tags = config.tags.plus(this.tags),
|
||||
summary = this.summary,
|
||||
description = this.description,
|
||||
externalDocs = this.externalDocumentation,
|
||||
operationId = this.operationId,
|
||||
deprecated = this.deprecated,
|
||||
parameters = this.parameters,
|
||||
security = config.security
|
||||
?.map { (k, v) -> k to v }
|
||||
?.map { listOf(it).toMap() }
|
||||
?.toMutableList(),
|
||||
requestBody = when (this) {
|
||||
is MethodInfoWithRequest -> Request(
|
||||
description = this.request.description,
|
||||
content = this.request.requestType.toReferenceContent(this.request.examples),
|
||||
required = true
|
||||
)
|
||||
|
||||
else -> null
|
||||
},
|
||||
responses = mapOf(
|
||||
this.response.responseCode.value to Response(
|
||||
description = this.response.description,
|
||||
content = this.response.responseType.toReferenceContent(this.response.examples)
|
||||
)
|
||||
).plus(this.errors.toResponseMap())
|
||||
)
|
||||
|
||||
private fun List<ResponseInfo>.toResponseMap(): Map<Int, Response> = associate { error ->
|
||||
error.responseCode.value to Response(
|
||||
description = error.description,
|
||||
content = error.responseType.toReferenceContent(error.examples)
|
||||
)
|
||||
}
|
||||
|
||||
private fun KType.toReferenceContent(examples: Map<String, MediaType.Example>?): Map<String, MediaType>? =
|
||||
when (this.classifier as KClass<*>) {
|
||||
Unit::class -> null
|
||||
else -> mapOf(
|
||||
"application/json" to MediaType(
|
||||
schema = ReferenceDefinition(this.getReferenceSlug()),
|
||||
examples = examples
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package io.bkbn.kompendium.core.util
|
||||
|
||||
import io.bkbn.kompendium.core.metadata.DeleteInfo
|
||||
import io.bkbn.kompendium.core.metadata.GetInfo
|
||||
import io.bkbn.kompendium.core.metadata.HeadInfo
|
||||
import io.bkbn.kompendium.core.metadata.OptionsInfo
|
||||
import io.bkbn.kompendium.core.metadata.PatchInfo
|
||||
import io.bkbn.kompendium.core.metadata.PostInfo
|
||||
import io.bkbn.kompendium.core.metadata.PutInfo
|
||||
import io.bkbn.kompendium.oas.payload.Parameter
|
||||
|
||||
interface SpecConfig {
|
||||
var tags: Set<String>
|
||||
var parameters: List<Parameter>
|
||||
var get: GetInfo?
|
||||
var post: PostInfo?
|
||||
var put: PutInfo?
|
||||
var delete: DeleteInfo?
|
||||
var patch: PatchInfo?
|
||||
var head: HeadInfo?
|
||||
var options: OptionsInfo?
|
||||
var security: Map<String, List<String>>?
|
||||
}
|
363
core/src/test/kotlin/io/bkbn/kompendium/core/KompendiumTest.kt
Normal file
@ -0,0 +1,363 @@
|
||||
package io.bkbn.kompendium.core
|
||||
|
||||
import dev.forst.ktor.apikey.apiKey
|
||||
import io.bkbn.kompendium.core.fixtures.TestHelpers.openApiTestAllSerializers
|
||||
import io.bkbn.kompendium.core.util.TestModules.complexRequest
|
||||
import io.bkbn.kompendium.core.util.TestModules.customAuthConfig
|
||||
import io.bkbn.kompendium.core.util.TestModules.customFieldNameResponse
|
||||
import io.bkbn.kompendium.core.util.TestModules.dateTimeString
|
||||
import io.bkbn.kompendium.core.util.TestModules.defaultAuthConfig
|
||||
import io.bkbn.kompendium.core.util.TestModules.defaultField
|
||||
import io.bkbn.kompendium.core.util.TestModules.defaultParameter
|
||||
import io.bkbn.kompendium.core.util.TestModules.exampleParams
|
||||
import io.bkbn.kompendium.core.util.TestModules.genericException
|
||||
import io.bkbn.kompendium.core.util.TestModules.genericPolymorphicResponse
|
||||
import io.bkbn.kompendium.core.util.TestModules.genericPolymorphicResponseMultipleImpls
|
||||
import io.bkbn.kompendium.core.util.TestModules.gnarlyGenericResponse
|
||||
import io.bkbn.kompendium.core.util.TestModules.headerParameter
|
||||
import io.bkbn.kompendium.core.util.TestModules.ignoredFieldsResponse
|
||||
import io.bkbn.kompendium.core.util.TestModules.multipleAuthStrategies
|
||||
import io.bkbn.kompendium.core.util.TestModules.multipleExceptions
|
||||
import io.bkbn.kompendium.core.util.TestModules.nestedGenericCollection
|
||||
import io.bkbn.kompendium.core.util.TestModules.nestedGenericMultipleParamsCollection
|
||||
import io.bkbn.kompendium.core.util.TestModules.nestedGenericResponse
|
||||
import io.bkbn.kompendium.core.util.TestModules.nestedTypeName
|
||||
import io.bkbn.kompendium.core.util.TestModules.nestedUnderRoot
|
||||
import io.bkbn.kompendium.core.util.TestModules.nonRequiredParam
|
||||
import io.bkbn.kompendium.core.util.TestModules.nonRequiredParams
|
||||
import io.bkbn.kompendium.core.util.TestModules.notarizedDelete
|
||||
import io.bkbn.kompendium.core.util.TestModules.notarizedGet
|
||||
import io.bkbn.kompendium.core.util.TestModules.notarizedHead
|
||||
import io.bkbn.kompendium.core.util.TestModules.notarizedOptions
|
||||
import io.bkbn.kompendium.core.util.TestModules.notarizedPatch
|
||||
import io.bkbn.kompendium.core.util.TestModules.notarizedPost
|
||||
import io.bkbn.kompendium.core.util.TestModules.notarizedPut
|
||||
import io.bkbn.kompendium.core.util.TestModules.nullableEnumField
|
||||
import io.bkbn.kompendium.core.util.TestModules.nullableField
|
||||
import io.bkbn.kompendium.core.util.TestModules.nullableNestedObject
|
||||
import io.bkbn.kompendium.core.util.TestModules.nullableReference
|
||||
import io.bkbn.kompendium.core.util.TestModules.polymorphicCollectionResponse
|
||||
import io.bkbn.kompendium.core.util.TestModules.polymorphicException
|
||||
import io.bkbn.kompendium.core.util.TestModules.polymorphicMapResponse
|
||||
import io.bkbn.kompendium.core.util.TestModules.polymorphicResponse
|
||||
import io.bkbn.kompendium.core.util.TestModules.primitives
|
||||
import io.bkbn.kompendium.core.util.TestModules.reqRespExamples
|
||||
import io.bkbn.kompendium.core.util.TestModules.requiredParams
|
||||
import io.bkbn.kompendium.core.util.TestModules.returnsList
|
||||
import io.bkbn.kompendium.core.util.TestModules.rootRoute
|
||||
import io.bkbn.kompendium.core.util.TestModules.simpleGenericResponse
|
||||
import io.bkbn.kompendium.core.util.TestModules.simplePathParsing
|
||||
import io.bkbn.kompendium.core.util.TestModules.simpleRecursive
|
||||
import io.bkbn.kompendium.core.util.TestModules.singleException
|
||||
import io.bkbn.kompendium.core.util.TestModules.trailingSlash
|
||||
import io.bkbn.kompendium.core.util.TestModules.unbackedFieldsResponse
|
||||
import io.bkbn.kompendium.core.util.TestModules.withOperationId
|
||||
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
|
||||
import io.bkbn.kompendium.json.schema.exception.UnknownSchemaException
|
||||
import io.bkbn.kompendium.oas.component.Components
|
||||
import io.bkbn.kompendium.oas.security.ApiKeyAuth
|
||||
import io.bkbn.kompendium.oas.security.BasicAuth
|
||||
import io.bkbn.kompendium.oas.security.BearerAuth
|
||||
import io.bkbn.kompendium.oas.security.OAuth
|
||||
import io.kotest.assertions.throwables.shouldThrow
|
||||
import io.kotest.core.spec.style.DescribeSpec
|
||||
import io.kotest.matchers.should
|
||||
import io.kotest.matchers.string.startWith
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.cio.CIO
|
||||
import io.ktor.http.HttpMethod
|
||||
import io.ktor.server.application.install
|
||||
import io.ktor.server.auth.Authentication
|
||||
import io.ktor.server.auth.OAuthServerSettings
|
||||
import io.ktor.server.auth.UserIdPrincipal
|
||||
import io.ktor.server.auth.basic
|
||||
import io.ktor.server.auth.jwt.jwt
|
||||
import io.ktor.server.auth.oauth
|
||||
import kotlin.reflect.typeOf
|
||||
import java.time.Instant
|
||||
|
||||
class KompendiumTest : DescribeSpec({
|
||||
describe("Notarized Open API Metadata Tests") {
|
||||
it("Can notarize a get request") {
|
||||
openApiTestAllSerializers("T0001__notarized_get.json") { notarizedGet() }
|
||||
}
|
||||
it("Can notarize a post request") {
|
||||
openApiTestAllSerializers("T0002__notarized_post.json") { notarizedPost() }
|
||||
}
|
||||
it("Can notarize a put request") {
|
||||
openApiTestAllSerializers("T0003__notarized_put.json") { notarizedPut() }
|
||||
}
|
||||
it("Can notarize a delete request") {
|
||||
openApiTestAllSerializers("T0004__notarized_delete.json") { notarizedDelete() }
|
||||
}
|
||||
it("Can notarize a patch request") {
|
||||
openApiTestAllSerializers("T0005__notarized_patch.json") { notarizedPatch() }
|
||||
}
|
||||
it("Can notarize a head request") {
|
||||
openApiTestAllSerializers("T0006__notarized_head.json") { notarizedHead() }
|
||||
}
|
||||
it("Can notarize an options request") {
|
||||
openApiTestAllSerializers("T0007__notarized_options.json") { notarizedOptions() }
|
||||
}
|
||||
it("Can notarize a complex type") {
|
||||
openApiTestAllSerializers("T0008__complex_type.json") { complexRequest() }
|
||||
}
|
||||
it("Can notarize primitives") {
|
||||
openApiTestAllSerializers("T0009__notarized_primitives.json") { primitives() }
|
||||
}
|
||||
it("Can notarize a top level list response") {
|
||||
openApiTestAllSerializers("T0010__response_list.json") { returnsList() }
|
||||
}
|
||||
it("Can notarize a route with non-required params") {
|
||||
openApiTestAllSerializers("T0011__non_required_params.json") { nonRequiredParams() }
|
||||
}
|
||||
}
|
||||
describe("Route Parsing") {
|
||||
it("Can parse a simple path and store it under the expected route") {
|
||||
openApiTestAllSerializers("T0012__path_parser.json") { simplePathParsing() }
|
||||
}
|
||||
it("Can notarize the root route") {
|
||||
openApiTestAllSerializers("T0013__root_route.json") { rootRoute() }
|
||||
}
|
||||
it("Can notarize a route under the root module without appending trailing slash") {
|
||||
openApiTestAllSerializers("T0014__nested_under_root.json") { nestedUnderRoot() }
|
||||
}
|
||||
it("Can notarize a route with a trailing slash") {
|
||||
openApiTestAllSerializers("T0015__trailing_slash.json") { trailingSlash() }
|
||||
}
|
||||
}
|
||||
describe("Exceptions") {
|
||||
it("Can add an exception status code to a response") {
|
||||
openApiTestAllSerializers("T0016__notarized_get_with_exception_response.json") { singleException() }
|
||||
}
|
||||
it("Can support multiple response codes") {
|
||||
openApiTestAllSerializers("T0017__notarized_get_with_multiple_exception_responses.json") { multipleExceptions() }
|
||||
}
|
||||
it("Can add a polymorphic exception response") {
|
||||
openApiTestAllSerializers("T0018__polymorphic_error_status_codes.json") { polymorphicException() }
|
||||
}
|
||||
it("Can add a generic exception response") {
|
||||
openApiTestAllSerializers("T0019__generic_exception.json") { genericException() }
|
||||
}
|
||||
}
|
||||
describe("Examples") {
|
||||
it("Can generate example response and request bodies") {
|
||||
openApiTestAllSerializers("T0020__example_req_and_resp.json") { reqRespExamples() }
|
||||
}
|
||||
it("Can describe example parameters") {
|
||||
openApiTestAllSerializers("T0021__example_parameters.json") { exampleParams() }
|
||||
}
|
||||
}
|
||||
describe("Defaults") {
|
||||
it("Can generate a default parameter value") {
|
||||
openApiTestAllSerializers("T0022__query_with_default_parameter.json") { defaultParameter() }
|
||||
}
|
||||
}
|
||||
describe("Required Fields") {
|
||||
it("Marks a parameter as required if there is no default and it is not marked nullable") {
|
||||
openApiTestAllSerializers("T0023__required_param.json") { requiredParams() }
|
||||
}
|
||||
it("Can mark a parameter as not required") {
|
||||
openApiTestAllSerializers("T0024__non_required_param.json") { nonRequiredParam() }
|
||||
}
|
||||
it("Does not mark a field as required if a default value is provided") {
|
||||
openApiTestAllSerializers("T0025__default_field.json") { defaultField() }
|
||||
}
|
||||
it("Does not mark a nullable field as required") {
|
||||
openApiTestAllSerializers("T0026__nullable_field.json") { nullableField() }
|
||||
}
|
||||
}
|
||||
describe("Polymorphism and Generics") {
|
||||
it("can generate a polymorphic response type") {
|
||||
openApiTestAllSerializers("T0027__polymorphic_response.json") { polymorphicResponse() }
|
||||
}
|
||||
it("Can generate a collection with polymorphic response type") {
|
||||
openApiTestAllSerializers("T0028__polymorphic_list_response.json") { polymorphicCollectionResponse() }
|
||||
}
|
||||
it("Can generate a map with a polymorphic response type") {
|
||||
openApiTestAllSerializers("T0029__polymorphic_map_response.json") { polymorphicMapResponse() }
|
||||
}
|
||||
it("Can generate a response type with a generic type") {
|
||||
openApiTestAllSerializers("T0030__simple_generic_response.json") { simpleGenericResponse() }
|
||||
}
|
||||
it("Can generate a response type with a nested generic type") {
|
||||
openApiTestAllSerializers("T0031__nested_generic_response.json") { nestedGenericResponse() }
|
||||
}
|
||||
it("Can generate a polymorphic response type with generics") {
|
||||
openApiTestAllSerializers("T0032__polymorphic_response_with_generics.json") { genericPolymorphicResponse() }
|
||||
}
|
||||
it("Can handle an absolutely psycho inheritance test") {
|
||||
openApiTestAllSerializers("T0033__crazy_polymorphic_example.json") { genericPolymorphicResponseMultipleImpls() }
|
||||
}
|
||||
it("Can support nested generic collections") {
|
||||
openApiTestAllSerializers("T0039__nested_generic_collection.json") { nestedGenericCollection() }
|
||||
}
|
||||
it("Can support nested generics with multiple type parameters") {
|
||||
openApiTestAllSerializers("T0040__nested_generic_multiple_type_params.json") {
|
||||
nestedGenericMultipleParamsCollection()
|
||||
}
|
||||
}
|
||||
it("Can handle a really gnarly generic example") {
|
||||
openApiTestAllSerializers("T0043__gnarly_generic_example.json") { gnarlyGenericResponse() }
|
||||
}
|
||||
}
|
||||
describe("Custom Serializable Reader tests") {
|
||||
it("Can support ignoring fields") {
|
||||
openApiTestAllSerializers("T0048__ignored_property.json") { ignoredFieldsResponse() }
|
||||
}
|
||||
it("Can support un-backed fields") {
|
||||
openApiTestAllSerializers("T0049__unbacked_property.json") { unbackedFieldsResponse() }
|
||||
}
|
||||
it("Can support custom named fields") {
|
||||
openApiTestAllSerializers("T0050__custom_named_property.json") { customFieldNameResponse() }
|
||||
}
|
||||
}
|
||||
describe("Miscellaneous") {
|
||||
xit("Can generate the necessary ReDoc home page") {
|
||||
// TODO apiFunctionalityTest(getFileSnapshot("redoc.html"), "/docs") { returnsList() }
|
||||
}
|
||||
it("Can add an operation id to a notarized route") {
|
||||
openApiTestAllSerializers("T0034__notarized_get_with_operation_id.json") { withOperationId() }
|
||||
}
|
||||
xit("Can add an undeclared field") {
|
||||
// TODO openApiTestAllSerializers("undeclared_field.json") { undeclaredType() }
|
||||
}
|
||||
it("Can add a custom header parameter with a name override") {
|
||||
openApiTestAllSerializers("T0035__override_parameter_name.json") { headerParameter() }
|
||||
}
|
||||
xit("Can override field name") {
|
||||
// TODO Assess strategies here
|
||||
}
|
||||
it("Can serialize a recursive type") {
|
||||
openApiTestAllSerializers("T0042__simple_recursive.json") { simpleRecursive() }
|
||||
}
|
||||
it("Nullable fields do not lead to doom") {
|
||||
openApiTestAllSerializers("T0036__nullable_fields.json") { nullableNestedObject() }
|
||||
}
|
||||
it("Can have a nullable enum as a member field") {
|
||||
openApiTestAllSerializers("T0037__nullable_enum_field.json") { nullableEnumField() }
|
||||
}
|
||||
it("Can have a nullable reference without impacting base type") {
|
||||
openApiTestAllSerializers("T0041__nullable_reference.json") { nullableReference() }
|
||||
}
|
||||
it("Can handle nested type names") {
|
||||
openApiTestAllSerializers("T0044__nested_type_name.json") { nestedTypeName() }
|
||||
}
|
||||
}
|
||||
describe("Error Handling") {
|
||||
it("Throws a clear exception when an unidentified type is encountered") {
|
||||
val exception = shouldThrow<UnknownSchemaException> { openApiTestAllSerializers("") { dateTimeString() } }
|
||||
exception.message should startWith("An unknown type was encountered: class java.time.Instant")
|
||||
}
|
||||
}
|
||||
describe("Constraints") {
|
||||
// TODO Assess strategies here
|
||||
}
|
||||
describe("Formats") {
|
||||
it("Can set a format for a simple type schema") {
|
||||
openApiTestAllSerializers(
|
||||
snapshotName = "T0038__formatted_date_time_string.json",
|
||||
customTypes = mapOf(typeOf<Instant>() to TypeDefinition(type = "string", format = "date"))
|
||||
) { dateTimeString() }
|
||||
}
|
||||
}
|
||||
describe("Free Form") {
|
||||
// todo Assess strategies here
|
||||
}
|
||||
describe("Authentication") {
|
||||
it("Can add a default auth config by default") {
|
||||
openApiTestAllSerializers(
|
||||
snapshotName = "T0045__default_auth_config.json",
|
||||
applicationSetup = {
|
||||
install(Authentication) {
|
||||
basic("basic") {
|
||||
realm = "Ktor Server"
|
||||
validate { UserIdPrincipal("Placeholder") }
|
||||
}
|
||||
}
|
||||
},
|
||||
specOverrides = {
|
||||
this.copy(
|
||||
components = Components(
|
||||
securitySchemes = mutableMapOf(
|
||||
"basic" to BasicAuth()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
) { defaultAuthConfig() }
|
||||
}
|
||||
it("Can provide custom auth config with proper scopes") {
|
||||
openApiTestAllSerializers(
|
||||
snapshotName = "T0046__custom_auth_config.json",
|
||||
applicationSetup = {
|
||||
install(Authentication) {
|
||||
oauth("auth-oauth-google") {
|
||||
urlProvider = { "http://localhost:8080/callback" }
|
||||
providerLookup = {
|
||||
OAuthServerSettings.OAuth2ServerSettings(
|
||||
name = "google",
|
||||
authorizeUrl = "https://accounts.google.com/o/oauth2/auth",
|
||||
accessTokenUrl = "https://accounts.google.com/o/oauth2/token",
|
||||
requestMethod = HttpMethod.Post,
|
||||
clientId = "DUMMY_VAL",
|
||||
clientSecret = "DUMMY_VAL",
|
||||
defaultScopes = listOf("https://www.googleapis.com/auth/userinfo.profile"),
|
||||
extraTokenParameters = listOf("access_type" to "offline")
|
||||
)
|
||||
}
|
||||
client = HttpClient(CIO)
|
||||
}
|
||||
}
|
||||
},
|
||||
specOverrides = {
|
||||
this.copy(
|
||||
components = Components(
|
||||
securitySchemes = mutableMapOf(
|
||||
"auth-oauth-google" to OAuth(
|
||||
flows = OAuth.Flows(
|
||||
implicit = OAuth.Flows.Implicit(
|
||||
authorizationUrl = "https://accounts.google.com/o/oauth2/auth",
|
||||
scopes = mapOf(
|
||||
"write:pets" to "modify pets in your account",
|
||||
"read:pets" to "read your pets"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
) { customAuthConfig() }
|
||||
}
|
||||
it("Can provide multiple authentication strategies") {
|
||||
openApiTestAllSerializers(
|
||||
snapshotName = "T0047__multiple_auth_strategies.json",
|
||||
applicationSetup = {
|
||||
install(Authentication) {
|
||||
apiKey("api-key") {
|
||||
headerName = "X-API-KEY"
|
||||
validate {
|
||||
UserIdPrincipal("Placeholder")
|
||||
}
|
||||
}
|
||||
jwt("jwt") {
|
||||
realm = "Server"
|
||||
}
|
||||
}
|
||||
},
|
||||
specOverrides = {
|
||||
this.copy(
|
||||
components = Components(
|
||||
securitySchemes = mutableMapOf(
|
||||
"jwt" to BearerAuth("JWT"),
|
||||
"api-key" to ApiKeyAuth(ApiKeyAuth.ApiKeyLocation.HEADER, "X-API-KEY")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
) { multipleAuthStrategies() }
|
||||
}
|
||||
}
|
||||
})
|
682
core/src/test/kotlin/io/bkbn/kompendium/core/util/TestModules.kt
Normal file
@ -0,0 +1,682 @@
|
||||
package io.bkbn.kompendium.core.util
|
||||
|
||||
import io.bkbn.kompendium.core.fixtures.Barzo
|
||||
import io.bkbn.kompendium.core.fixtures.ColumnSchema
|
||||
import io.bkbn.kompendium.core.fixtures.ComplexRequest
|
||||
import io.bkbn.kompendium.core.fixtures.DateTimeString
|
||||
import io.bkbn.kompendium.core.fixtures.DefaultField
|
||||
import io.bkbn.kompendium.core.fixtures.ExceptionResponse
|
||||
import io.bkbn.kompendium.core.fixtures.Flibbity
|
||||
import io.bkbn.kompendium.core.fixtures.FlibbityGibbit
|
||||
import io.bkbn.kompendium.core.fixtures.Foosy
|
||||
import io.bkbn.kompendium.core.fixtures.Gibbity
|
||||
import io.bkbn.kompendium.core.fixtures.ManyThings
|
||||
import io.bkbn.kompendium.core.fixtures.MultiNestedGenerics
|
||||
import io.bkbn.kompendium.core.fixtures.Nested
|
||||
import io.bkbn.kompendium.core.fixtures.NullableEnum
|
||||
import io.bkbn.kompendium.core.fixtures.NullableField
|
||||
import io.bkbn.kompendium.core.fixtures.Page
|
||||
import io.bkbn.kompendium.core.fixtures.ProfileUpdateRequest
|
||||
import io.bkbn.kompendium.core.fixtures.SerialNameObject
|
||||
import io.bkbn.kompendium.core.fixtures.TestCreatedResponse
|
||||
import io.bkbn.kompendium.core.fixtures.TestNested
|
||||
import io.bkbn.kompendium.core.fixtures.TestRequest
|
||||
import io.bkbn.kompendium.core.fixtures.TestResponse
|
||||
import io.bkbn.kompendium.core.fixtures.TestSimpleRequest
|
||||
import io.bkbn.kompendium.core.fixtures.TransientObject
|
||||
import io.bkbn.kompendium.core.fixtures.UnbakcedObject
|
||||
import io.bkbn.kompendium.core.metadata.DeleteInfo
|
||||
import io.bkbn.kompendium.core.metadata.GetInfo
|
||||
import io.bkbn.kompendium.core.metadata.HeadInfo
|
||||
import io.bkbn.kompendium.core.metadata.OptionsInfo
|
||||
import io.bkbn.kompendium.core.metadata.PatchInfo
|
||||
import io.bkbn.kompendium.core.metadata.PostInfo
|
||||
import io.bkbn.kompendium.core.metadata.PutInfo
|
||||
import io.bkbn.kompendium.core.plugin.NotarizedRoute
|
||||
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
|
||||
import io.bkbn.kompendium.oas.payload.Parameter
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.server.application.call
|
||||
import io.ktor.server.application.install
|
||||
import io.ktor.server.auth.authenticate
|
||||
import io.ktor.server.response.respond
|
||||
import io.ktor.server.response.respondText
|
||||
import io.ktor.server.routing.Route
|
||||
import io.ktor.server.routing.Routing
|
||||
import io.ktor.server.routing.delete
|
||||
import io.ktor.server.routing.get
|
||||
import io.ktor.server.routing.head
|
||||
import io.ktor.server.routing.options
|
||||
import io.ktor.server.routing.patch
|
||||
import io.ktor.server.routing.post
|
||||
import io.ktor.server.routing.put
|
||||
import io.ktor.server.routing.route
|
||||
|
||||
object TestModules {
|
||||
private const val defaultPath = "/test/{a}"
|
||||
private const val rootPath = "/"
|
||||
private const val defaultResponseDescription = "A Successful Endeavor"
|
||||
private const val defaultRequestDescription = "You gotta send it"
|
||||
private const val defaultPathSummary = "Great Summary!"
|
||||
private const val defaultPathDescription = "testing more"
|
||||
|
||||
private val defaultParams = listOf(
|
||||
Parameter(
|
||||
name = "a",
|
||||
`in` = Parameter.Location.path,
|
||||
schema = TypeDefinition.STRING,
|
||||
),
|
||||
Parameter(
|
||||
name = "aa",
|
||||
`in` = Parameter.Location.query,
|
||||
schema = TypeDefinition.INT
|
||||
)
|
||||
)
|
||||
|
||||
fun Routing.notarizedGet() {
|
||||
route(defaultPath) {
|
||||
install(NotarizedRoute()) {
|
||||
parameters = defaultParams
|
||||
get = GetInfo.builder {
|
||||
response {
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<TestResponse>()
|
||||
description(defaultResponseDescription)
|
||||
}
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
}
|
||||
}
|
||||
get {
|
||||
call.respondText { "hey dude ‼️ congrats on the get request" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.notarizedPost() {
|
||||
route(defaultPath) {
|
||||
install(NotarizedRoute()) {
|
||||
parameters = defaultParams
|
||||
post = PostInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
request {
|
||||
requestType<TestSimpleRequest>()
|
||||
description("A Test request")
|
||||
}
|
||||
response {
|
||||
responseCode(HttpStatusCode.Created)
|
||||
responseType<TestCreatedResponse>()
|
||||
description(defaultResponseDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
call.respondText { "hey dude ‼️ congrats on the post request" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.notarizedPut() {
|
||||
route(defaultPath) {
|
||||
install(NotarizedRoute()) {
|
||||
parameters = defaultParams
|
||||
put = PutInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
request {
|
||||
requestType<TestSimpleRequest>()
|
||||
description("A Test request")
|
||||
}
|
||||
response {
|
||||
responseCode(HttpStatusCode.Created)
|
||||
responseType<TestCreatedResponse>()
|
||||
description(defaultResponseDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
put {
|
||||
call.respondText { "hey dude ‼️ congrats on the post request" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.notarizedDelete() {
|
||||
route(defaultPath) {
|
||||
install(NotarizedRoute()) {
|
||||
parameters = defaultParams
|
||||
delete = DeleteInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
response {
|
||||
responseCode(HttpStatusCode.NoContent)
|
||||
responseType<Unit>()
|
||||
description(defaultResponseDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete {
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.notarizedPatch() {
|
||||
route(defaultPath) {
|
||||
install(NotarizedRoute()) {
|
||||
parameters = defaultParams
|
||||
patch = PatchInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
request {
|
||||
description("A Test request")
|
||||
requestType<TestSimpleRequest>()
|
||||
}
|
||||
response {
|
||||
responseCode(HttpStatusCode.Created)
|
||||
responseType<TestCreatedResponse>()
|
||||
description(defaultResponseDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
patch {
|
||||
call.respond(HttpStatusCode.Created) { TestCreatedResponse(123, "Nice!") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.notarizedHead() {
|
||||
route(defaultPath) {
|
||||
install(NotarizedRoute()) {
|
||||
parameters = defaultParams
|
||||
head = HeadInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
|
||||
response {
|
||||
description("great!")
|
||||
responseCode(HttpStatusCode.Created)
|
||||
responseType<Unit>()
|
||||
}
|
||||
}
|
||||
}
|
||||
head {
|
||||
call.respond(HttpStatusCode.OK)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.notarizedOptions() {
|
||||
route(defaultPath) {
|
||||
install(NotarizedRoute()) {
|
||||
parameters = defaultParams
|
||||
options = OptionsInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
response {
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<TestResponse>()
|
||||
description("nice")
|
||||
}
|
||||
}
|
||||
}
|
||||
options {
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.complexRequest() {
|
||||
route(rootPath) {
|
||||
install(NotarizedRoute()) {
|
||||
put = PutInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
request {
|
||||
requestType<ComplexRequest>()
|
||||
description("A Complex request")
|
||||
}
|
||||
response {
|
||||
responseCode(HttpStatusCode.Created)
|
||||
responseType<TestCreatedResponse>()
|
||||
description(defaultResponseDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
patch {
|
||||
call.respond(HttpStatusCode.Created, TestCreatedResponse(123, "nice!"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.primitives() {
|
||||
route(rootPath) {
|
||||
install(NotarizedRoute()) {
|
||||
put = PutInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
request {
|
||||
requestType<Int>()
|
||||
description("A Test Request")
|
||||
}
|
||||
response {
|
||||
responseCode(HttpStatusCode.Created)
|
||||
responseType<Boolean>()
|
||||
description(defaultResponseDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.returnsList() {
|
||||
route(defaultPath) {
|
||||
install(NotarizedRoute()) {
|
||||
parameters = defaultParams
|
||||
get = GetInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
response {
|
||||
description("A Successful List-y Endeavor")
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<List<TestResponse>>()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.nonRequiredParams() {
|
||||
route("/optional") {
|
||||
install(NotarizedRoute()) {
|
||||
parameters = listOf(
|
||||
Parameter(
|
||||
name = "notRequired",
|
||||
`in` = Parameter.Location.query,
|
||||
schema = TypeDefinition.STRING,
|
||||
required = false,
|
||||
),
|
||||
Parameter(
|
||||
name = "required",
|
||||
`in` = Parameter.Location.query,
|
||||
schema = TypeDefinition.STRING
|
||||
)
|
||||
)
|
||||
get = GetInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
response {
|
||||
responseType<Unit>()
|
||||
description("Empty")
|
||||
responseCode(HttpStatusCode.NoContent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.simplePathParsing() {
|
||||
route("/this") {
|
||||
route("/is") {
|
||||
route("/a") {
|
||||
route("/complex") {
|
||||
route("path") {
|
||||
route("with/an/{id}") {
|
||||
install(NotarizedRoute()) {
|
||||
get = GetInfo.builder {
|
||||
parameters = listOf(
|
||||
Parameter(
|
||||
name = "id",
|
||||
`in` = Parameter.Location.path,
|
||||
schema = TypeDefinition.STRING
|
||||
)
|
||||
)
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
response {
|
||||
description(defaultResponseDescription)
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<TestResponse>()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.rootRoute() {
|
||||
route(rootPath) {
|
||||
install(NotarizedRoute()) {
|
||||
parameters = listOf(defaultParams.last())
|
||||
get = GetInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
response {
|
||||
description(defaultResponseDescription)
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<TestResponse>()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.nestedUnderRoot() {
|
||||
route("/") {
|
||||
route("/testerino") {
|
||||
install(NotarizedRoute()) {
|
||||
get = GetInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
response {
|
||||
description(defaultResponseDescription)
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<TestResponse>()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.trailingSlash() {
|
||||
route("/test") {
|
||||
route("/") {
|
||||
install(NotarizedRoute()) {
|
||||
get = GetInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
response {
|
||||
description(defaultResponseDescription)
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<TestResponse>()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.singleException() {
|
||||
route(rootPath) {
|
||||
install(NotarizedRoute()) {
|
||||
get = GetInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
response {
|
||||
description(defaultResponseDescription)
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<TestResponse>()
|
||||
}
|
||||
canRespond {
|
||||
description("Bad Things Happened")
|
||||
responseCode(HttpStatusCode.BadRequest)
|
||||
responseType<ExceptionResponse>()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.multipleExceptions() {
|
||||
route(rootPath) {
|
||||
install(NotarizedRoute()) {
|
||||
get = GetInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
response {
|
||||
description(defaultResponseDescription)
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<TestResponse>()
|
||||
}
|
||||
canRespond {
|
||||
description("Bad Things Happened")
|
||||
responseCode(HttpStatusCode.BadRequest)
|
||||
responseType<ExceptionResponse>()
|
||||
}
|
||||
canRespond {
|
||||
description("Access Denied")
|
||||
responseCode(HttpStatusCode.Forbidden)
|
||||
responseType<ExceptionResponse>()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.polymorphicException() {
|
||||
route(rootPath) {
|
||||
install(NotarizedRoute()) {
|
||||
get = GetInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
response {
|
||||
description(defaultResponseDescription)
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<TestResponse>()
|
||||
}
|
||||
canRespond {
|
||||
description("Bad Things Happened")
|
||||
responseCode(HttpStatusCode.InternalServerError)
|
||||
responseType<FlibbityGibbit>()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.genericException() {
|
||||
route(rootPath) {
|
||||
install(NotarizedRoute()) {
|
||||
get = GetInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
response {
|
||||
description(defaultResponseDescription)
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<TestResponse>()
|
||||
}
|
||||
canRespond {
|
||||
description("Bad Things Happened")
|
||||
responseCode(HttpStatusCode.BadRequest)
|
||||
responseType<Flibbity<String>>()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.reqRespExamples() {
|
||||
route(rootPath) {
|
||||
install(NotarizedRoute()) {
|
||||
post = PostInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
request {
|
||||
description(defaultRequestDescription)
|
||||
requestType<TestRequest>()
|
||||
examples(
|
||||
"Testerina" to TestRequest(TestNested("asdf"), 1.5, emptyList())
|
||||
)
|
||||
}
|
||||
response {
|
||||
description(defaultResponseDescription)
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<TestResponse>()
|
||||
examples(
|
||||
"Testerino" to TestResponse("Heya")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.exampleParams() = basicGetGenerator<TestResponse>(
|
||||
params = listOf(
|
||||
Parameter(
|
||||
name = "id",
|
||||
`in` = Parameter.Location.path,
|
||||
schema = TypeDefinition.STRING,
|
||||
examples = mapOf(
|
||||
"foo" to Parameter.Example("testing")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
fun Routing.defaultParameter() = basicGetGenerator<TestResponse>(
|
||||
params = listOf(
|
||||
Parameter(
|
||||
name = "id",
|
||||
`in` = Parameter.Location.path,
|
||||
schema = TypeDefinition.STRING.withDefault("IDK")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
fun Routing.requiredParams() = basicGetGenerator<TestResponse>(
|
||||
params = listOf(
|
||||
Parameter(
|
||||
name = "id",
|
||||
`in` = Parameter.Location.path,
|
||||
schema = TypeDefinition.STRING
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
fun Routing.nonRequiredParam() = basicGetGenerator<TestResponse>(
|
||||
params = listOf(
|
||||
Parameter(
|
||||
name = "id",
|
||||
`in` = Parameter.Location.query,
|
||||
schema = TypeDefinition.STRING,
|
||||
required = false
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
fun Routing.defaultField() = basicGetGenerator<DefaultField>()
|
||||
|
||||
fun Routing.nullableField() = basicGetGenerator<NullableField>()
|
||||
|
||||
fun Routing.polymorphicResponse() = basicGetGenerator<FlibbityGibbit>()
|
||||
|
||||
fun Routing.ignoredFieldsResponse() = basicGetGenerator<TransientObject>()
|
||||
|
||||
fun Routing.unbackedFieldsResponse() = basicGetGenerator<UnbakcedObject>()
|
||||
|
||||
fun Routing.customFieldNameResponse() = basicGetGenerator<SerialNameObject>()
|
||||
|
||||
fun Routing.polymorphicCollectionResponse() = basicGetGenerator<List<FlibbityGibbit>>()
|
||||
|
||||
fun Routing.polymorphicMapResponse() = basicGetGenerator<Map<String, FlibbityGibbit>>()
|
||||
|
||||
fun Routing.simpleGenericResponse() = basicGetGenerator<Gibbity<String>>()
|
||||
|
||||
fun Routing.gnarlyGenericResponse() = basicGetGenerator<Foosy<Barzo<Int>, String>>()
|
||||
|
||||
fun Routing.nestedGenericResponse() = basicGetGenerator<Gibbity<Map<String, String>>>()
|
||||
|
||||
fun Routing.genericPolymorphicResponse() = basicGetGenerator<Flibbity<Double>>()
|
||||
|
||||
fun Routing.genericPolymorphicResponseMultipleImpls() = basicGetGenerator<Flibbity<FlibbityGibbit>>()
|
||||
|
||||
fun Routing.nestedGenericCollection() = basicGetGenerator<Page<Int>>()
|
||||
|
||||
fun Routing.nestedGenericMultipleParamsCollection() = basicGetGenerator<MultiNestedGenerics<String, ComplexRequest>>()
|
||||
|
||||
fun Routing.withOperationId() = basicGetGenerator<TestResponse>(operationId = "getThisDude")
|
||||
|
||||
fun Routing.nullableNestedObject() = basicGetGenerator<ProfileUpdateRequest>()
|
||||
|
||||
fun Routing.nullableEnumField() = basicGetGenerator<NullableEnum>()
|
||||
|
||||
fun Routing.nullableReference() = basicGetGenerator<ManyThings>()
|
||||
|
||||
fun Routing.dateTimeString() = basicGetGenerator<DateTimeString>()
|
||||
|
||||
fun Routing.headerParameter() = basicGetGenerator<TestResponse>(
|
||||
params = listOf(
|
||||
Parameter(
|
||||
name = "X-User-Email",
|
||||
`in` = Parameter.Location.header,
|
||||
schema = TypeDefinition.STRING,
|
||||
required = true
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
fun Routing.nestedTypeName() = basicGetGenerator<Nested.Response>()
|
||||
|
||||
fun Routing.simpleRecursive() = basicGetGenerator<ColumnSchema>()
|
||||
|
||||
fun Routing.defaultAuthConfig() {
|
||||
authenticate("basic") {
|
||||
route(rootPath) {
|
||||
basicGetGenerator<TestResponse>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.customAuthConfig() {
|
||||
authenticate("auth-oauth-google") {
|
||||
route(rootPath) {
|
||||
install(NotarizedRoute()) {
|
||||
get = GetInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
response {
|
||||
description(defaultResponseDescription)
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<TestResponse>()
|
||||
}
|
||||
security = mapOf(
|
||||
"auth-oauth-google" to listOf("read:pets")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Routing.multipleAuthStrategies() {
|
||||
authenticate("jwt", "api-key") {
|
||||
route(rootPath) {
|
||||
basicGetGenerator<TestResponse>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T> Routing.basicGetGenerator(
|
||||
params: List<Parameter> = emptyList(),
|
||||
operationId: String? = null
|
||||
) {
|
||||
route(rootPath) {
|
||||
basicGetGenerator<T>(params, operationId)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T> Route.basicGetGenerator(
|
||||
params: List<Parameter> = emptyList(),
|
||||
operationId: String? = null
|
||||
) {
|
||||
install(NotarizedRoute()) {
|
||||
get = GetInfo.builder {
|
||||
summary(defaultPathSummary)
|
||||
description(defaultPathDescription)
|
||||
operationId?.let { operationId(it) }
|
||||
parameters = params
|
||||
response {
|
||||
description(defaultResponseDescription)
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<T>()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,33 +27,12 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test": {
|
||||
"/test/{a}": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Another get test",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"operationId": "getTest",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
@ -66,12 +46,35 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -79,8 +82,7 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,38 +27,18 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test": {
|
||||
"/test/{a}": {
|
||||
"post": {
|
||||
"tags": [],
|
||||
"summary": "Test post endpoint",
|
||||
"description": "Post your tests here!",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"description": "A Test request",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TestRequest"
|
||||
"$ref": "#/components/schemas/TestSimpleRequest"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -76,61 +57,64 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestRequest": {
|
||||
"properties": {
|
||||
"aaa": {
|
||||
"items": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"b": {
|
||||
"format": "double",
|
||||
"type": "number"
|
||||
},
|
||||
"field_name": {
|
||||
"$ref": "#/components/schemas/TestNested"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"field_name",
|
||||
"b",
|
||||
"aaa"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TestNested": {
|
||||
"properties": {
|
||||
"nesty": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"nesty"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TestCreatedResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
"c",
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"TestSimpleRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string"
|
||||
},
|
||||
"b": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a",
|
||||
"b"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,38 +27,18 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test": {
|
||||
"/test/{a}": {
|
||||
"put": {
|
||||
"tags": [],
|
||||
"summary": "Test put endpoint",
|
||||
"description": "Put your tests here!",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"description": "A Test request",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TestRequest"
|
||||
"$ref": "#/components/schemas/TestSimpleRequest"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -76,61 +57,64 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestRequest": {
|
||||
"properties": {
|
||||
"aaa": {
|
||||
"items": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"b": {
|
||||
"format": "double",
|
||||
"type": "number"
|
||||
},
|
||||
"field_name": {
|
||||
"$ref": "#/components/schemas/TestNested"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"field_name",
|
||||
"b",
|
||||
"aaa"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TestNested": {
|
||||
"properties": {
|
||||
"nesty": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"nesty"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TestCreatedResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
"c",
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"TestSimpleRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string"
|
||||
},
|
||||
"b": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a",
|
||||
"b"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
73
core/src/test/resources/T0004__notarized_delete.json
Normal file
@ -0,0 +1,73 @@
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
"description": "An amazing, fully-ish 😉 generated API spec",
|
||||
"termsOfService": "https://example.com",
|
||||
"contact": {
|
||||
"name": "Homer Simpson",
|
||||
"url": "https://gph.is/1NPUDiM",
|
||||
"email": "chunkylover53@aol.com"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT",
|
||||
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://myawesomeapi.com",
|
||||
"description": "Production instance of my API"
|
||||
},
|
||||
{
|
||||
"url": "https://staging.myawesomeapi.com",
|
||||
"description": "Where the fun stuff happens"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/{a}": {
|
||||
"delete": {
|
||||
"tags": [],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "A Successful Endeavor"
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {},
|
||||
"securitySchemes": {}
|
||||
},
|
||||
"security": [],
|
||||
"tags": []
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,18 +27,18 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test": {
|
||||
"/test/{a}": {
|
||||
"patch": {
|
||||
"tags": [],
|
||||
"summary": "Test patch endpoint",
|
||||
"description": "patch your tests here!",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"description": "A Test request",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TestRequest"
|
||||
"$ref": "#/components/schemas/TestSimpleRequest"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -49,63 +50,71 @@
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TestResponse"
|
||||
"$ref": "#/components/schemas/TestCreatedResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestRequest": {
|
||||
"properties": {
|
||||
"aaa": {
|
||||
"items": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"b": {
|
||||
"format": "double",
|
||||
"type": "number"
|
||||
},
|
||||
"field_name": {
|
||||
"$ref": "#/components/schemas/TestNested"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"field_name",
|
||||
"b",
|
||||
"aaa"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TestNested": {
|
||||
"properties": {
|
||||
"nesty": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"nesty"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TestResponse": {
|
||||
"TestCreatedResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
"c",
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"TestSimpleRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string"
|
||||
},
|
||||
"b": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a",
|
||||
"b"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,21 +27,43 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test": {
|
||||
"/test/{a}": {
|
||||
"head": {
|
||||
"tags": [],
|
||||
"summary": "Test head endpoint",
|
||||
"description": "head test 💀",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"201": {
|
||||
"description": "great!"
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,32 +27,12 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test": {
|
||||
"/test/{a}": {
|
||||
"options": {
|
||||
"tags": [],
|
||||
"summary": "Test options",
|
||||
"description": "endpoint of options",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "nice",
|
||||
@ -65,12 +46,35 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -78,8 +82,7 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,11 +27,11 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test": {
|
||||
"/": {
|
||||
"put": {
|
||||
"tags": [],
|
||||
"summary": "Test put endpoint",
|
||||
"description": "Put your tests here!",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"description": "A Complex request",
|
||||
@ -56,14 +57,33 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ComplexRequest": {
|
||||
"TestCreatedResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"amazing_field": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"c",
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"ComplexRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"amazingField": {
|
||||
"type": "string"
|
||||
},
|
||||
"org": {
|
||||
@ -77,13 +97,13 @@
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"amazingField",
|
||||
"org",
|
||||
"amazing_field",
|
||||
"tables"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"NestedComplexItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"alias": {
|
||||
"additionalProperties": {
|
||||
@ -96,44 +116,23 @@
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"alias"
|
||||
],
|
||||
"type": "object"
|
||||
"alias",
|
||||
"name"
|
||||
]
|
||||
},
|
||||
"CrazyItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enumeration": {
|
||||
"$ref": "#/components/schemas/SimpleEnum"
|
||||
"enum": [
|
||||
"ONE",
|
||||
"TWO"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"enumeration"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"SimpleEnum": {
|
||||
"enum": [
|
||||
"ONE",
|
||||
"TWO"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"TestCreatedResponse": {
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,19 +27,18 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test": {
|
||||
"/": {
|
||||
"put": {
|
||||
"tags": [],
|
||||
"summary": "Test put endpoint",
|
||||
"description": "Put your tests here!",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"description": "A Test request",
|
||||
"description": "A Test Request",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
"$ref": "#/components/schemas/Int"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -50,18 +50,28 @@
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "boolean"
|
||||
"$ref": "#/components/schemas/Boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {},
|
||||
"schemas": {
|
||||
"Boolean": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"Int": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
||||
},
|
||||
"security": [],
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,54 +27,54 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test": {
|
||||
"/test/{a}": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Another get test",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful List-y Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/TestResponse"
|
||||
},
|
||||
"type": "array"
|
||||
"$ref": "#/components/schemas/List-TestResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -81,8 +82,13 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"List-TestResponse": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/TestResponse"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,41 +27,42 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/optional": {
|
||||
"/optional": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "No request params and response body",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "notRequired",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"required": false,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "required",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "Empty"
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "notRequired",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": false,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "required",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -29,27 +30,17 @@
|
||||
"/this/is/a/complex/path/with/an/{id}": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Another get test",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@ -65,12 +56,15 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -78,8 +72,7 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,32 +27,12 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/testerino": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Another get test",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
@ -65,12 +46,26 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -78,8 +73,7 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,25 +27,15 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/required_param": {
|
||||
"/testerino": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "required param",
|
||||
"description": "Cool stuff",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
@ -55,12 +46,15 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -68,8 +62,7 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,26 +27,15 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/required_param": {
|
||||
"/test/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "required param",
|
||||
"description": "Cool stuff",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "password"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
@ -56,12 +46,15 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -69,8 +62,7 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,32 +27,12 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Another get test",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
@ -75,12 +56,15 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -88,10 +72,10 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"ExceptionResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string"
|
||||
@ -99,8 +83,7 @@
|
||||
},
|
||||
"required": [
|
||||
"message"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,32 +27,12 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Another get test",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
@ -63,16 +44,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Access Denied",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ExceptionResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Things Happened",
|
||||
"content": {
|
||||
@ -82,15 +53,28 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Access Denied",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ExceptionResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -98,10 +82,10 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"ExceptionResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string"
|
||||
@ -109,8 +93,7 @@
|
||||
},
|
||||
"required": [
|
||||
"message"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,32 +27,12 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Another get test",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
@ -63,31 +44,27 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"501": {
|
||||
"description": "The Gibbits are ANGRY",
|
||||
"500": {
|
||||
"description": "Bad Things Happened",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/SimpleGibbit"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/ComplexGibbit"
|
||||
}
|
||||
]
|
||||
"$ref": "#/components/schemas/FlibbityGibbit"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -95,35 +72,51 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"SimpleGibbit": {
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"ComplexGibbit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"b": {
|
||||
"type": "string"
|
||||
},
|
||||
"c": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"z": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
"c",
|
||||
"z"
|
||||
]
|
||||
},
|
||||
"SimpleGibbit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string"
|
||||
},
|
||||
"z": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
]
|
||||
},
|
||||
"FlibbityGibbit": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ComplexGibbit"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/SimpleGibbit"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,32 +27,12 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Another get test",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
@ -64,30 +45,26 @@
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Wow serious things went wrong",
|
||||
"description": "Bad Things Happened",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/Gibbity-String"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Bibbity-String"
|
||||
}
|
||||
]
|
||||
"$ref": "#/components/schemas/Flibbity-String"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -95,21 +72,10 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"Gibbity-String": {
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"Bibbity-String": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"b": {
|
||||
"type": "string"
|
||||
@ -121,8 +87,28 @@
|
||||
"required": [
|
||||
"b",
|
||||
"f"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"Gibbity-String": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
]
|
||||
},
|
||||
"Flibbity-String": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/Bibbity-String"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Gibbity-String"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,39 +27,28 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/examples": {
|
||||
"/": {
|
||||
"post": {
|
||||
"tags": [],
|
||||
"summary": "Example Parameters",
|
||||
"description": "A test for setting parameter examples",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"description": "Test",
|
||||
"description": "You gotta send it",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TestRequest"
|
||||
},
|
||||
"examples": {
|
||||
"one": {
|
||||
"Testerina": {
|
||||
"value": {
|
||||
"fieldName": {
|
||||
"nesty": "hey"
|
||||
"nesty": "asdf"
|
||||
},
|
||||
"b": 4.0,
|
||||
"b": 1.5,
|
||||
"aaa": []
|
||||
}
|
||||
},
|
||||
"two": {
|
||||
"value": {
|
||||
"fieldName": {
|
||||
"nesty": "hello"
|
||||
},
|
||||
"b": 3.8,
|
||||
"aaa": [
|
||||
31324234
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -66,17 +56,17 @@
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "nice",
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TestResponse"
|
||||
},
|
||||
"examples": {
|
||||
"test": {
|
||||
"Testerino": {
|
||||
"value": {
|
||||
"c": "spud"
|
||||
"c": "Heya"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,47 +75,15 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestRequest": {
|
||||
"properties": {
|
||||
"aaa": {
|
||||
"items": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"b": {
|
||||
"format": "double",
|
||||
"type": "number"
|
||||
},
|
||||
"field_name": {
|
||||
"$ref": "#/components/schemas/TestNested"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"field_name",
|
||||
"b",
|
||||
"aaa"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TestNested": {
|
||||
"properties": {
|
||||
"nesty": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"nesty"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -133,8 +91,42 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
},
|
||||
"TestRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aaa": {
|
||||
"items": {
|
||||
"type": "number",
|
||||
"format": "int64"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"b": {
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
"fieldName": {
|
||||
"$ref": "#/components/schemas/TestNested"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"aaa",
|
||||
"b",
|
||||
"fieldName"
|
||||
]
|
||||
},
|
||||
"TestNested": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nesty": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"nesty"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,30 +27,25 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Another get test",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": {
|
||||
"foo": {
|
||||
"value": "testing"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@ -65,12 +61,15 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -78,8 +77,7 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,27 +27,18 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Another get test",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
"type": "string",
|
||||
"default": "IDK"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
@ -65,12 +57,15 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -78,8 +73,7 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -29,27 +30,17 @@
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Another get test",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@ -65,12 +56,15 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -78,8 +72,7 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,18 +27,17 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/required_param": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "default param",
|
||||
"description": "Cool stuff",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "b",
|
||||
"name": "id",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"default": "heyo"
|
||||
"type": "string"
|
||||
},
|
||||
"required": false,
|
||||
"deprecated": false
|
||||
@ -45,7 +45,7 @@
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
@ -56,12 +56,15 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -69,8 +72,7 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,45 +27,46 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/constrained_int": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Constrained int field",
|
||||
"description": "Cool stuff",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/MinMaxDouble"
|
||||
"$ref": "#/components/schemas/DefaultField"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"MinMaxDouble": {
|
||||
"DefaultField": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"format": "double",
|
||||
"type": "string"
|
||||
},
|
||||
"b": {
|
||||
"type": "number",
|
||||
"minimum": 5.5,
|
||||
"maximum": 13.37,
|
||||
"exclusiveMinimum": false,
|
||||
"exclusiveMaximum": false
|
||||
"format": "int32"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
],
|
||||
"type": "object"
|
||||
"b"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,45 +27,47 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/constrained_int": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Constrained int field",
|
||||
"description": "Cool stuff",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ExclusiveMinMax"
|
||||
"$ref": "#/components/schemas/NullableField"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ExclusiveMinMax": {
|
||||
"NullableField": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"format": "int32",
|
||||
"type": "integer",
|
||||
"minimum": 5,
|
||||
"maximum": 100,
|
||||
"exclusiveMinimum": true,
|
||||
"exclusiveMaximum": true
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
],
|
||||
"type": "object"
|
||||
"required": []
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,70 +27,75 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/polymorphiclist": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Oh so many gibbits",
|
||||
"description": "Polymorphic list response",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/SimpleGibbit"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/ComplexGibbit"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "array"
|
||||
"$ref": "#/components/schemas/FlibbityGibbit"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"FlibbityGibbit": {
|
||||
"properties": {},
|
||||
"type": "object"
|
||||
},
|
||||
"SimpleGibbit": {
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ComplexGibbit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"b": {
|
||||
"type": "string"
|
||||
},
|
||||
"c": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"z": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
"c",
|
||||
"z"
|
||||
]
|
||||
},
|
||||
"SimpleGibbit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string"
|
||||
},
|
||||
"z": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
]
|
||||
},
|
||||
"FlibbityGibbit": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ComplexGibbit"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/SimpleGibbit"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,73 +27,78 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/polymorphic": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "More flibbity",
|
||||
"description": "Polymorphic with generics",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/Gibbity-TestNested"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Bibbity-TestNested"
|
||||
}
|
||||
]
|
||||
"$ref": "#/components/schemas/List-FlibbityGibbit"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Gibbity-TestNested": {
|
||||
"properties": {
|
||||
"a": {
|
||||
"$ref": "#/components/schemas/TestNested"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TestNested": {
|
||||
"properties": {
|
||||
"nesty": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"nesty"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"Bibbity-TestNested": {
|
||||
"ComplexGibbit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"b": {
|
||||
"type": "string"
|
||||
},
|
||||
"f": {
|
||||
"$ref": "#/components/schemas/TestNested"
|
||||
"c": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"z": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"b",
|
||||
"f"
|
||||
],
|
||||
"type": "object"
|
||||
"c",
|
||||
"z"
|
||||
]
|
||||
},
|
||||
"SimpleGibbit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string"
|
||||
},
|
||||
"z": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
]
|
||||
},
|
||||
"List-FlibbityGibbit": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ComplexGibbit"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/SimpleGibbit"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,69 +27,77 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/polymorphicmap": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "By gawd that's a lot of gibbits",
|
||||
"description": "Polymorphic list response",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"additionalProperties": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/SimpleGibbit"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/ComplexGibbit"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "object"
|
||||
"$ref": "#/components/schemas/Map-String-FlibbityGibbit"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"FlibbityGibbit": {
|
||||
"properties": {},
|
||||
"type": "object"
|
||||
},
|
||||
"SimpleGibbit": {
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ComplexGibbit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"b": {
|
||||
"type": "string"
|
||||
},
|
||||
"c": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"z": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"c",
|
||||
"z"
|
||||
]
|
||||
},
|
||||
"SimpleGibbit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string"
|
||||
},
|
||||
"z": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
]
|
||||
},
|
||||
"Map-String-FlibbityGibbit": {
|
||||
"additionalProperties": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ComplexGibbit"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/SimpleGibbit"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
},
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,42 +27,42 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/required_param": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "required param",
|
||||
"description": "Cool stuff",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/MultipleOfDouble"
|
||||
"$ref": "#/components/schemas/Gibbity-String"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"MultipleOfDouble": {
|
||||
"Gibbity-String": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"format": "double",
|
||||
"type": "number",
|
||||
"multipleOf": 2.5
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,45 +27,45 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/required_param": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "required param",
|
||||
"description": "Cool stuff",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/MinMaxArray"
|
||||
"$ref": "#/components/schemas/Gibbity-Map"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"MinMaxArray": {
|
||||
"Gibbity-Map": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"items": {
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"minItems": 1,
|
||||
"maxItems": 10,
|
||||
"type": "array"
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,63 +27,69 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/polymorphic": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "All the gibbits",
|
||||
"description": "Polymorphic response",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/SimpleGibbit"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/ComplexGibbit"
|
||||
}
|
||||
]
|
||||
"$ref": "#/components/schemas/Flibbity-Double"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"SimpleGibbit": {
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ComplexGibbit": {
|
||||
"Bibbity-Double": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"b": {
|
||||
"type": "string"
|
||||
},
|
||||
"c": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
"f": {
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
"f"
|
||||
]
|
||||
},
|
||||
"Gibbity-Double": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
]
|
||||
},
|
||||
"Flibbity-Double": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/Bibbity-Double"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Gibbity-Double"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
145
core/src/test/resources/T0033__crazy_polymorphic_example.json
Normal file
@ -0,0 +1,145 @@
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
"description": "An amazing, fully-ish 😉 generated API spec",
|
||||
"termsOfService": "https://example.com",
|
||||
"contact": {
|
||||
"name": "Homer Simpson",
|
||||
"url": "https://gph.is/1NPUDiM",
|
||||
"email": "chunkylover53@aol.com"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT",
|
||||
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://myawesomeapi.com",
|
||||
"description": "Production instance of my API"
|
||||
},
|
||||
{
|
||||
"url": "https://staging.myawesomeapi.com",
|
||||
"description": "Where the fun stuff happens"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Flibbity-FlibbityGibbit"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ComplexGibbit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"b": {
|
||||
"type": "string"
|
||||
},
|
||||
"c": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"z": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"b",
|
||||
"c",
|
||||
"z"
|
||||
]
|
||||
},
|
||||
"SimpleGibbit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string"
|
||||
},
|
||||
"z": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
]
|
||||
},
|
||||
"Bibbity-FlibbityGibbit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"b": {
|
||||
"type": "string"
|
||||
},
|
||||
"f": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ComplexGibbit"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/SimpleGibbit"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"b",
|
||||
"f"
|
||||
]
|
||||
},
|
||||
"Gibbity-FlibbityGibbit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/ComplexGibbit"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/SimpleGibbit"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
]
|
||||
},
|
||||
"Flibbity-FlibbityGibbit": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/Bibbity-FlibbityGibbit"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Gibbity-FlibbityGibbit"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
||||
},
|
||||
"security": [],
|
||||
"tags": []
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
"description": "An amazing, fully-ish 😉 generated API spec",
|
||||
"termsOfService": "https://example.com",
|
||||
"contact": {
|
||||
"name": "Homer Simpson",
|
||||
"url": "https://gph.is/1NPUDiM",
|
||||
"email": "chunkylover53@aol.com"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT",
|
||||
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://myawesomeapi.com",
|
||||
"description": "Production instance of my API"
|
||||
},
|
||||
{
|
||||
"url": "https://staging.myawesomeapi.com",
|
||||
"description": "Where the fun stuff happens"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"operationId": "getThisDude",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TestResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
||||
},
|
||||
"security": [],
|
||||
"tags": []
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,14 +27,14 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/with_header": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "testing header stuffs",
|
||||
"description": "Good for many things",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "X-UserEmail",
|
||||
"name": "X-User-Email",
|
||||
"in": "header",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
@ -44,7 +45,7 @@
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
@ -55,12 +56,15 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -68,8 +72,7 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
131
core/src/test/resources/T0036__nullable_fields.json
Normal file
@ -0,0 +1,131 @@
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
"description": "An amazing, fully-ish 😉 generated API spec",
|
||||
"termsOfService": "https://example.com",
|
||||
"contact": {
|
||||
"name": "Homer Simpson",
|
||||
"url": "https://gph.is/1NPUDiM",
|
||||
"email": "chunkylover53@aol.com"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT",
|
||||
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://myawesomeapi.com",
|
||||
"description": "Production instance of my API"
|
||||
},
|
||||
{
|
||||
"url": "https://staging.myawesomeapi.com",
|
||||
"description": "Where the fun stuff happens"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProfileUpdateRequest"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ProfileUpdateRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"metadata": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/ProfileMetadataUpdateRequest"
|
||||
}
|
||||
]
|
||||
},
|
||||
"mood": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"viewCount": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"format": "int64"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
},
|
||||
"ProfileMetadataUpdateRequest": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"isPrivate": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
},
|
||||
"otherThing": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
||||
},
|
||||
"security": [],
|
||||
"tags": []
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,45 +27,50 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/constrained_int": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Constrained int field",
|
||||
"description": "Cool stuff",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/MinMaxInt"
|
||||
"$ref": "#/components/schemas/NullableEnum"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"MinMaxInt": {
|
||||
"NullableEnum": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"format": "int32",
|
||||
"type": "integer",
|
||||
"minimum": 5,
|
||||
"maximum": 100,
|
||||
"exclusiveMinimum": false,
|
||||
"exclusiveMaximum": false
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"YES",
|
||||
"NO"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
],
|
||||
"type": "object"
|
||||
"required": []
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,42 +27,47 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/required_param": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "required param",
|
||||
"description": "Cool stuff",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/MinMaxString"
|
||||
"$ref": "#/components/schemas/DateTimeString"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"MinMaxString": {
|
||||
"Instant": {
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
},
|
||||
"DateTimeString": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string",
|
||||
"minLength": 42,
|
||||
"maxLength": 1337
|
||||
"format": "date"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
101
core/src/test/resources/T0039__nested_generic_collection.json
Normal file
@ -0,0 +1,101 @@
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
"description": "An amazing, fully-ish 😉 generated API spec",
|
||||
"termsOfService": "https://example.com",
|
||||
"contact": {
|
||||
"name": "Homer Simpson",
|
||||
"url": "https://gph.is/1NPUDiM",
|
||||
"email": "chunkylover53@aol.com"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT",
|
||||
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://myawesomeapi.com",
|
||||
"description": "Production instance of my API"
|
||||
},
|
||||
{
|
||||
"url": "https://staging.myawesomeapi.com",
|
||||
"description": "Where the fun stuff happens"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Page-Int"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Page-Int": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"content": {
|
||||
"items": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"number": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"numberOfElements": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"size": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
},
|
||||
"totalElements": {
|
||||
"type": "number",
|
||||
"format": "int64"
|
||||
},
|
||||
"totalPages": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"content",
|
||||
"number",
|
||||
"numberOfElements",
|
||||
"size",
|
||||
"totalElements",
|
||||
"totalPages"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
||||
},
|
||||
"security": [],
|
||||
"tags": []
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
"description": "An amazing, fully-ish 😉 generated API spec",
|
||||
"termsOfService": "https://example.com",
|
||||
"contact": {
|
||||
"name": "Homer Simpson",
|
||||
"url": "https://gph.is/1NPUDiM",
|
||||
"email": "chunkylover53@aol.com"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT",
|
||||
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://myawesomeapi.com",
|
||||
"description": "Production instance of my API"
|
||||
},
|
||||
{
|
||||
"url": "https://staging.myawesomeapi.com",
|
||||
"description": "Where the fun stuff happens"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/MultiNestedGenerics-String-ComplexRequest"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"CrazyItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enumeration": {
|
||||
"enum": [
|
||||
"ONE",
|
||||
"TWO"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"enumeration"
|
||||
]
|
||||
},
|
||||
"NestedComplexItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"alias": {
|
||||
"additionalProperties": {
|
||||
"$ref": "#/components/schemas/CrazyItem"
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"alias",
|
||||
"name"
|
||||
]
|
||||
},
|
||||
"ComplexRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"amazingField": {
|
||||
"type": "string"
|
||||
},
|
||||
"org": {
|
||||
"type": "string"
|
||||
},
|
||||
"tables": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/NestedComplexItem"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"amazingField",
|
||||
"org",
|
||||
"tables"
|
||||
]
|
||||
},
|
||||
"MultiNestedGenerics-String-ComplexRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"content": {
|
||||
"additionalProperties": {
|
||||
"$ref": "#/components/schemas/ComplexRequest"
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"content"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
||||
},
|
||||
"security": [],
|
||||
"tags": []
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,63 +27,68 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/required_param": {
|
||||
"post": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "default param",
|
||||
"description": "Cool stuff",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"description": "cool",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/NullableField"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TestResponse"
|
||||
"$ref": "#/components/schemas/ManyThings"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"NullableField": {
|
||||
"Something": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TestResponse": {
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
},
|
||||
"b": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
"a",
|
||||
"b"
|
||||
]
|
||||
},
|
||||
"ManyThings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"someA": {
|
||||
"$ref": "#/components/schemas/Something"
|
||||
},
|
||||
"someB": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Something"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"someA"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,15 +27,15 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/simple_recursive": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Simple recursive example",
|
||||
"description": "Pretty neato!",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
@ -45,18 +46,25 @@
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"ColumnSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"mode": {
|
||||
"$ref": "#/components/schemas/ColumnMode"
|
||||
"enum": [
|
||||
"NULLABLE",
|
||||
"REQUIRED",
|
||||
"REPEATED"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
@ -72,20 +80,11 @@
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"type",
|
||||
"description",
|
||||
"mode"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ColumnMode": {
|
||||
"enum": [
|
||||
"NULLABLE",
|
||||
"REQUIRED",
|
||||
"REPEATED"
|
||||
],
|
||||
"type": "string"
|
||||
"mode",
|
||||
"name",
|
||||
"type"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
91
core/src/test/resources/T0043__gnarly_generic_example.json
Normal file
@ -0,0 +1,91 @@
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
"description": "An amazing, fully-ish 😉 generated API spec",
|
||||
"termsOfService": "https://example.com",
|
||||
"contact": {
|
||||
"name": "Homer Simpson",
|
||||
"url": "https://gph.is/1NPUDiM",
|
||||
"email": "chunkylover53@aol.com"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT",
|
||||
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://myawesomeapi.com",
|
||||
"description": "Production instance of my API"
|
||||
},
|
||||
{
|
||||
"url": "https://staging.myawesomeapi.com",
|
||||
"description": "Where the fun stuff happens"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Foosy-Barzo-String"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Foosy-Barzo-String": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"otherThing": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"test": {
|
||||
"$ref": "#/components/schemas/Barzo-Int"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"otherThing",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
"Barzo-Int": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {
|
||||
"type": "number",
|
||||
"format": "int32"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"result"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
||||
},
|
||||
"security": [],
|
||||
"tags": []
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,40 +27,42 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/field_override": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "A Response with a spicy field",
|
||||
"description": "Important info within!",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TestFieldOverride"
|
||||
"$ref": "#/components/schemas/NestedResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestFieldOverride": {
|
||||
"NestedResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"real_name": {
|
||||
"idk": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"real_name"
|
||||
],
|
||||
"type": "object"
|
||||
"idk"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,32 +27,12 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Another get test",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
@ -70,12 +51,15 @@
|
||||
"basic": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -83,8 +67,7 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {
|
92
core/src/test/resources/T0046__custom_auth_config.json
Normal file
@ -0,0 +1,92 @@
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
"description": "An amazing, fully-ish 😉 generated API spec",
|
||||
"termsOfService": "https://example.com",
|
||||
"contact": {
|
||||
"name": "Homer Simpson",
|
||||
"url": "https://gph.is/1NPUDiM",
|
||||
"email": "chunkylover53@aol.com"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT",
|
||||
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://myawesomeapi.com",
|
||||
"description": "Production instance of my API"
|
||||
},
|
||||
{
|
||||
"url": "https://staging.myawesomeapi.com",
|
||||
"description": "Where the fun stuff happens"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TestResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false,
|
||||
"security": [
|
||||
{
|
||||
"auth-oauth-google": [
|
||||
"read:pets"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {
|
||||
"auth-oauth-google": {
|
||||
"flows": {
|
||||
"implicit": {
|
||||
"authorizationUrl": "https://accounts.google.com/o/oauth2/auth",
|
||||
"scopes": {
|
||||
"write:pets": "modify pets in your account",
|
||||
"read:pets": "read your pets"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "oauth2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [],
|
||||
"tags": []
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,32 +27,12 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Another get test",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "a",
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "aa",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
@ -68,14 +49,20 @@
|
||||
"security": [
|
||||
{
|
||||
"jwt": []
|
||||
},
|
||||
{
|
||||
"api-key": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "string"
|
||||
@ -83,8 +70,7 @@
|
||||
},
|
||||
"required": [
|
||||
"c"
|
||||
],
|
||||
"type": "object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {
|
||||
@ -92,6 +78,11 @@
|
||||
"bearerFormat": "JWT",
|
||||
"type": "http",
|
||||
"scheme": "bearer"
|
||||
},
|
||||
"api-key": {
|
||||
"in": "header",
|
||||
"name": "X-API-KEY",
|
||||
"type": "apiKey"
|
||||
}
|
||||
}
|
||||
},
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,45 +27,42 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/polymorphic": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Single Generic",
|
||||
"description": "Simple generic data class",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/TestGeneric-Int"
|
||||
"$ref": "#/components/schemas/TransientObject"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"TestGeneric-Int": {
|
||||
"TransientObject": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"messy": {
|
||||
"nonTransient": {
|
||||
"type": "string"
|
||||
},
|
||||
"potato": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"messy",
|
||||
"potato"
|
||||
],
|
||||
"type": "object"
|
||||
"nonTransient"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
@ -26,41 +27,42 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/test/required_param": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "required param",
|
||||
"description": "Cool stuff",
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful endeavor",
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/FreeFormData"
|
||||
"$ref": "#/components/schemas/UnbakcedObject"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"FreeFormData": {
|
||||
"UnbakcedObject": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
"backed": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"data"
|
||||
],
|
||||
"type": "object"
|
||||
"backed"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
72
core/src/test/resources/T0050__custom_named_property.json
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.33.7",
|
||||
"description": "An amazing, fully-ish 😉 generated API spec",
|
||||
"termsOfService": "https://example.com",
|
||||
"contact": {
|
||||
"name": "Homer Simpson",
|
||||
"url": "https://gph.is/1NPUDiM",
|
||||
"email": "chunkylover53@aol.com"
|
||||
},
|
||||
"license": {
|
||||
"name": "MIT",
|
||||
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://myawesomeapi.com",
|
||||
"description": "Production instance of my API"
|
||||
},
|
||||
{
|
||||
"url": "https://staging.myawesomeapi.com",
|
||||
"description": "Where the fun stuff happens"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/": {
|
||||
"get": {
|
||||
"tags": [],
|
||||
"summary": "Great Summary!",
|
||||
"description": "testing more",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A Successful Endeavor",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/SerialNameObject"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated": false
|
||||
},
|
||||
"parameters": []
|
||||
}
|
||||
},
|
||||
"webhooks": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"SerialNameObject": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"snake_case_name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"snake_case_name"
|
||||
]
|
||||
}
|
||||
},
|
||||
"securitySchemes": {}
|
||||
},
|
||||
"security": [],
|
||||
"tags": []
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package io.bkbn.kompendium.core.fixtures
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.google.gson.annotations.Expose
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import io.bkbn.kompendium.json.schema.SchemaConfigurator
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty1
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.javaField
|
||||
|
||||
/*
|
||||
These are test implementation and may well be a good starting point for creating production ones.
|
||||
Both Gson and Jackson are complex and can achieve this things is more than one way therefore
|
||||
these will not always work hence why they are in the test package
|
||||
*/
|
||||
|
||||
class GsonSchemaConfigurator: SchemaConfigurator {
|
||||
|
||||
override fun serializableMemberProperties(clazz: KClass<*>): Collection<KProperty1<out Any, *>> {
|
||||
// NOTE: This is test logic Expose is set at a global Gson level so configure to match your Gson set up
|
||||
val hasAnyExpose = clazz.memberProperties.any { it.hasJavaAnnotation<Expose>() }
|
||||
return if(hasAnyExpose) {
|
||||
clazz.memberProperties
|
||||
.filter { it.hasJavaAnnotation<Expose>() }
|
||||
} else clazz.memberProperties
|
||||
}
|
||||
|
||||
override fun serializableName(property: KProperty1<out Any, *>): String =
|
||||
property.getJavaAnnotation<SerializedName>()?.value?: property.name
|
||||
|
||||
}
|
||||
|
||||
class JacksonSchemaConfigurator: SchemaConfigurator {
|
||||
|
||||
override fun serializableMemberProperties(clazz: KClass<*>): Collection<KProperty1<out Any, *>> =
|
||||
clazz.memberProperties
|
||||
.filterNot {
|
||||
it.hasJavaAnnotation<JsonIgnore>()
|
||||
}
|
||||
|
||||
override fun serializableName(property: KProperty1<out Any, *>): String =
|
||||
property.getJavaAnnotation<JsonProperty>()?.value?: property.name
|
||||
|
||||
}
|
||||
|
||||
inline fun <reified T: Annotation> KProperty1<*, *>.hasJavaAnnotation(): Boolean {
|
||||
return javaField?.isAnnotationPresent(T::class.java)?: false
|
||||
}
|
||||
|
||||
inline fun <reified T: Annotation> KProperty1<*, *>.getJavaAnnotation(): T? {
|
||||
return javaField?.getDeclaredAnnotation(T::class.java)
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
package io.bkbn.kompendium.core.fixtures
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude
|
||||
import com.fasterxml.jackson.databind.SerializationFeature
|
||||
import io.bkbn.kompendium.core.fixtures.TestSpecs.defaultSpec
|
||||
import io.bkbn.kompendium.core.plugin.NotarizedApplication
|
||||
import io.bkbn.kompendium.core.routes.redoc
|
||||
import io.bkbn.kompendium.json.schema.KotlinXSchemaConfigurator
|
||||
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||
import io.bkbn.kompendium.oas.OpenApiSpec
|
||||
import io.bkbn.kompendium.oas.serialization.KompendiumSerializersModule
|
||||
import io.kotest.assertions.json.shouldEqualJson
|
||||
import io.kotest.assertions.ktor.client.shouldHaveStatus
|
||||
import io.kotest.matchers.shouldNot
|
||||
import io.kotest.matchers.string.beBlank
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.serialization.gson.gson
|
||||
import io.ktor.serialization.jackson.jackson
|
||||
import io.ktor.serialization.kotlinx.json.json
|
||||
import io.ktor.server.application.Application
|
||||
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
|
||||
import io.ktor.server.routing.Routing
|
||||
import io.ktor.server.testing.ApplicationTestBuilder
|
||||
import io.ktor.server.testing.testApplication
|
||||
import kotlin.reflect.KType
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.io.File
|
||||
|
||||
object TestHelpers {
|
||||
private const val OPEN_API_ENDPOINT = "/openapi.json"
|
||||
|
||||
fun getFileSnapshot(fileName: String): String {
|
||||
val snapshotPath = "src/test/resources"
|
||||
val file = File("$snapshotPath/$fileName")
|
||||
return file.readText()
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the baseline expected tests on an OpenAPI result. Confirms that the endpoint
|
||||
* exists as expected, and that the content matches the expected blob found in the specified file
|
||||
* @param snapshotName The snapshot file to retrieve from the resources folder
|
||||
*/
|
||||
private suspend fun ApplicationTestBuilder.compareOpenAPISpec(snapshotName: String) {
|
||||
val response = client.get(OPEN_API_ENDPOINT)
|
||||
response shouldHaveStatus HttpStatusCode.OK
|
||||
response.bodyAsText() shouldNot beBlank()
|
||||
response.bodyAsText() shouldEqualJson getFileSnapshot(snapshotName)
|
||||
}
|
||||
|
||||
/**
|
||||
* This will take a provided JSON snapshot file, retrieve it from the resource folder,
|
||||
* and build a test ktor server to compare the expected output with the output found in the default
|
||||
* OpenAPI json endpoint. By default, this will run the same test with Gson, Kotlinx, and Jackson serializers
|
||||
* @param snapshotName The snapshot file to retrieve from the resources folder
|
||||
*/
|
||||
fun openApiTestAllSerializers(
|
||||
snapshotName: String,
|
||||
customTypes: Map<KType, JsonSchema> = emptyMap(),
|
||||
applicationSetup: Application.() -> Unit = { },
|
||||
specOverrides: OpenApiSpec.() -> OpenApiSpec = { this },
|
||||
routeUnderTest: Routing.() -> Unit
|
||||
) {
|
||||
openApiTest(snapshotName, SupportedSerializer.KOTLINX, routeUnderTest, applicationSetup, specOverrides, customTypes)
|
||||
openApiTest(snapshotName, SupportedSerializer.JACKSON, routeUnderTest, applicationSetup, specOverrides, customTypes)
|
||||
openApiTest(snapshotName, SupportedSerializer.GSON, routeUnderTest, applicationSetup, specOverrides, customTypes)
|
||||
}
|
||||
|
||||
private fun openApiTest(
|
||||
snapshotName: String,
|
||||
serializer: SupportedSerializer,
|
||||
routeUnderTest: Routing.() -> Unit,
|
||||
applicationSetup: Application.() -> Unit,
|
||||
specOverrides: OpenApiSpec.() -> OpenApiSpec,
|
||||
typeOverrides: Map<KType, JsonSchema> = emptyMap()
|
||||
) = testApplication {
|
||||
install(NotarizedApplication()) {
|
||||
customTypes = typeOverrides
|
||||
spec = defaultSpec().specOverrides()
|
||||
schemaConfigurator = when (serializer) {
|
||||
SupportedSerializer.KOTLINX -> KotlinXSchemaConfigurator()
|
||||
SupportedSerializer.GSON -> GsonSchemaConfigurator()
|
||||
SupportedSerializer.JACKSON -> JacksonSchemaConfigurator()
|
||||
}
|
||||
}
|
||||
install(ContentNegotiation) {
|
||||
when (serializer) {
|
||||
SupportedSerializer.KOTLINX -> json(Json {
|
||||
encodeDefaults = true
|
||||
explicitNulls = false
|
||||
serializersModule = KompendiumSerializersModule.module
|
||||
})
|
||||
|
||||
SupportedSerializer.GSON -> gson()
|
||||
SupportedSerializer.JACKSON -> jackson(ContentType.Application.Json) {
|
||||
enable(SerializationFeature.INDENT_OUTPUT)
|
||||
setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
||||
}
|
||||
}
|
||||
}
|
||||
application(applicationSetup)
|
||||
routing {
|
||||
redoc()
|
||||
routeUnderTest()
|
||||
}
|
||||
compareOpenAPISpec(snapshotName)
|
||||
}
|
||||
}
|
@ -0,0 +1,178 @@
|
||||
package io.bkbn.kompendium.core.fixtures
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.google.gson.annotations.Expose
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import java.time.Instant
|
||||
|
||||
@Serializable
|
||||
data class TestNested(val nesty: String)
|
||||
|
||||
@Serializable
|
||||
data class TestRequest(
|
||||
val fieldName: TestNested,
|
||||
val b: Double,
|
||||
val aaa: List<Long>
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TestSimpleRequest(
|
||||
val a: String,
|
||||
val b: Int
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TestResponse(val c: String)
|
||||
|
||||
@Serializable
|
||||
enum class TestEnum {
|
||||
YES,
|
||||
NO
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class NullableEnum(val a: TestEnum? = null)
|
||||
|
||||
data class TestCreatedResponse(val id: Int, val c: String)
|
||||
|
||||
data class DateTimeString(
|
||||
val a: Instant
|
||||
)
|
||||
|
||||
data class DefaultField(
|
||||
val a: String = "hi",
|
||||
val b: Int
|
||||
)
|
||||
|
||||
data class NullableField(
|
||||
val a: String?
|
||||
)
|
||||
|
||||
data class ComplexRequest(
|
||||
val org: String,
|
||||
val amazingField: String,
|
||||
val tables: List<NestedComplexItem>
|
||||
)
|
||||
|
||||
data class NestedComplexItem(
|
||||
val name: String,
|
||||
val alias: CustomAlias
|
||||
)
|
||||
|
||||
typealias CustomAlias = Map<String, CrazyItem>
|
||||
|
||||
data class CrazyItem(val enumeration: SimpleEnum)
|
||||
|
||||
enum class SimpleEnum {
|
||||
ONE,
|
||||
TWO
|
||||
}
|
||||
|
||||
data class ExceptionResponse(val message: String)
|
||||
|
||||
sealed class FlibbityGibbit {
|
||||
abstract val z: String
|
||||
}
|
||||
|
||||
data class SimpleGibbit(val a: String, override val z: String = "z") : FlibbityGibbit()
|
||||
data class ComplexGibbit(val b: String, val c: Int, override val z: String) : FlibbityGibbit()
|
||||
|
||||
sealed interface SlammaJamma
|
||||
|
||||
data class OneJamma(val a: Int) : SlammaJamma
|
||||
data class AnothaJamma(val b: Float) : SlammaJamma
|
||||
|
||||
data class InsaneJamma(val c: SlammaJamma) : SlammaJamma
|
||||
|
||||
sealed interface Flibbity<T>
|
||||
|
||||
data class Gibbity<T>(val a: T) : Flibbity<T>
|
||||
data class Bibbity<T>(val b: String, val f: T) : Flibbity<T>
|
||||
|
||||
data class NestedFlibbity<T>(
|
||||
val flibbity: Flibbity<T>
|
||||
)
|
||||
|
||||
enum class ColumnMode {
|
||||
NULLABLE,
|
||||
REQUIRED,
|
||||
REPEATED
|
||||
}
|
||||
|
||||
data class ColumnSchema(
|
||||
val name: String,
|
||||
val type: String,
|
||||
val description: String,
|
||||
val mode: ColumnMode,
|
||||
val subColumns: List<ColumnSchema> = emptyList()
|
||||
)
|
||||
|
||||
@Serializable
|
||||
public data class ProfileUpdateRequest(
|
||||
public val mood: String?,
|
||||
public val viewCount: Long?,
|
||||
public val metadata: ProfileMetadataUpdateRequest?
|
||||
)
|
||||
|
||||
|
||||
@Serializable
|
||||
public data class ProfileMetadataUpdateRequest(
|
||||
public val isPrivate: Boolean?,
|
||||
public val otherThing: String?
|
||||
)
|
||||
|
||||
data class Page<T>(
|
||||
val content: List<T>,
|
||||
val totalElements: Long,
|
||||
val totalPages: Int,
|
||||
val numberOfElements: Int,
|
||||
val number: Int,
|
||||
val size: Int
|
||||
)
|
||||
|
||||
data class MultiNestedGenerics<T, E>(
|
||||
val content: Map<T, E>
|
||||
)
|
||||
|
||||
data class Something(val a: String, val b: Int)
|
||||
|
||||
data class ManyThings(
|
||||
val someA: Something,
|
||||
val someB: Something?
|
||||
)
|
||||
|
||||
data class Foosy<T, K>(val test: T, val otherThing: List<K>)
|
||||
data class Barzo<G>(val result: G)
|
||||
|
||||
object Nested {
|
||||
@Serializable
|
||||
data class Response(val idk: Boolean)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class TransientObject(
|
||||
@field:Expose
|
||||
val nonTransient: String,
|
||||
@field:JsonIgnore
|
||||
@Transient
|
||||
val transient: String = "transient"
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class UnbakcedObject(
|
||||
val backed: String
|
||||
) {
|
||||
val unbacked: String get() = "unbacked"
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class SerialNameObject(
|
||||
@field:JsonProperty("snake_case_name")
|
||||
@field:SerializedName("snake_case_name")
|
||||
@SerialName("snake_case_name")
|
||||
val camelCaseName: String
|
||||
)
|
@ -13,7 +13,7 @@ object TestSpecs {
|
||||
info = Info(
|
||||
title = "Test API",
|
||||
version = "1.33.7",
|
||||
description = "An amazing, fully-ish 😉 generated API spec",
|
||||
description = "An amazing, fully-ish \uD83D\uDE09 generated API spec",
|
||||
termsOfService = URI("https://example.com"),
|
||||
contact = Contact(
|
||||
name = "Homer Simpson",
|
13
detekt.yml
@ -4,19 +4,24 @@ complexity:
|
||||
LongParameterList:
|
||||
active: true
|
||||
functionThreshold: 10
|
||||
constructorThreshold: 10
|
||||
constructorThreshold: 15
|
||||
ComplexMethod:
|
||||
threshold: 20
|
||||
formatting:
|
||||
ParameterListWrapping:
|
||||
active: false
|
||||
style:
|
||||
MaxLineLength:
|
||||
excludes: ['**/test/**/*']
|
||||
active: true
|
||||
maxLineLength: 120
|
||||
excludeCommentStatements: true
|
||||
MagicNumber:
|
||||
excludes: ['**/kompendium-playground/**/*', '**/test/**/*']
|
||||
ForbiddenMethodCall:
|
||||
active: true
|
||||
formatting:
|
||||
Indentation:
|
||||
indentSize: 2
|
||||
ImportOrdering:
|
||||
active: false
|
||||
naming:
|
||||
ConstructorParameterNaming:
|
||||
active: false
|
||||
|
@ -1,4 +0,0 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M21.2496 5.3C20.3496 4.5 19.2496 4 18.0496 4C16.8496 4 15.6496 4.5 14.8496 5.3L10.3496 9.8L11.7496 11.2L16.2496 6.7C17.2496 5.7 18.8496 5.7 19.8496 6.7C20.8496 7.7 20.8496 9.3 19.8496 10.3L15.3496 14.8L16.7496 16.2L21.2496 11.7C22.1496 10.8 22.5496 9.7 22.5496 8.5C22.5496 7.3 22.1496 6.2 21.2496 5.3Z" fill="#637282"/>
|
||||
<path d="M8.35 16.7998C7.35 17.7998 5.75 17.7998 4.75 16.7998C3.75 15.7998 3.75 14.1998 4.75 13.1998L9.25 8.6998L7.85 7.2998L3.35 11.7998C1.55 13.5998 1.55 16.3998 3.35 18.1998C4.25 19.0998 5.35 19.4998 6.55 19.4998C7.75 19.4998 8.85 19.0998 9.75 18.1998L14.25 13.6998L12.85 12.2998L8.35 16.7998Z" fill="#637282"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 754 B |
@ -1,3 +0,0 @@
|
||||
<svg width="24" height="24" viewBox="-5 -3 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11 9l-6 5.25V3.75z" fill="currentColor"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 160 B |
@ -1,3 +0,0 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 4H15V16H5V4ZM17 7H19V18V20H17H8V18H17V7Z" fill="black"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 215 B |
@ -1,3 +0,0 @@
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 9C18 14 14 18 9 18C4 18 0 14 0 9C0 4 4 0 9 0C14 0 18 4 18 9ZM14.2 6.2L12.8 4.8L7.5 10.1L5.3 7.8L3.8 9.2L7.5 13L14.2 6.2Z" fill="#4DBB5F"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 258 B |
@ -1,3 +0,0 @@
|
||||
<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 0H2.3949L4.84076 2.44586L0 7.28662L0.713376 8L5.55414 3.15924L8 5.6051V0Z" fill="#637282"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 206 B |
@ -1,4 +0,0 @@
|
||||
<svg width="12" height="10" viewBox="0 0 12 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.3337 9.66683H0.666992L6.00033 3.66683L11.3337 9.66683Z" fill="#637282"/>
|
||||
<path d="M0.666992 0.333496H11.3337V1.66683H0.666992V0.333496Z" fill="#637282"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 277 B |
@ -1,10 +0,0 @@
|
||||
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M64 64H0V0H64L31.3373 31.5369L64 64Z" fill="url(#paint0_radial)"/>
|
||||
<defs>
|
||||
<radialGradient id="paint0_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(61.8732 2.63097) scale(73.3111)">
|
||||
<stop offset="0.00343514" stop-color="#EF4857"/>
|
||||
<stop offset="0.4689" stop-color="#D211EC"/>
|
||||
<stop offset="1" stop-color="#7F52FF"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 558 B |
@ -1,4 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24">
|
||||
<path fill="white" fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M0 9a9 9 0 1018 0A9 9 0 000 9zm16 0a7 7 0 01-7 7V2a7 7 0 017 7z" transform="translate(3, 3)"></path>
|
||||
</svg>
|
Before Width: | Height: | Size: 247 B |
@ -1,136 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
|
||||
<title>All modules</title>
|
||||
<link href="images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "";</script> <script>const storage = localStorage.getItem("dokka-dark-mode")
|
||||
const savedDarkMode = storage ? JSON.parse(storage) : false
|
||||
if(savedDarkMode === true){
|
||||
document.getElementsByTagName("html")[0].classList.add("theme-dark")
|
||||
}</script>
|
||||
<script type="text/javascript" src="scripts/sourceset_dependencies.js" async="async"></script><link href="styles/style.css" rel="Stylesheet"><link href="styles/jetbrains-mono.css" rel="Stylesheet"><link href="styles/main.css" rel="Stylesheet"><link href="styles/prism.css" rel="Stylesheet"><link href="styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="scripts/clipboard.js" async="async"></script><script type="text/javascript" src="scripts/navigation-loader.js" async="async"></script><script type="text/javascript" src="scripts/platform-content-handler.js" async="async"></script><script type="text/javascript" src="scripts/main.js" defer="defer"></script><script type="text/javascript" src="scripts/prism.js" async="async"></script><link href="styles/multimodule.css" rel="Stylesheet"> </head>
|
||||
<body>
|
||||
<div class="navigation-wrapper" id="navigation-wrapper">
|
||||
<div id="leftToggler"><span class="icon-toggler"></span></div>
|
||||
<div class="library-name"><a href="index.html">kompendium</a></div>
|
||||
<div><dokka-template-command data="{"@class":"org.jetbrains.dokka.base.templating.ReplaceVersionsCommand","location":"index.html"}">2.0.1</dokka-template-command></div>
|
||||
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
|
||||
<div id="searchBar"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="container">
|
||||
<div id="leftColumn">
|
||||
<div id="sideMenu"></div>
|
||||
</div>
|
||||
<div id="main">
|
||||
<div class="main-content" id="content" pageIds="kompendium::.ext/allModules///PointingToDeclaration//0">
|
||||
<div class="breadcrumbs"></div>
|
||||
<div class="cover ">
|
||||
<div class="cover ">
|
||||
<h1 class="">Kompendium</h1>
|
||||
<p class="paragraph">Welcome to Kompendium, the straight-forward, minimally-invasive OpenAPI generator for Ktor. </p>
|
||||
<h2 class=""> How to install</h2>
|
||||
<p class="paragraph">Kompendium publishes all releases to Maven Central. As such, using the release versions of <code class="lang-kotlin">Kompendium</code> is as simple as declaring it as an implementation dependency in your <code class="lang-kotlin">build.gradle.kts</code></p>
|
||||
<div class="sample-container">
|
||||
<pre><code class="block lang-kotlin" theme="idea">repositories {<br> mavenCentral()<br>}<br><br>dependencies {<br> implementation("io.bkbn:kompendium-core:latest.release")<br>}</code></pre>
|
||||
<span class="top-right-position"><span class="copy-icon"></span>
|
||||
<div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div>
|
||||
</span></div>
|
||||
<p class="paragraph">In addition to publishing releases to Maven Central, a snapshot version gets published to GitHub Packages on every merge to <code class="lang-kotlin">main</code>. These can be consumed by adding the repository to your gradle build file. Instructions can be found <a href="https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-gradle-registry#using-a-published-package">here</a></p>
|
||||
<h2 class=""> Setting up the Kompendium Plugin</h2>
|
||||
<p class="paragraph">Kompendium is instantiated as a Ktor Feature/Plugin. It can be added to your API as follows</p>
|
||||
<div class="sample-container">
|
||||
<pre><code class="block lang-kotlin" theme="idea">private fun Application.mainModule() {<br> // Installs the Kompendium Plugin and sets up baseline server metadata<br> install(Kompendium) {<br> spec = OpenApiSpec(/*..*/)<br> }<br> // ...<br>}</code></pre>
|
||||
<span class="top-right-position"><span class="copy-icon"></span>
|
||||
<div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div>
|
||||
</span></div>
|
||||
<h2 class=""> Notarization</h2>
|
||||
<p class="paragraph">The concept of notarizing routes / exceptions / etc. is central to Kompendium. More details on <i>how</i> to notarize your API can be found in the kompendium-core module.</p>
|
||||
</div>
|
||||
<h2 class="">All modules:</h2>
|
||||
<div class="table"><a data-name="1162350513%2FMain%2F0" anchor-label="kompendium-annotations" id="1162350513%2FMain%2F0" data-filterable-set=""></a>
|
||||
<div class="table-row">
|
||||
<div class="main-subrow ">
|
||||
<div class="w-100"><span class="inline-flex">
|
||||
<div><a href="kompendium-annotations/index.html">kompendium-annotations</a></div>
|
||||
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="1162350513%2FMain%2F0"></span>
|
||||
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
|
||||
</span></span></div>
|
||||
<div><span class="brief-comment">
|
||||
<p class="paragraph">This module houses all annotations that Kompendium uses to provide key metadata when performing reflective analysis. </p>
|
||||
</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<a data-name="1574642149%2FMain%2F0" anchor-label="kompendium-auth" id="1574642149%2FMain%2F0" data-filterable-set=""></a>
|
||||
<div class="table-row">
|
||||
<div class="main-subrow ">
|
||||
<div class="w-100"><span class="inline-flex">
|
||||
<div><a href="kompendium-auth/index.html">kompendium-auth</a></div>
|
||||
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="1574642149%2FMain%2F0"></span>
|
||||
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
|
||||
</span></span></div>
|
||||
<div><span class="brief-comment">
|
||||
<p class="paragraph">This module is responsible for providing wrappers around ktor-auth configuration blocks, allowing users to document their API authentication with minimal modifications to their existing configuration.</p>
|
||||
</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<a data-name="-1821989938%2FMain%2F0" anchor-label="kompendium-core" id="-1821989938%2FMain%2F0" data-filterable-set=""></a>
|
||||
<div class="table-row">
|
||||
<div class="main-subrow ">
|
||||
<div class="w-100"><span class="inline-flex">
|
||||
<div><a href="kompendium-core/index.html">kompendium-core</a></div>
|
||||
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="-1821989938%2FMain%2F0"></span>
|
||||
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
|
||||
</span></span></div>
|
||||
<div><span class="brief-comment">
|
||||
<p class="paragraph">This is where the magic happens. This module houses all the reflective goodness that powers Kompendium.</p>
|
||||
</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<a data-name="-960478793%2FMain%2F0" anchor-label="kompendium-locations" id="-960478793%2FMain%2F0" data-filterable-set=""></a>
|
||||
<div class="table-row">
|
||||
<div class="main-subrow ">
|
||||
<div class="w-100"><span class="inline-flex">
|
||||
<div><a href="kompendium-locations/index.html">kompendium-locations</a></div>
|
||||
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="-960478793%2FMain%2F0"></span>
|
||||
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
|
||||
</span></span></div>
|
||||
<div><span class="brief-comment">
|
||||
<p class="paragraph">Adds support for Ktor <a href="https://ktor.io/docs/locations.html">Locations</a> API. Any notarized location <i>must</i> be provided with a <code class="lang-kotlin">TParam</code> annotated with <code class="lang-kotlin">@Location</code>. Nested Locations are supported</p>
|
||||
</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<a data-name="926400660%2FMain%2F0" anchor-label="kompendium-oas" id="926400660%2FMain%2F0" data-filterable-set=""></a>
|
||||
<div class="table-row">
|
||||
<div class="main-subrow ">
|
||||
<div class="w-100"><span class="inline-flex">
|
||||
<div><a href="kompendium-oas/index.html">kompendium-oas</a></div>
|
||||
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="926400660%2FMain%2F0"></span>
|
||||
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
|
||||
</span></span></div>
|
||||
<div><span class="brief-comment">
|
||||
<p class="paragraph">This module contains the models that represent the Open Api Specification 3.0 (OAS).</p>
|
||||
</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<a data-name="-1622380618%2FMain%2F0" anchor-label="kompendium-swagger-ui" id="-1622380618%2FMain%2F0" data-filterable-set=""></a>
|
||||
<div class="table-row">
|
||||
<div class="main-subrow ">
|
||||
<div class="w-100"><span class="inline-flex">
|
||||
<div><a href="kompendium-swagger-ui/index.html">kompendium-swagger-ui</a></div>
|
||||
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="-1622380618%2FMain%2F0"></span>
|
||||
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
|
||||
</span></span></div>
|
||||
<div><span class="brief-comment">
|
||||
<p class="paragraph">Contains the code necessary to launch <code class="lang-kotlin">swagger</code> as your documentation frontend.</p>
|
||||
</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,73 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
|
||||
<title>kompendium-annotations</title>
|
||||
</head><body><link href="../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../";</script>
|
||||
<script type="text/javascript" src="../scripts/sourceset_dependencies.js" async></script><link href="../styles/style.css" rel="Stylesheet"><link href="../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../styles/main.css" rel="Stylesheet"><link href="../styles/prism.css" rel="Stylesheet"><link href="../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../scripts/clipboard.js" async></script><script type="text/javascript" src="../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../scripts/main.js" defer></script><script type="text/javascript" src="../scripts/prism.js" async></script><link href="../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
|
||||
const savedDarkMode = storage ? JSON.parse(storage) : false
|
||||
if(savedDarkMode === true){
|
||||
document.getElementsByTagName("html")[0].classList.add("theme-dark")
|
||||
}</script>
|
||||
|
||||
|
||||
<div class="navigation-wrapper" id="navigation-wrapper">
|
||||
<div id="leftToggler"><span class="icon-toggler"></span></div>
|
||||
<div class="library-name"><a href="../index.html"><span>kompendium</span></a></div>
|
||||
<div><dokka-template-command data="{"@class":"org.jetbrains.dokka.base.templating.ReplaceVersionsCommand","location":"index.html"}">2.0.1</dokka-template-command></div>
|
||||
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
|
||||
<div id="searchBar"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="container">
|
||||
<div id="leftColumn">
|
||||
<div id="sideMenu"></div>
|
||||
</div>
|
||||
<div id="main">
|
||||
<div class="main-content" id="content" pageids="kompendium-annotations::////PointingToDeclaration//-1155457116">
|
||||
<div class="breadcrumbs"></div>
|
||||
<div class="cover ">
|
||||
<h1 class="cover"><span><span>kompendium-annotations</span></span></h1>
|
||||
<div class="platform-hinted UnderCoverText" data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><p class="paragraph">This module houses all annotations that Kompendium uses to provide key metadata when performing reflective analysis. </p><p class="paragraph">It is separated from core predominantly to allow for potential future integrations with <a href="https://github.com/google/ksp">Kotlin Symbol Processing</a></p></div></div>
|
||||
</div>
|
||||
<h2 class="">Packages</h2>
|
||||
<div class="table"><a data-name="-1446117290%2FPackages%2F-1155457116" anchor-label="io.bkbn.kompendium.annotations" id="-1446117290%2FPackages%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
|
||||
<div class="table-row" data-filterable-current=":kompendium-annotations:dokkaHtmlPartial/main" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main">
|
||||
<div>
|
||||
<div class="main-subrow ">
|
||||
<div class=""><span class="inline-flex">
|
||||
<div><a href="io.bkbn.kompendium.annotations/index.html">io.bkbn.kompendium.annotations</a></div>
|
||||
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="-1446117290%2FPackages%2F-1155457116"></span>
|
||||
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
|
||||
</span></span></div>
|
||||
<div class="pull-right"></div>
|
||||
</div>
|
||||
<div><span class="brief-comment"><a data-name="-1446117290%2FPackages%2F-1155457116" anchor-label="io.bkbn.kompendium.annotations" id="-1446117290%2FPackages%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
|
||||
<p class="paragraph">Contains all annotations used by Kompendium</p>
|
||||
</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<a data-name="1495666105%2FPackages%2F-1155457116" anchor-label="io.bkbn.kompendium.annotations.constraint" id="1495666105%2FPackages%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
|
||||
<div class="table-row" data-filterable-current=":kompendium-annotations:dokkaHtmlPartial/main" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main">
|
||||
<div>
|
||||
<div class="main-subrow ">
|
||||
<div class=""><span class="inline-flex">
|
||||
<div><a href="io.bkbn.kompendium.annotations.constraint/index.html">io.bkbn.kompendium.annotations.constraint</a></div>
|
||||
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="1495666105%2FPackages%2F-1155457116"></span>
|
||||
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
|
||||
</span></span></div>
|
||||
<div class="pull-right"></div>
|
||||
</div>
|
||||
<div><span class="brief-comment"><a data-name="1495666105%2FPackages%2F-1155457116" anchor-label="io.bkbn.kompendium.annotations.constraint" id="1495666105%2FPackages%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
|
||||
<p class="paragraph">Annotations that place bespoke constraints on individual fields of your API schemas.</p>
|
||||
</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body></html>
|
||||
|
||||
|
@ -1,39 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
|
||||
<title>Format</title>
|
||||
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
|
||||
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
|
||||
const savedDarkMode = storage ? JSON.parse(storage) : false
|
||||
if(savedDarkMode === true){
|
||||
document.getElementsByTagName("html")[0].classList.add("theme-dark")
|
||||
}</script>
|
||||
|
||||
|
||||
<div class="navigation-wrapper" id="navigation-wrapper">
|
||||
<div id="leftToggler"><span class="icon-toggler"></span></div>
|
||||
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
|
||||
<div><dokka-template-command data="{"@class":"org.jetbrains.dokka.base.templating.ReplaceVersionsCommand","location":"io.bkbn.kompendium.annotations.constraint/-format/-format.html"}">2.0.1</dokka-template-command></div>
|
||||
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
|
||||
<div id="searchBar"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="container">
|
||||
<div id="leftColumn">
|
||||
<div id="sideMenu"></div>
|
||||
</div>
|
||||
<div id="main">
|
||||
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/Format/Format/#kotlin.String/PointingToDeclaration//-1155457116">
|
||||
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">Format</a>/<a href="-format.html">Format</a></div>
|
||||
<div class="cover ">
|
||||
<h1 class="cover"><span><span>Format</span></span></h1>
|
||||
</div>
|
||||
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">fun </span><a href="-format.html"><span class="token function">Format</span></a><span class="token punctuation">(</span>format<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html">String</a><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
|
||||
</div>
|
||||
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body></html>
|
||||
|
||||
|
@ -1,39 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
|
||||
<title>format</title>
|
||||
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
|
||||
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
|
||||
const savedDarkMode = storage ? JSON.parse(storage) : false
|
||||
if(savedDarkMode === true){
|
||||
document.getElementsByTagName("html")[0].classList.add("theme-dark")
|
||||
}</script>
|
||||
|
||||
|
||||
<div class="navigation-wrapper" id="navigation-wrapper">
|
||||
<div id="leftToggler"><span class="icon-toggler"></span></div>
|
||||
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
|
||||
<div><dokka-template-command data="{"@class":"org.jetbrains.dokka.base.templating.ReplaceVersionsCommand","location":"io.bkbn.kompendium.annotations.constraint/-format/format.html"}">2.0.1</dokka-template-command></div>
|
||||
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
|
||||
<div id="searchBar"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="container">
|
||||
<div id="leftColumn">
|
||||
<div id="sideMenu"></div>
|
||||
</div>
|
||||
<div id="main">
|
||||
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/Format/format/#/PointingToDeclaration//-1155457116">
|
||||
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">Format</a>/<a href="format.html">format</a></div>
|
||||
<div class="cover ">
|
||||
<h1 class="cover"><span><span>format</span></span></h1>
|
||||
</div>
|
||||
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="format.html">format</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html">String</a><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
|
||||
</div>
|
||||
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body></html>
|
||||
|
||||
|
@ -1,61 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8">
|
||||
<title>Format</title>
|
||||
</head><body><link href="../../../images/logo-icon.svg" rel="icon" type="image/svg"><script>var pathToRoot = "../../../";</script>
|
||||
<script type="text/javascript" src="../../../scripts/sourceset_dependencies.js" async></script><link href="../../../styles/style.css" rel="Stylesheet"><link href="../../../styles/jetbrains-mono.css" rel="Stylesheet"><link href="../../../styles/main.css" rel="Stylesheet"><link href="../../../styles/prism.css" rel="Stylesheet"><link href="../../../styles/logo-styles.css" rel="Stylesheet"><script type="text/javascript" src="../../../scripts/clipboard.js" async></script><script type="text/javascript" src="../../../scripts/navigation-loader.js" async></script><script type="text/javascript" src="../../../scripts/platform-content-handler.js" async></script><script type="text/javascript" src="../../../scripts/main.js" defer></script><script type="text/javascript" src="../../../scripts/prism.js" async></script><link href="../../../styles/multimodule.css" rel="Stylesheet"><script>const storage = localStorage.getItem("dokka-dark-mode")
|
||||
const savedDarkMode = storage ? JSON.parse(storage) : false
|
||||
if(savedDarkMode === true){
|
||||
document.getElementsByTagName("html")[0].classList.add("theme-dark")
|
||||
}</script>
|
||||
|
||||
|
||||
<div class="navigation-wrapper" id="navigation-wrapper">
|
||||
<div id="leftToggler"><span class="icon-toggler"></span></div>
|
||||
<div class="library-name"><a href="../../../index.html"><span>kompendium</span></a></div>
|
||||
<div><dokka-template-command data="{"@class":"org.jetbrains.dokka.base.templating.ReplaceVersionsCommand","location":"io.bkbn.kompendium.annotations.constraint/-format/index.html"}">2.0.1</dokka-template-command></div>
|
||||
<div class="pull-right d-flex"><button id="theme-toggle-button"><span id="theme-toggle"></span></button>
|
||||
<div id="searchBar"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="container">
|
||||
<div id="leftColumn">
|
||||
<div id="sideMenu"></div>
|
||||
</div>
|
||||
<div id="main">
|
||||
<div class="main-content" id="content" pageids="kompendium-annotations::io.bkbn.kompendium.annotations.constraint/Format///PointingToDeclaration//-1155457116">
|
||||
<div class="breadcrumbs"><a href="../../index.html">kompendium-annotations</a>/<a href="../index.html">io.bkbn.kompendium.annotations.constraint</a>/<a href="index.html">Format</a></div>
|
||||
<div class="cover ">
|
||||
<h1 class="cover"><span><span>Format</span></span></h1>
|
||||
<div class="platform-hinted " data-platform-hinted="data-platform-hinted"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><div class="symbol monospace"><div class="block"><div class="block"><span class="token annotation">@</span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-target/index.html"><span class="token annotation">Target</span></a><span class="token punctuation">(</span><span>allowedTargets<span class="token operator"> = </span><span class="token punctuation">[</span><span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-annotation-target/-p-r-o-p-e-r-t-y/index.html">AnnotationTarget.PROPERTY</a></span><wbr><span class="token punctuation">]</span></span><wbr><span class="token punctuation">)</span></div></div><span class="token keyword">annotation class </span><a href="index.html">Format</a><span class="token punctuation">(</span>format<span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html">String</a><span class="token punctuation">)</span><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
|
||||
</div>
|
||||
<div class="tabbedcontent">
|
||||
<div class="tabs-section" tabs-section="tabs-section"><button class="section-tab" data-active="" data-togglable="Properties">Properties</button></div>
|
||||
<div class="tabs-section-body">
|
||||
<h2 class="">Properties</h2>
|
||||
<div class="table" data-togglable="Properties"><a data-name="-1740241114%2FProperties%2F-1155457116" anchor-label="format" id="-1740241114%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a>
|
||||
<div class="table-row" data-filterable-current=":kompendium-annotations:dokkaHtmlPartial/main" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main">
|
||||
<div class="main-subrow keyValue ">
|
||||
<div class=""><span class="inline-flex">
|
||||
<div><a href="format.html">format</a></div>
|
||||
<span class="anchor-wrapper"><span class="anchor-icon" pointing-to="-1740241114%2FProperties%2F-1155457116"></span>
|
||||
<div class="copy-popup-wrapper "><span class="copy-popup-icon"></span><span>Link copied to clipboard</span></div>
|
||||
</span></span></div>
|
||||
<div>
|
||||
<div class="title">
|
||||
<div class="platform-hinted " data-platform-hinted="data-platform-hinted" data-togglable="Properties"><div class="content sourceset-depenent-content" data-active="" data-togglable=":kompendium-annotations:dokkaHtmlPartial/main"><a data-name="-1740241114%2FProperties%2F-1155457116" anchor-label="format" id="-1740241114%2FProperties%2F-1155457116" data-filterable-set=":kompendium-annotations:dokkaHtmlPartial/main"></a><div class="symbol monospace"><span class="token keyword"></span><span class="token keyword">val </span><a href="format.html">format</a><span class="token operator">: </span><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html">String</a><span class="top-right-position"><span class="copy-icon"></span><div class="copy-popup-wrapper popup-to-left"><span class="copy-popup-icon"></span><span>Content copied to clipboard</span></div></span></div></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer"><span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>© 2022 Copyright</span><span class="pull-right"><span>Generated by </span><a href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body></html>
|
||||
|
||||
|