Skip to content

Commit

Permalink
cleanup, documentation, set version 3.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
SMILEY4 committed Jun 9, 2024
1 parent 48faa19 commit 0535620
Show file tree
Hide file tree
Showing 73 changed files with 320 additions and 35 deletions.
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ This library provides a Ktor plugin to document routes, generate an OpenApi Spec
## Features

- minimally invasive (no immediate change to existing code required)
- provides swagger-ui with no initial configuration required
- supports most of the [OpenAPI 3.0.3 Specification](https://swagger.io/specification/)
- automatic json-schema generation from arbitrary types/classes for bodies and parameters
- use custom encoder/serializers for examples and json-schemas
- provide custom schemas or a custom schema-builder
- external/custom json-schemas for bodies
- protect Swagger-UI and OpenApi-Spec with custom authentication
- provides swagger-ui and openapi-spec with minimal configuration
- supports most of the [OpenAPI 3.1.0 Specification](https://swagger.io/specification/)
- automatic [json-schema generation](https://github.com/SMILEY4/schema-kenerator) from arbitrary types/classes for bodies and parameters
- supports generics, inheritance, collections, ...
- support for Jackson-annotations and swagger Schema-annotations (optional)
- use with reflection or kotlinx-serialization
- customizable schema-generation


## Documentation
Expand All @@ -32,8 +32,10 @@ dependencies {
```


## Example
Full examples can be found in [src/test/examples](https://github.com/SMILEY4/ktor-swagger-ui/tree/develop/src/test/kotlin/io/github/smiley4/ktorswaggerui/examples).
## Examples

Runnable examples can be found in [ktor-swagger-ui-examples/src/main/kotlin/io/github/smiley4/ktorswaggerui/examples](https://github.com/SMILEY4/ktor-swagger-ui/tree/release/ktor-swagger-ui-examples/src/main/kotlin/io/github/smiley4/ktorswaggerui/examples).


### Configuration

Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ kotlin.code.style=official
# project id
projectGroupId=io.github.smiley4
projectArtifactIdBase=ktor-swagger-ui
projectVersion=3.0.0-beta3
projectVersion=3.0.0

# publishing information
projectNameBase=Ktor Swagger UI
Expand All @@ -19,7 +19,7 @@ projectDeveloperUrl=https://github.com/SMILEY4
versionKtor=2.3.11
versionSwaggerUI=5.17.11
versionSwaggerParser=2.1.22
versionSchemaKenerator=0.4.0
versionSchemaKenerator=1.0.0
versionKotlinLogging=3.0.5
versionKotest=5.8.0
versionKotlinTest=1.8.21
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ private fun buildOpenApiSpec(pluginConfig: PluginConfigData, routes: List<RouteM
it.add(routes)
}
val exampleContext = ExampleContextImpl().also {
it.addGlobal(pluginConfig.exampleConfig)
it.addShared(pluginConfig.exampleConfig)
it.add(routes)
}
val openApi = builder(pluginConfig, schemaContext, exampleContext).build(routes)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,19 @@ package io.github.smiley4.ktorswaggerui.builder.example
import io.github.smiley4.ktorswaggerui.data.ExampleDescriptor
import io.swagger.v3.oas.models.examples.Example

/**
* Provides examples for an openapi-spec
*/
interface ExampleContext {

/**
* Get an [Example] (or a ref to an example) by its [ExampleDescriptor]
*/
fun getExample(descriptor: ExampleDescriptor): Example


/**
* Get all examples placed in the components-section of the spec.
*/
fun getComponentSection(): Map<String, Example>
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,39 @@ import io.github.smiley4.ktorswaggerui.data.SwaggerExampleDescriptor
import io.github.smiley4.ktorswaggerui.data.ValueExampleDescriptor
import io.swagger.v3.oas.models.examples.Example

/**
* Implementation of an [ExampleContext].
*/
class ExampleContextImpl : ExampleContext {

private val rootExamples = mutableMapOf<ExampleDescriptor, Example>()
private val componentExamples = mutableMapOf<String, Example>()

fun addGlobal(config: ExampleConfigData) {

/**
* Add all global/shared examples from the config that are placed in the components-section of the openapi-spec
*/
fun addShared(config: ExampleConfigData) {
config.sharedExamples.forEach { (_, exampleDescriptor) ->
val example = generateExample(exampleDescriptor)
componentExamples[exampleDescriptor.name] = example
}
}


/**
* Collect and add all examples for the given routes
*/
fun add(routes: Collection<RouteMeta>) {
collectExampleDescriptors(routes).forEach { exampleDescriptor ->
rootExamples[exampleDescriptor] = generateExample(exampleDescriptor)
}
}


/**
* Collect all [ExampleDescriptor]s from the given routes
*/
private fun collectExampleDescriptors(routes: Collection<RouteMeta>): List<ExampleDescriptor> {
val descriptors = mutableListOf<ExampleDescriptor>()
routes
Expand All @@ -53,6 +68,10 @@ class ExampleContextImpl : ExampleContext {
return descriptors
}


/**
* Generate a swagger [Example] from the given [ExampleDescriptor]
*/
private fun generateExample(exampleDescriptor: ExampleDescriptor): Example {
return when (exampleDescriptor) {
is ValueExampleDescriptor -> Example().also {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import io.swagger.v3.oas.models.Components
import io.swagger.v3.oas.models.examples.Example
import io.swagger.v3.oas.models.media.Schema

/**
* Builds the openapi [Components]-object containing shared reusable schemas and examples.
* See [OpenAPI Specification - Components Object](https://swagger.io/specification/#components-object).
*/
class ComponentsBuilder(
private val config: PluginConfigData,
private val securitySchemesBuilder: SecuritySchemesBuilder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package io.github.smiley4.ktorswaggerui.builder.openapi
import io.github.smiley4.ktorswaggerui.data.ContactData
import io.swagger.v3.oas.models.info.Contact

/**
* Builds the openapi [Contact]-object. Holds Contact information for the exposed API.
* See [OpenAPI Specification - Contact Object](https://swagger.io/specification/#contact-object).
*/
class ContactBuilder {

fun build(contact: ContactData): Contact =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ import io.swagger.v3.oas.models.media.MediaType
import io.swagger.v3.oas.models.media.Schema
import kotlin.collections.set

/**
* Builds the openapi [Content]-object for request and response bodies.
* See [OpenAPI Specification - Request Body Object](https://swagger.io/specification/#request-body-object)
* and [OpenAPI Specification - Response Object](https://swagger.io/specification/#response-object).
*/
class ContentBuilder(
private val schemaContext: SchemaContext,
private val exampleContext: ExampleContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package io.github.smiley4.ktorswaggerui.builder.openapi
import io.github.smiley4.ktorswaggerui.data.ExternalDocsData
import io.swagger.v3.oas.models.ExternalDocumentation

/**
* Build the openapi [ExternalDocumentation]-object. Allows referencing an external resource for extended documentation.
* See [OpenAPI Specification - External Documentation Object](https://swagger.io/specification/#external-documentation-object).
*/
class ExternalDocumentationBuilder {

fun build(externalDocs: ExternalDocsData): ExternalDocumentation =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ package io.github.smiley4.ktorswaggerui.builder.openapi

import io.github.smiley4.ktorswaggerui.builder.schema.SchemaContext
import io.github.smiley4.ktorswaggerui.data.OpenApiHeaderData
import io.swagger.v3.oas.models.ExternalDocumentation
import io.swagger.v3.oas.models.headers.Header

/**
* Build the openapi [Header]-object.
* See [OpenAPI Specification - Header Object](https://swagger.io/specification/#header-object).
*/
class HeaderBuilder(
private val schemaContext: SchemaContext
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package io.github.smiley4.ktorswaggerui.builder.openapi
import io.github.smiley4.ktorswaggerui.data.InfoData
import io.swagger.v3.oas.models.info.Info

/**
* Build the openapi [Info]-object. Holds metadata about the API.
* See [OpenAPI Specification - Info Object](https://swagger.io/specification/#info-object).
*/
class InfoBuilder(
private val contactBuilder: ContactBuilder,
private val licenseBuilder: LicenseBuilder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package io.github.smiley4.ktorswaggerui.builder.openapi
import io.github.smiley4.ktorswaggerui.data.LicenseData
import io.swagger.v3.oas.models.info.License

/**
* Build the openapi [License]-object. Holds license information for the exposed API.
* See [OpenAPI Specification - License Object](https://swagger.io/specification/#license-object).
*/
class LicenseBuilder {

fun build(license: LicenseData): License =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import io.swagger.v3.oas.models.security.OAuthFlow
import io.swagger.v3.oas.models.security.OAuthFlows
import io.swagger.v3.oas.models.security.Scopes

/**
* Build the openapi [OAuthFlows]-object. Holds configuration of the supported OAuth Flows.
* See [OpenAPI Specification - OAuth Flows Object](https://swagger.io/specification/#oauth-flows-object).
*/
class OAuthFlowsBuilder {

fun build(flows: OpenIdOAuthFlowsData): OAuthFlows {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import io.github.smiley4.ktorswaggerui.builder.schema.SchemaContext
import io.swagger.v3.oas.models.OpenAPI
import io.swagger.v3.oas.models.SpecVersion

/**
* Build the openapi [OpenAPI]-object. Is the root of the openapi document.
* See [OpenAPI Specification - OpenAPI Object](https://swagger.io/specification/#openapi-object).
*/
class OpenApiBuilder(
private val config: PluginConfigData,
private val schemaContext: SchemaContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package io.github.smiley4.ktorswaggerui.builder.openapi
import io.github.smiley4.ktorswaggerui.builder.route.RouteMeta
import io.swagger.v3.oas.models.Operation

/**
* Build the openapi [Operation]-object. Holds information describing a single API operation on a path.
* See [OpenAPI Specification - Operation Object](https://swagger.io/specification/#operation-object).
*/
class OperationBuilder(
private val operationTagsBuilder: OperationTagsBuilder,
private val parameterBuilder: ParameterBuilder,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package io.github.smiley4.ktorswaggerui.builder.openapi
import io.github.smiley4.ktorswaggerui.data.PluginConfigData
import io.github.smiley4.ktorswaggerui.builder.route.RouteMeta

/**
* Builds the list of tags for a single route.
*/
class OperationTagsBuilder(
private val config: PluginConfigData
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import io.github.smiley4.ktorswaggerui.data.OpenApiRequestParameterData
import io.github.smiley4.ktorswaggerui.data.ParameterLocation
import io.swagger.v3.oas.models.parameters.Parameter

/**
* Build the openapi [Parameter]-object. Holds information describing a single operation (query, path or header) parameter.
* See [OpenAPI Specification - Parameter Object](https://swagger.io/specification/#parameter-object).
*/
class ParameterBuilder(
private val schemaContext: SchemaContext,
private val exampleContext: ExampleContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import io.github.smiley4.ktorswaggerui.builder.route.RouteMeta
import io.ktor.http.HttpMethod
import io.swagger.v3.oas.models.PathItem

/**
* Build the openapi [PathItem]-object. Holds information describing the operations available on a single path.
* See [OpenAPI Specification - Path Item Object](https://swagger.io/specification/#path-item-object).
*/
class PathBuilder(
private val operationBuilder: OperationBuilder
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import io.github.smiley4.ktorswaggerui.builder.route.RouteMeta
import io.swagger.v3.oas.models.PathItem
import io.swagger.v3.oas.models.Paths

/**
* Build the openapi [Paths]-object. Holds the relative paths to the individual endpoints and their operations.
* See [OpenAPI Specification - Paths Object](https://swagger.io/specification/#paths-object).
*/
class PathsBuilder(
private val pathBuilder: PathBuilder
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package io.github.smiley4.ktorswaggerui.builder.openapi
import io.github.smiley4.ktorswaggerui.data.OpenApiBaseBodyData
import io.swagger.v3.oas.models.parameters.RequestBody

/**
* Build the openapi [RequestBody]-object. Holds information describing a single request body.
* See [OpenAPI Specification - Request Body Object](https://swagger.io/specification/#request-body-object).
*/
class RequestBodyBuilder(
private val contentBuilder: ContentBuilder
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package io.github.smiley4.ktorswaggerui.builder.openapi
import io.github.smiley4.ktorswaggerui.data.OpenApiResponseData
import io.swagger.v3.oas.models.responses.ApiResponse

/**
* Build the openapi [ApiResponse]-objects by status-code. Holds information describing status-codes and responses from an API Operation.
* See [OpenAPI Specification - Response Object](https://swagger.io/specification/#response-object).
*/
class ResponseBuilder(
private val headerBuilder: HeaderBuilder,
private val contentBuilder: ContentBuilder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import io.github.smiley4.ktorswaggerui.data.PluginConfigData
import io.ktor.http.HttpStatusCode
import io.swagger.v3.oas.models.responses.ApiResponses

/**
* Build the openapi [ApiResponses]-object. A container for the expected responses of an operation.
* See [OpenAPI Specification - Responses Object](https://swagger.io/specification/#responses-object).
*/
class ResponsesBuilder(
private val responseBuilder: ResponseBuilder,
private val config: PluginConfigData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@ import io.github.smiley4.ktorswaggerui.builder.route.RouteMeta
import io.github.smiley4.ktorswaggerui.data.PluginConfigData
import io.swagger.v3.oas.models.security.SecurityRequirement

/**
* Build the openapi [SecurityRequirement]-objects.
* See [OpenAPI Specification - Security Requirement Object](https://swagger.io/specification/#security-requirement-object).
*/
class SecurityRequirementsBuilder(
private val config: PluginConfigData
) {

fun build(route: RouteMeta): List<SecurityRequirement> {
val securitySchemes = buildSet {
return buildSet {
addAll(route.documentation.securitySchemeNames)
if(route.documentation.securitySchemeNames.isEmpty()) {
addAll(config.securityConfig.defaultSecuritySchemeNames)
}
}
return securitySchemes.map {
}.map {
SecurityRequirement().apply {
addList(it, emptyList())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import io.github.smiley4.ktorswaggerui.data.AuthType
import io.github.smiley4.ktorswaggerui.data.SecuritySchemeData
import io.swagger.v3.oas.models.security.SecurityScheme

/**
* Build the openapi [SecurityScheme]-objects with their names. Holds information defining security schemes that can be used by operations.
* See [OpenAPI Specification - Security Scheme Object](https://swagger.io/specification/#security-scheme-object).
*/
class SecuritySchemesBuilder(
private val oAuthFlowsBuilder: OAuthFlowsBuilder
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import io.swagger.v3.oas.models.servers.Server
import io.swagger.v3.oas.models.servers.ServerVariable
import io.swagger.v3.oas.models.servers.ServerVariables

/**
* Build the openapi [Server]-object. Holds information representing a Server.
* See [OpenAPI Specification - Server Object](https://swagger.io/specification/#server-object).
*/
class ServerBuilder {

fun build(server: ServerData): Server =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package io.github.smiley4.ktorswaggerui.builder.openapi
import io.github.smiley4.ktorswaggerui.data.TagData
import io.swagger.v3.oas.models.tags.Tag

/**
* Build the openapi [Tag]-object. Holds metadata of a single tag.
* See [OpenAPI Specification - Tag Object](https://swagger.io/specification/#tag-object).
*/
class TagBuilder(
private val tagExternalDocumentationBuilder: TagExternalDocumentationBuilder
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package io.github.smiley4.ktorswaggerui.builder.openapi

import io.swagger.v3.oas.models.ExternalDocumentation

/**
* Build the openapi [ExternalDocumentation]-object for a tag.
* See [OpenAPI Specification - External Documentation Object](https://swagger.io/specification/#external-documentation-object).
*/
class TagExternalDocumentationBuilder {

fun build(url: String, description: String): ExternalDocumentation =
Expand Down
Loading

0 comments on commit 0535620

Please sign in to comment.