breaking change: V3 alpha (#256)
This commit is contained in:
55
oas/Module.md
Normal file
55
oas/Module.md
Normal file
@ -0,0 +1,55 @@
|
||||
# Module kompendium-oas
|
||||
|
||||
## Open Api Specification
|
||||
|
||||
This module contains the models that represent the Open Api Specification 3.0 (OAS).
|
||||
|
||||
It is a purely domain-based module, with no logic whatsoever.
|
||||
|
||||
The specification can be found [here](https://swagger.io/specification).
|
||||
|
||||
# Package io.bkbn.kompendium.oas
|
||||
|
||||
This is the root package that contains the top level spec that is ultimately serialized into the specification JSON
|
||||
payload.
|
||||
|
||||
# Package io.bkbn.kompendium.oas.common
|
||||
|
||||
Here we house data models that will be used across the module.
|
||||
|
||||
# Package io.bkbn.kompendium.oas.component
|
||||
|
||||
This package correlates to the OAS Component layer, which at the moment is relatively bare bones. It will just contain a
|
||||
reference to any security schemas, as adding objects here as components severely limits future ability to add cool
|
||||
features such as route level object validations. Got issues with that, bring it up with the Open API Team :)
|
||||
|
||||
# Package io.bkbn.kompendium.oas.info
|
||||
|
||||
This package houses the data models for information metadata such as contact and licensing info
|
||||
|
||||
# Package io.bkbn.kompendium.oas.path
|
||||
|
||||
Now we're getting to the good stuff. This is where the details on each path level operation will live. Your `gets`,
|
||||
your `puts`, so on and so forth.
|
||||
|
||||
# Package io.bkbn.kompendium.oas.payload
|
||||
|
||||
This is another good one, this is where the actual payload types live. Request and response body specifications,
|
||||
parameter details, collection support. That all lives here.
|
||||
|
||||
# Package io.bkbn.kompendium.oas.schema
|
||||
|
||||
A bit confusingly, in the OAS, there is a distinction between a payload and a schema. You can think of payloads as
|
||||
containing schemas. So here we dive into the true object level definitions that we want to map out. Models for
|
||||
supporting collections, dictionaries, polymorphic classes, enums, along with your standard library classes all live
|
||||
here.
|
||||
|
||||
# Package io.bkbn.kompendium.oas.security
|
||||
|
||||
Separated from the core schema models are the models that represent security schemas. Despite being referred to as
|
||||
schemas, and despite living as part of the component data structure, these models are drastically different from your
|
||||
core data model schemas, and thus earn their own package
|
||||
|
||||
# Package io.bkbn.kompendium.oas.server
|
||||
|
||||
Here we detail any server information that you wish to attach to your specification
|
32
oas/build.gradle.kts
Normal file
32
oas/build.gradle.kts
Normal file
@ -0,0 +1,32 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
kotlin("plugin.serialization")
|
||||
id("io.bkbn.sourdough.library.jvm")
|
||||
id("io.gitlab.arturbosch.detekt")
|
||||
id("com.adarshr.test-logger")
|
||||
id("org.jetbrains.dokka")
|
||||
id("maven-publish")
|
||||
id("java-library")
|
||||
id("signing")
|
||||
}
|
||||
|
||||
sourdoughLibrary {
|
||||
libraryName.set("Kompendium OpenAPI Spec")
|
||||
libraryDescription.set("Collections of kotlin data classes modeling the OpenAPI specification")
|
||||
compilerArgs.set(listOf("-opt-in=kotlin.RequiresOptIn"))
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(projects.kompendiumJsonSchema)
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.3")
|
||||
|
||||
testImplementation(testFixtures(projects.kompendiumCore))
|
||||
}
|
||||
|
||||
testing {
|
||||
suites {
|
||||
named("test", JvmTestSuite::class) {
|
||||
useJUnitJupiter()
|
||||
}
|
||||
}
|
||||
}
|
42
oas/src/main/kotlin/io/bkbn/kompendium/oas/OpenApiSpec.kt
Normal file
42
oas/src/main/kotlin/io/bkbn/kompendium/oas/OpenApiSpec.kt
Normal file
@ -0,0 +1,42 @@
|
||||
package io.bkbn.kompendium.oas
|
||||
|
||||
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||
import io.bkbn.kompendium.oas.common.Tag
|
||||
import io.bkbn.kompendium.oas.component.Components
|
||||
import io.bkbn.kompendium.oas.info.Info
|
||||
import io.bkbn.kompendium.oas.path.Path
|
||||
import io.bkbn.kompendium.oas.server.Server
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* This is the root object of the OpenAPI document.
|
||||
*
|
||||
* https://spec.openapis.org/oas/v3.1.0#openapi-object
|
||||
*
|
||||
* @param openapi This string MUST be the version number of the OpenAPI Specification that the OpenAPI document uses.
|
||||
* Kompendium only supports OpenAPI 3.1
|
||||
* @param jsonSchemaDialect The default value for the $schema keyword within Schema Objects contained within this OAS document.
|
||||
* Kompendium only supports the 2020 draft
|
||||
* @param info Provides metadata about the API.
|
||||
* @param servers An array of Server Objects, which provide connectivity information to a target server.
|
||||
* If the property is not provided, or is an empty array, the default value would be a Server Object with a url value of /.
|
||||
* @param paths The available paths and operations for the API.
|
||||
* @param webhooks The incoming webhooks that MAY be received as part of this API and that the API consumer MAY choose to implement.
|
||||
* @param components An element to hold various schemas for the document.
|
||||
* @param security A declaration of which security mechanisms can be used across the API.
|
||||
* @param tags A list of tags used by the document with additional metadata.
|
||||
* @param externalDocs Additional external documentation.
|
||||
*/
|
||||
@Serializable
|
||||
data class OpenApiSpec(
|
||||
val openapi: String = "3.1.0",
|
||||
val jsonSchemaDialect: String = "https://json-schema.org/draft/2020-12/schema",
|
||||
val info: Info,
|
||||
val servers: MutableList<Server> = mutableListOf(),
|
||||
val paths: MutableMap<String, Path> = mutableMapOf(),
|
||||
val webhooks: MutableMap<String, Path> = mutableMapOf(),
|
||||
val components: Components = Components(),
|
||||
val security: MutableList<Map<String, List<String>>> = mutableListOf(),
|
||||
val tags: MutableList<Tag> = mutableListOf(),
|
||||
val externalDocs: ExternalDocumentation? = null
|
||||
)
|
@ -0,0 +1,20 @@
|
||||
package io.bkbn.kompendium.oas.common
|
||||
|
||||
import io.bkbn.kompendium.oas.serialization.UriSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.net.URI
|
||||
|
||||
/**
|
||||
* Allows referencing an external resource for extended documentation.
|
||||
*
|
||||
* https://spec.openapis.org/oas/v3.1.0#external-documentation-object
|
||||
*
|
||||
* @param url The URL for the target documentation.
|
||||
* @param description A description of the target documentation.
|
||||
*/
|
||||
@Serializable
|
||||
data class ExternalDocumentation(
|
||||
@Serializable(with = UriSerializer::class)
|
||||
val url: URI,
|
||||
val description: String?
|
||||
)
|
10
oas/src/main/kotlin/io/bkbn/kompendium/oas/common/Tag.kt
Normal file
10
oas/src/main/kotlin/io/bkbn/kompendium/oas/common/Tag.kt
Normal file
@ -0,0 +1,10 @@
|
||||
package io.bkbn.kompendium.oas.common
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Tag(
|
||||
val name: String,
|
||||
val description: String? = null,
|
||||
val externalDocs: ExternalDocumentation? = null
|
||||
)
|
@ -0,0 +1,17 @@
|
||||
package io.bkbn.kompendium.oas.component
|
||||
|
||||
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||
import io.bkbn.kompendium.oas.security.SecuritySchema
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Holds a set of reusable objects for different aspects of the OAS. All objects defined within the components object
|
||||
* will have no effect on the API unless they are explicitly referenced from properties outside the components object.
|
||||
*
|
||||
* https://spec.openapis.org/oas/v3.1.0#components-object
|
||||
*/
|
||||
@Serializable
|
||||
data class Components(
|
||||
val schemas: MutableMap<String, JsonSchema> = mutableMapOf(),
|
||||
val securitySchemes: MutableMap<String, SecuritySchema> = mutableMapOf()
|
||||
)
|
22
oas/src/main/kotlin/io/bkbn/kompendium/oas/info/Contact.kt
Normal file
22
oas/src/main/kotlin/io/bkbn/kompendium/oas/info/Contact.kt
Normal file
@ -0,0 +1,22 @@
|
||||
package io.bkbn.kompendium.oas.info
|
||||
|
||||
import io.bkbn.kompendium.oas.serialization.UriSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.net.URI
|
||||
|
||||
/**
|
||||
* Contact information for the exposed API.
|
||||
*
|
||||
* https://spec.openapis.org/oas/v3.1.0#contactObject
|
||||
*
|
||||
* @param name The identifying name of the contact person/organization.
|
||||
* @param url The URL pointing to the contact information.
|
||||
* @param email The email address of the contact person/organization.
|
||||
*/
|
||||
@Serializable
|
||||
data class Contact(
|
||||
var name: String,
|
||||
@Serializable(with = UriSerializer::class)
|
||||
var url: URI? = null,
|
||||
var email: String? = null
|
||||
)
|
32
oas/src/main/kotlin/io/bkbn/kompendium/oas/info/Info.kt
Normal file
32
oas/src/main/kotlin/io/bkbn/kompendium/oas/info/Info.kt
Normal file
@ -0,0 +1,32 @@
|
||||
package io.bkbn.kompendium.oas.info
|
||||
|
||||
import io.bkbn.kompendium.oas.serialization.UriSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.net.URI
|
||||
|
||||
/**
|
||||
* The object provides metadata about the API.
|
||||
* The metadata MAY be used by the clients if needed, and MAY be presented in
|
||||
* editing or documentation generation tools for convenience.
|
||||
*
|
||||
* https://spec.openapis.org/oas/v3.1.0#infoObject
|
||||
*
|
||||
* @param title The title of the API.
|
||||
* @param version The version of the OpenAPI document.
|
||||
* @param summary A short summary of the API.
|
||||
* @param description A description of the API.
|
||||
* @param termsOfService A URL to the Terms of Service for the API.
|
||||
* @param contact The contact information for the exposed API.
|
||||
* @param license The license information for the exposed API.
|
||||
*/
|
||||
@Serializable
|
||||
data class Info(
|
||||
val title: String,
|
||||
var version: String,
|
||||
var summary: String? = null,
|
||||
var description: String? = null,
|
||||
@Serializable(with = UriSerializer::class)
|
||||
var termsOfService: URI? = null,
|
||||
var contact: Contact? = null,
|
||||
var license: License? = null,
|
||||
)
|
23
oas/src/main/kotlin/io/bkbn/kompendium/oas/info/License.kt
Normal file
23
oas/src/main/kotlin/io/bkbn/kompendium/oas/info/License.kt
Normal file
@ -0,0 +1,23 @@
|
||||
package io.bkbn.kompendium.oas.info
|
||||
|
||||
import io.bkbn.kompendium.oas.serialization.UriSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.net.URI
|
||||
|
||||
/**
|
||||
* License information for the exposed API.
|
||||
*
|
||||
* https://spec.openapis.org/oas/v3.1.0#license-object
|
||||
*
|
||||
* @param name The license name used for the API.
|
||||
* @param identifier An SPDX license expression for the API. The identifier field is mutually exclusive of the url field.
|
||||
* @param url A URL to the license used for the API.
|
||||
*
|
||||
*/
|
||||
@Serializable
|
||||
data class License(
|
||||
var name: String,
|
||||
var identifier: String? = null,
|
||||
@Serializable(with = UriSerializer::class)
|
||||
var url: URI? = null
|
||||
)
|
41
oas/src/main/kotlin/io/bkbn/kompendium/oas/path/Path.kt
Normal file
41
oas/src/main/kotlin/io/bkbn/kompendium/oas/path/Path.kt
Normal file
@ -0,0 +1,41 @@
|
||||
package io.bkbn.kompendium.oas.path
|
||||
|
||||
import io.bkbn.kompendium.oas.payload.Parameter
|
||||
import io.bkbn.kompendium.oas.server.Server
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Describes the operations available on a single path.
|
||||
*
|
||||
* https://spec.openapis.org/oas/v3.1.0#path-item-object
|
||||
*
|
||||
* @param summary An optional, string summary, intended to apply to all operations in this path.
|
||||
* @param description An optional, string description, intended to apply to all operations in this path.
|
||||
* @param get A definition of a GET operation on this path.
|
||||
* @param put A definition of a GET operation on this path.
|
||||
* @param post A definition of a GET operation on this path.
|
||||
* @param delete A definition of a GET operation on this path.
|
||||
* @param options A definition of a GET operation on this path.
|
||||
* @param head A definition of a GET operation on this path.
|
||||
* @param patch A definition of a GET operation on this path.
|
||||
* @param trace A definition of a GET operation on this path.
|
||||
* @param servers An alternative server array to service all operations in this path.
|
||||
* @param parameters A list of parameters that are applicable for all the operations described under this path.
|
||||
* These parameters can be overridden at the operation level,
|
||||
* but cannot be removed there. The list MUST NOT include duplicated parameters.
|
||||
*/
|
||||
@Serializable
|
||||
data class Path(
|
||||
var summary: String? = null,
|
||||
var description: String? = null,
|
||||
var get: PathOperation? = null,
|
||||
var put: PathOperation? = null,
|
||||
var post: PathOperation? = null,
|
||||
var delete: PathOperation? = null,
|
||||
var options: PathOperation? = null,
|
||||
var head: PathOperation? = null,
|
||||
var patch: PathOperation? = null,
|
||||
var trace: PathOperation? = null,
|
||||
var servers: List<Server>? = null,
|
||||
var parameters: List<Parameter>? = null
|
||||
)
|
@ -0,0 +1,44 @@
|
||||
package io.bkbn.kompendium.oas.path
|
||||
|
||||
import io.bkbn.kompendium.oas.common.ExternalDocumentation
|
||||
import io.bkbn.kompendium.oas.payload.Parameter
|
||||
import io.bkbn.kompendium.oas.payload.Request
|
||||
import io.bkbn.kompendium.oas.payload.Response
|
||||
import io.bkbn.kompendium.oas.server.Server
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Describes a single API operation on a path.
|
||||
*
|
||||
* https://spec.openapis.org/oas/v3.1.0#operation-object
|
||||
*
|
||||
* @param tags A list of tags for API documentation control. Tags can be used for logical grouping of operations by resources or any other qualifier.
|
||||
* @param summary A short summary of what the operation does.
|
||||
* @param description A verbose explanation of the operation behavior.
|
||||
* @param externalDocs Additional external documentation for this operation.
|
||||
* @param operationId Unique string used to identify the operation. The id MUST be unique among
|
||||
* all operations described in the API. The operationId value is case-sensitive.
|
||||
* @param parameters A list of parameters that are applicable for this operation. If a parameter is already defined at
|
||||
* the Path Item, the new definition will override it but can never remove it. The list MUST NOT include duplicated parameters
|
||||
* @param requestBody The request body applicable for this operation.
|
||||
* @param responses The list of possible responses as they are returned from executing this operation.
|
||||
* @param callbacks A map of possible out-of band callbacks related to the parent operation.
|
||||
* @param deprecated Declares this operation to be deprecated.
|
||||
* @param security A declaration of which security mechanisms can be used for this operation.
|
||||
* @param servers An alternative server array to service this operation.
|
||||
*/
|
||||
@Serializable
|
||||
data class PathOperation(
|
||||
var tags: Set<String> = emptySet(),
|
||||
var summary: String? = null,
|
||||
var description: String? = null,
|
||||
var externalDocs: ExternalDocumentation? = null,
|
||||
var operationId: String? = null,
|
||||
var parameters: List<Parameter>? = null,
|
||||
var requestBody: Request? = null,
|
||||
var responses: Map<Int, Response>? = null,
|
||||
var callbacks: Map<String, PathOperation>? = null,
|
||||
var deprecated: Boolean = false,
|
||||
var security: List<Map<String, List<String>>>? = null,
|
||||
var servers: List<Server>? = null,
|
||||
)
|
@ -0,0 +1,24 @@
|
||||
package io.bkbn.kompendium.oas.payload
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* A single encoding definition applied to a single schema property.
|
||||
*
|
||||
* https://spec.openapis.org/oas/v3.1.0#encoding-object
|
||||
*
|
||||
* @param contentType The Content-Type for encoding a specific property.
|
||||
* @param headers A map allowing additional information to be provided as headers
|
||||
* @param style Describes how a specific property value will be serialized depending on its type.
|
||||
* @param explode When this is true, property values of type array or object generate separate parameters for each
|
||||
* value of the array, or key-value-pair of the map. For other types of properties this property has no effect.
|
||||
* @param allowReserved Determines whether the parameter value SHOULD allow reserved characters, as defined by RFC3986
|
||||
*/
|
||||
@Serializable
|
||||
data class Encoding(
|
||||
val contentType: String,
|
||||
val headers: MutableMap<String, Header>,
|
||||
val style: String,
|
||||
val explode: Boolean,
|
||||
val allowReserved: Boolean = false
|
||||
)
|
25
oas/src/main/kotlin/io/bkbn/kompendium/oas/payload/Header.kt
Normal file
25
oas/src/main/kotlin/io/bkbn/kompendium/oas/payload/Header.kt
Normal file
@ -0,0 +1,25 @@
|
||||
package io.bkbn.kompendium.oas.payload
|
||||
|
||||
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Describes a header object
|
||||
* https://spec.openapis.org/oas/v3.1.0#header-object
|
||||
*
|
||||
* @param description A brief description of the parameter.
|
||||
* @param required Determines whether this parameter is mandatory. If the parameter location is "path",
|
||||
* this property is REQUIRED and its value MUST be true. Otherwise, the property MAY be included and its default value is false.
|
||||
* @param deprecated Specifies that a parameter is deprecated and SHOULD be transitioned out of usage.
|
||||
* @param allowEmptyValue Sets the ability to pass empty-valued parameters.
|
||||
* This is valid only for query parameters and allows sending a parameter with an empty value.
|
||||
*/
|
||||
@Serializable
|
||||
data class Header(
|
||||
val schema: JsonSchema,
|
||||
val description: String? = null,
|
||||
val required: Boolean = true,
|
||||
val deprecated: Boolean = false,
|
||||
val allowEmptyValue: Boolean? = null,
|
||||
// todo support styling https://spec.openapis.org/oas/v3.1.0#style-values
|
||||
)
|
26
oas/src/main/kotlin/io/bkbn/kompendium/oas/payload/Link.kt
Normal file
26
oas/src/main/kotlin/io/bkbn/kompendium/oas/payload/Link.kt
Normal file
@ -0,0 +1,26 @@
|
||||
package io.bkbn.kompendium.oas.payload
|
||||
|
||||
import io.bkbn.kompendium.oas.server.Server
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* The Link object represents a possible design-time link for a response.
|
||||
*
|
||||
* https://spec.openapis.org/oas/v3.1.0#link-object
|
||||
*
|
||||
* @param operationRef A relative or absolute URI reference to an OAS operation.
|
||||
* @param operationId The name of an existing, resolvable OAS operation
|
||||
* @param parameters A map representing parameters to pass to an operation as specified with operationId or identified via operationRef.
|
||||
* @param requestBody Used as a request body when calling the target operation.
|
||||
* @param description A description of the link.
|
||||
* @param server A server object to be used by the target operation.
|
||||
*/
|
||||
@Serializable
|
||||
data class Link(
|
||||
val operationRef: String? = null,
|
||||
val operationId: String? = null,
|
||||
val parameters: Map<String, String>? = null,
|
||||
val requestBody: Map<String, String>? = null,
|
||||
val description: String? = null,
|
||||
val server: Server? = null
|
||||
)
|
@ -0,0 +1,24 @@
|
||||
package io.bkbn.kompendium.oas.payload
|
||||
|
||||
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||
import kotlinx.serialization.Contextual
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Each Media Type Object provides schema and examples for the media type identified by its key.
|
||||
*
|
||||
* https://spec.openapis.org/oas/v3.1.0#media-type-object
|
||||
*
|
||||
* @param schema The schema defining the content of the request, response, or parameter.
|
||||
* @param examples Examples of the media type. Each example object SHOULD match the media type and specified schema if present.
|
||||
* @param encoding A map between a property name and its encoding information.
|
||||
*/
|
||||
@Serializable
|
||||
data class MediaType(
|
||||
val schema: JsonSchema,
|
||||
val examples: Map<String, Example>? = null,
|
||||
val encoding: Map<String, Encoding>? = null,
|
||||
) {
|
||||
@Serializable
|
||||
data class Example(@Contextual val value: Any)
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package io.bkbn.kompendium.oas.payload
|
||||
|
||||
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||
import kotlinx.serialization.Contextual
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Describes a single operation parameter
|
||||
* https://spec.openapis.org/oas/v3.1.0#parameter-object
|
||||
*
|
||||
* @param name The name of the parameter. Parameter names are case-sensitive.
|
||||
* @param in The location of the parameter.
|
||||
* @param description A brief description of the parameter.
|
||||
* @param required Determines whether this parameter is mandatory. If the parameter location is "path",
|
||||
* this property is REQUIRED and its value MUST be true. Otherwise, the property MAY be included and its default value is false.
|
||||
* @param deprecated Specifies that a parameter is deprecated and SHOULD be transitioned out of usage.
|
||||
* @param allowEmptyValue Sets the ability to pass empty-valued parameters.
|
||||
* This is valid only for query parameters and allows sending a parameter with an empty value.
|
||||
*/
|
||||
@Serializable
|
||||
data class Parameter(
|
||||
val name: String,
|
||||
val `in`: Location,
|
||||
val schema: JsonSchema,
|
||||
val description: String? = null,
|
||||
val required: Boolean = true,
|
||||
val deprecated: Boolean = false,
|
||||
val allowEmptyValue: Boolean? = null,
|
||||
val examples: Map<String, Example>? = null,
|
||||
// todo support styling https://spec.openapis.org/oas/v3.1.0#style-values
|
||||
) {
|
||||
@Serializable
|
||||
data class Example(@Contextual val value: Any)
|
||||
|
||||
@Suppress("EnumNaming")
|
||||
@Serializable
|
||||
enum class Location {
|
||||
query,
|
||||
header,
|
||||
path,
|
||||
cookie
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package io.bkbn.kompendium.oas.payload
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Describes a single request body.
|
||||
*
|
||||
* https://spec.openapis.org/oas/v3.1.0#request-body-object
|
||||
*
|
||||
* @param description A brief description of the request body.
|
||||
* @param content The content of the request body. The key is a media type or media type range and the value describes it.
|
||||
* @param required Determines if the request body is required in the request.
|
||||
*/
|
||||
@Serializable
|
||||
data class Request(
|
||||
val description: String?,
|
||||
val content: Map<String, MediaType>?, // todo maybe this needs to be required?? 👀
|
||||
val required: Boolean = false
|
||||
)
|
@ -0,0 +1,22 @@
|
||||
package io.bkbn.kompendium.oas.payload
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Describes a single response from an API Operation
|
||||
*
|
||||
* https://spec.openapis.org/oas/v3.1.0#response-object
|
||||
*
|
||||
* @param description A description of the response.
|
||||
* @param headers Maps a header name to its definition.
|
||||
* @param content A map containing descriptions of potential response payloads.
|
||||
* The key is a media type or media type range and the value describes it.
|
||||
* @param links A map of operations links that can be followed from the response.
|
||||
*/
|
||||
@Serializable
|
||||
data class Response(
|
||||
val description: String,
|
||||
val headers: Map<String, Header>? = null,
|
||||
val content: Map<String, MediaType>? = null,
|
||||
val links: Map<String, Link>? = null
|
||||
)
|
@ -0,0 +1,18 @@
|
||||
package io.bkbn.kompendium.oas.security
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
// TODO... is there even an official ktor api auth mechanism??
|
||||
|
||||
@Serializable
|
||||
class ApiKeyAuth private constructor(val `in`: String, val name: String) : SecuritySchema {
|
||||
val type: String = "apiKey"
|
||||
|
||||
constructor(location: ApiKeyLocation, name: String) : this(location.value, name)
|
||||
|
||||
enum class ApiKeyLocation(val value: String) {
|
||||
HEADER("header"),
|
||||
QUERY("query"),
|
||||
COOKIE("cookie");
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package io.bkbn.kompendium.oas.security
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
class BasicAuth : SecuritySchema {
|
||||
val type: String = "http"
|
||||
val scheme: String = "basic"
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package io.bkbn.kompendium.oas.security
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class BearerAuth(val bearerFormat: String? = null): SecuritySchema {
|
||||
val type: String = "http"
|
||||
val scheme: String = "bearer"
|
||||
}
|
57
oas/src/main/kotlin/io/bkbn/kompendium/oas/security/OAuth.kt
Normal file
57
oas/src/main/kotlin/io/bkbn/kompendium/oas/security/OAuth.kt
Normal file
@ -0,0 +1,57 @@
|
||||
package io.bkbn.kompendium.oas.security
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class OAuth(val description: String? = null, val flows: Flows) : SecuritySchema {
|
||||
val type: String = "oauth2"
|
||||
|
||||
@Serializable
|
||||
data class Flows(
|
||||
val implicit: Implicit? = null,
|
||||
val authorizationCode: AuthorizationCode? = null,
|
||||
val password: Password? = null,
|
||||
val clientCredentials: ClientCredential? = null,
|
||||
) {
|
||||
|
||||
sealed interface Flow {
|
||||
val authorizationUrl: String?
|
||||
get() = null
|
||||
val tokenUrl: String?
|
||||
get() = null
|
||||
val refreshUrl: String?
|
||||
get() = null
|
||||
val scopes: Map<String, String>
|
||||
get() = emptyMap()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class Implicit(
|
||||
override val authorizationUrl: String,
|
||||
override val refreshUrl: String? = null,
|
||||
override val scopes: Map<String, String> = emptyMap()
|
||||
) : Flow
|
||||
|
||||
@Serializable
|
||||
data class AuthorizationCode(
|
||||
override val authorizationUrl: String,
|
||||
override val tokenUrl: String? = null,
|
||||
override val refreshUrl: String? = null,
|
||||
override val scopes: Map<String, String> = emptyMap()
|
||||
) : Flow
|
||||
|
||||
@Serializable
|
||||
data class Password(
|
||||
override val tokenUrl: String? = null,
|
||||
override val refreshUrl: String? = null,
|
||||
override val scopes: Map<String, String> = emptyMap()
|
||||
) : Flow
|
||||
|
||||
@Serializable
|
||||
data class ClientCredential(
|
||||
override val tokenUrl: String? = null,
|
||||
override val refreshUrl: String? = null,
|
||||
override val scopes: Map<String, String> = emptyMap()
|
||||
) : Flow
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package io.bkbn.kompendium.oas.security
|
||||
|
||||
import io.bkbn.kompendium.oas.serialization.SecuritySchemaSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable(with = SecuritySchemaSerializer::class)
|
||||
sealed interface SecuritySchema
|
@ -0,0 +1,28 @@
|
||||
package io.bkbn.kompendium.oas.serialization
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlinx.serialization.InternalSerializationApi
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
import kotlinx.serialization.serializer
|
||||
|
||||
class AnySerializer<T : Any> : KSerializer<T> {
|
||||
override fun serialize(encoder: Encoder, value: T) {
|
||||
serialize(encoder, value, value::class as KClass<T>)
|
||||
}
|
||||
|
||||
override fun deserialize(decoder: Decoder): T {
|
||||
error("Abandon all hope ye who enter 💀")
|
||||
}
|
||||
|
||||
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("KompendiumAny", PrimitiveKind.STRING)
|
||||
|
||||
@OptIn(InternalSerializationApi::class)
|
||||
fun serialize(encoder: Encoder, obj: T, clazz: KClass<T>) {
|
||||
clazz.serializer().serialize(encoder, obj)
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package io.bkbn.kompendium.oas.serialization
|
||||
|
||||
import kotlinx.serialization.modules.SerializersModule
|
||||
|
||||
object KompendiumSerializersModule {
|
||||
val module = SerializersModule {
|
||||
contextual(Any::class, AnySerializer())
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package io.bkbn.kompendium.oas.serialization
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.SerializationException
|
||||
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
|
||||
object NumberSerializer : KSerializer<Number> {
|
||||
override fun deserialize(decoder: Decoder): Number = try {
|
||||
decoder.decodeDouble()
|
||||
} catch (_: SerializationException) {
|
||||
decoder.decodeInt()
|
||||
}
|
||||
|
||||
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Number", PrimitiveKind.DOUBLE)
|
||||
|
||||
override fun serialize(encoder: Encoder, value: Number) {
|
||||
when (value) {
|
||||
is Int -> encoder.encodeInt(value)
|
||||
is Double -> encoder.encodeDouble(value)
|
||||
else -> error("Invalid OpenApi Number $value")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package io.bkbn.kompendium.oas.serialization
|
||||
|
||||
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.bkbn.kompendium.oas.security.SecuritySchema
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.Serializer
|
||||
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
@Serializer(forClass = SecuritySchema::class)
|
||||
object SecuritySchemaSerializer : KSerializer<SecuritySchema> {
|
||||
override fun deserialize(decoder: Decoder): SecuritySchema {
|
||||
error("Abandon all hope ye who enter 💀")
|
||||
}
|
||||
|
||||
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("SecuritySchema", PrimitiveKind.STRING)
|
||||
|
||||
override fun serialize(encoder: Encoder, value: SecuritySchema) {
|
||||
when (value) {
|
||||
is ApiKeyAuth -> ApiKeyAuth.serializer().serialize(encoder, value)
|
||||
is BasicAuth -> BasicAuth.serializer().serialize(encoder, value)
|
||||
is BearerAuth -> BearerAuth.serializer().serialize(encoder, value)
|
||||
is OAuth -> OAuth.serializer().serialize(encoder, value)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package io.bkbn.kompendium.oas.serialization
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
import java.net.URI
|
||||
|
||||
object UriSerializer : KSerializer<URI> {
|
||||
override fun deserialize(decoder: Decoder): URI = URI.create(decoder.decodeString())
|
||||
|
||||
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("URI", PrimitiveKind.STRING)
|
||||
|
||||
override fun serialize(encoder: Encoder, value: URI) {
|
||||
encoder.encodeString(value.toString())
|
||||
}
|
||||
|
||||
}
|
25
oas/src/main/kotlin/io/bkbn/kompendium/oas/server/Server.kt
Normal file
25
oas/src/main/kotlin/io/bkbn/kompendium/oas/server/Server.kt
Normal file
@ -0,0 +1,25 @@
|
||||
package io.bkbn.kompendium.oas.server
|
||||
|
||||
import io.bkbn.kompendium.oas.serialization.UriSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.net.URI
|
||||
|
||||
/**
|
||||
* An object representing a Server.
|
||||
*
|
||||
* https://spec.openapis.org/oas/v3.1.0#server-object
|
||||
*
|
||||
* @param url A URL to the target host. This URL supports Server Variables and MAY be relative, to indicate that
|
||||
* the host location is relative to the location where the OpenAPI document is being served. Variable
|
||||
* substitutions will be made when a variable is named in {brackets}.
|
||||
* @param description An optional string describing the host designated by the URL.
|
||||
* @param variables A map between a variable name and its value.
|
||||
* The value is used for substitution in the server’s URL template.
|
||||
*/
|
||||
@Serializable
|
||||
data class Server(
|
||||
@Serializable(with = UriSerializer::class)
|
||||
val url: URI,
|
||||
val description: String? = null,
|
||||
var variables: Map<String, ServerVariable>? = null
|
||||
)
|
@ -0,0 +1,19 @@
|
||||
package io.bkbn.kompendium.oas.server
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* An object representing a Server Variable for server URL template substitution.
|
||||
*
|
||||
* https://spec.openapis.org/oas/v3.1.0#serverVariableObject
|
||||
*
|
||||
* @param enum An enumeration of string values to be used if the substitution options are from a limited set. The array MUST NOT be empty.
|
||||
* @param default The default value to use for substitution, which SHALL be sent if an alternate value is not supplied.
|
||||
* @param description An optional description for the server variable.
|
||||
*/
|
||||
@Serializable
|
||||
data class ServerVariable(
|
||||
val `enum`: Set<String>, // todo enforce not empty
|
||||
val default: String,
|
||||
val description: String?
|
||||
)
|
@ -0,0 +1,25 @@
|
||||
package io.bkbn.kompendium.oas.security
|
||||
|
||||
import io.kotest.core.spec.style.DescribeSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
private val json = Json { encodeDefaults = true }
|
||||
|
||||
class ApiKeyAuthTest : DescribeSpec({
|
||||
describe("ApiKeyAuth") {
|
||||
it("should produce correct json") {
|
||||
mapOf(
|
||||
ApiKeyAuth.ApiKeyLocation.HEADER to "header",
|
||||
ApiKeyAuth.ApiKeyLocation.COOKIE to "cookie",
|
||||
ApiKeyAuth.ApiKeyLocation.QUERY to "query",
|
||||
).forEach {
|
||||
val example = ApiKeyAuth(it.key, "test-name")
|
||||
|
||||
val json = json.encodeToString(ApiKeyAuth.serializer(), example)
|
||||
|
||||
json.shouldBe("""{"in":"${it.value}","name":"test-name","type":"apiKey"}""")
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
Reference in New Issue
Block a user