breaking change: V3 alpha (#256)

This commit is contained in:
Ryan Brink
2022-08-13 09:59:59 -07:00
committed by GitHub
parent 48969a8fcc
commit c73c9b4605
308 changed files with 5410 additions and 10204 deletions

55
oas/Module.md Normal file
View 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
View 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()
}
}
}

View 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
)

View File

@ -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?
)

View 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
)

View File

@ -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()
)

View 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
)

View 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,
)

View 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
)

View 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
)

View File

@ -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,
)

View File

@ -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
)

View 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
)

View 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
)

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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
)

View File

@ -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
)

View File

@ -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");
}
}

View File

@ -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"
}

View File

@ -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"
}

View 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
}
}

View File

@ -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

View File

@ -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)
}
}

View File

@ -0,0 +1,9 @@
package io.bkbn.kompendium.oas.serialization
import kotlinx.serialization.modules.SerializersModule
object KompendiumSerializersModule {
val module = SerializersModule {
contextual(Any::class, AnySerializer())
}
}

View File

@ -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")
}
}
}

View File

@ -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)
}
}
}

View File

@ -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())
}
}

View 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 servers URL template.
*/
@Serializable
data class Server(
@Serializable(with = UriSerializer::class)
val url: URI,
val description: String? = null,
var variables: Map<String, ServerVariable>? = null
)

View File

@ -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?
)

View File

@ -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"}""")
}
}
}
})