diff --git a/config/detekt.yml b/config/detekt.yml index 55ecdc4..db9252e 100644 --- a/config/detekt.yml +++ b/config/detekt.yml @@ -783,6 +783,6 @@ style: active: true ignoreLateinitVar: false WildcardImport: - active: true + active: false excludeImports: - 'java.util.*' diff --git a/src/main/kotlin/io/github/smiley4/ktorswaggerui/SwaggerPlugin.kt b/src/main/kotlin/io/github/smiley4/ktorswaggerui/SwaggerPlugin.kt index aadc05d..f019555 100644 --- a/src/main/kotlin/io/github/smiley4/ktorswaggerui/SwaggerPlugin.kt +++ b/src/main/kotlin/io/github/smiley4/ktorswaggerui/SwaggerPlugin.kt @@ -1,32 +1,9 @@ package io.github.smiley4.ktorswaggerui import com.fasterxml.jackson.databind.ObjectMapper -import io.github.smiley4.ktorswaggerui.dsl.SchemaType -import io.github.smiley4.ktorswaggerui.dsl.getSchemaType import io.github.smiley4.ktorswaggerui.spec.example.ExampleContext import io.github.smiley4.ktorswaggerui.spec.example.ExampleContextBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ComponentsBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ContactBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ContentBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ExampleBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ExternalDocumentationBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.HeaderBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.InfoBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.LicenseBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.OAuthFlowsBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.OpenApiBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.OperationBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.OperationTagsBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ParameterBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.PathBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.PathsBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.RequestBodyBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ResponseBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ResponsesBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.SecurityRequirementsBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.SecuritySchemesBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ServerBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.TagBuilder +import io.github.smiley4.ktorswaggerui.spec.openapi.* import io.github.smiley4.ktorswaggerui.spec.route.RouteCollector import io.github.smiley4.ktorswaggerui.spec.route.RouteDocumentationMerger import io.github.smiley4.ktorswaggerui.spec.route.RouteMeta @@ -34,18 +11,12 @@ import io.github.smiley4.ktorswaggerui.spec.schema.SchemaBuilder import io.github.smiley4.ktorswaggerui.spec.schema.SchemaContext import io.github.smiley4.ktorswaggerui.spec.schema.SchemaContextBuilder import io.github.smiley4.ktorswaggerui.spec.schema.TypeOverwrites -import io.ktor.server.application.Application -import io.ktor.server.application.ApplicationStarted -import io.ktor.server.application.createApplicationPlugin -import io.ktor.server.application.hooks.MonitoringEvent -import io.ktor.server.application.install -import io.ktor.server.application.plugin -import io.ktor.server.application.pluginOrNull -import io.ktor.server.routing.Routing -import io.ktor.server.webjars.Webjars +import io.ktor.server.application.* +import io.ktor.server.application.hooks.* +import io.ktor.server.routing.* +import io.ktor.server.webjars.* import io.swagger.v3.core.util.Json import mu.KotlinLogging -import java.io.File /** * This version must match the version of the gradle dependency @@ -112,9 +83,10 @@ private fun builder(config: SwaggerUIPluginConfig, schemaContext: SchemaContext, contactBuilder = ContactBuilder(), licenseBuilder = LicenseBuilder() ), + externalDocumentationBuilder = ExternalDocumentationBuilder(), serverBuilder = ServerBuilder(), tagBuilder = TagBuilder( - externalDocumentationBuilder = ExternalDocumentationBuilder() + tagExternalDocumentationBuilder = TagExternalDocumentationBuilder() ), pathsBuilder = PathsBuilder( pathBuilder = PathBuilder( diff --git a/src/main/kotlin/io/github/smiley4/ktorswaggerui/SwaggerUIPluginConfig.kt b/src/main/kotlin/io/github/smiley4/ktorswaggerui/SwaggerUIPluginConfig.kt index e5e549d..9059928 100644 --- a/src/main/kotlin/io/github/smiley4/ktorswaggerui/SwaggerUIPluginConfig.kt +++ b/src/main/kotlin/io/github/smiley4/ktorswaggerui/SwaggerUIPluginConfig.kt @@ -1,17 +1,8 @@ package io.github.smiley4.ktorswaggerui -import io.github.smiley4.ktorswaggerui.dsl.CustomSchemas -import io.github.smiley4.ktorswaggerui.dsl.EncodingConfig -import io.github.smiley4.ktorswaggerui.dsl.OpenApiDslMarker -import io.github.smiley4.ktorswaggerui.dsl.OpenApiInfo -import io.github.smiley4.ktorswaggerui.dsl.OpenApiResponse -import io.github.smiley4.ktorswaggerui.dsl.OpenApiSecurityScheme -import io.github.smiley4.ktorswaggerui.dsl.OpenApiServer -import io.github.smiley4.ktorswaggerui.dsl.OpenApiTag -import io.github.smiley4.ktorswaggerui.dsl.SwaggerUIDsl -import io.ktor.http.HttpMethod -import io.ktor.http.HttpStatusCode -import io.ktor.server.routing.RouteSelector +import io.github.smiley4.ktorswaggerui.dsl.* +import io.ktor.http.* +import io.ktor.server.routing.* import kotlin.reflect.KClass /** @@ -101,6 +92,18 @@ class SwaggerUIPluginConfig { fun getServers(): List = servers + /** + * OpenAPI external docs configuration - link and description of an external documentation + */ + fun externalDocs(block: OpenApiExternalDocs.() -> Unit) { + externalDocs = OpenApiExternalDocs().apply(block) + } + + private var externalDocs = OpenApiExternalDocs() + + fun getExternalDocs() = externalDocs + + /** * Defines security schemes that can be used by operations */ diff --git a/src/main/kotlin/io/github/smiley4/ktorswaggerui/dsl/OpenApiExternalDocs.kt b/src/main/kotlin/io/github/smiley4/ktorswaggerui/dsl/OpenApiExternalDocs.kt new file mode 100644 index 0000000..c1ce30d --- /dev/null +++ b/src/main/kotlin/io/github/smiley4/ktorswaggerui/dsl/OpenApiExternalDocs.kt @@ -0,0 +1,17 @@ +package io.github.smiley4.ktorswaggerui.dsl + +/** + * An object representing external documentation. + */ +@OpenApiDslMarker +class OpenApiExternalDocs { + /** + * A short description of the external documentation + */ + var description: String? = null + + /** + * A URL to the external documentation + */ + var url: String = "/" +} diff --git a/src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/ExternalDocumentationBuilder.kt b/src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/ExternalDocumentationBuilder.kt index 1a13a8d..7c463e4 100644 --- a/src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/ExternalDocumentationBuilder.kt +++ b/src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/ExternalDocumentationBuilder.kt @@ -1,14 +1,15 @@ package io.github.smiley4.ktorswaggerui.spec.openapi +import io.github.smiley4.ktorswaggerui.dsl.OpenApiExternalDocs import io.swagger.v3.oas.models.ExternalDocumentation - class ExternalDocumentationBuilder { - fun build(url: String, description: String): ExternalDocumentation = + fun build(externalDocs: OpenApiExternalDocs): ExternalDocumentation = ExternalDocumentation().also { - it.url = url - it.description = description + it.url = externalDocs.url + it.description = externalDocs.description } } + diff --git a/src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/OpenApiBuilder.kt b/src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/OpenApiBuilder.kt index 14e2142..0f1c694 100644 --- a/src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/OpenApiBuilder.kt +++ b/src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/OpenApiBuilder.kt @@ -11,6 +11,7 @@ class OpenApiBuilder( private val schemaContext: SchemaContext, private val exampleContext: ExampleContext, private val infoBuilder: InfoBuilder, + private val externalDocumentationBuilder: ExternalDocumentationBuilder, private val serverBuilder: ServerBuilder, private val tagBuilder: TagBuilder, private val pathsBuilder: PathsBuilder, @@ -20,6 +21,7 @@ class OpenApiBuilder( fun build(routes: Collection): OpenAPI { return OpenAPI().also { it.info = infoBuilder.build(config.getInfo()) + it.externalDocs = externalDocumentationBuilder.build(config.getExternalDocs()) it.servers = config.getServers().map { server -> serverBuilder.build(server) } it.tags = config.getTags().map { tag -> tagBuilder.build(tag) } it.paths = pathsBuilder.build(routes) diff --git a/src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/TagBuilder.kt b/src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/TagBuilder.kt index be878f0..60284d7 100644 --- a/src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/TagBuilder.kt +++ b/src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/TagBuilder.kt @@ -4,7 +4,7 @@ import io.github.smiley4.ktorswaggerui.dsl.OpenApiTag import io.swagger.v3.oas.models.tags.Tag class TagBuilder( - private val externalDocumentationBuilder: ExternalDocumentationBuilder + private val tagExternalDocumentationBuilder: TagExternalDocumentationBuilder ) { fun build(tag: OpenApiTag): Tag = @@ -12,7 +12,7 @@ class TagBuilder( it.name = tag.name it.description = tag.description if(tag.externalDocUrl != null && tag.externalDocDescription != null) { - it.externalDocs = externalDocumentationBuilder.build(tag.externalDocUrl!!, tag.externalDocDescription!!) + it.externalDocs = tagExternalDocumentationBuilder.build(tag.externalDocUrl!!, tag.externalDocDescription!!) } } diff --git a/src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/TagExternalDocumentationBuilder.kt b/src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/TagExternalDocumentationBuilder.kt new file mode 100644 index 0000000..805cd31 --- /dev/null +++ b/src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/TagExternalDocumentationBuilder.kt @@ -0,0 +1,12 @@ +package io.github.smiley4.ktorswaggerui.spec.openapi + +import io.swagger.v3.oas.models.ExternalDocumentation + +class TagExternalDocumentationBuilder { + + fun build(url: String, description: String): ExternalDocumentation = + ExternalDocumentation().also { + it.url = url + it.description = description + } +} diff --git a/src/test/kotlin/io/github/smiley4/ktorswaggerui/examples/CompleteExample.kt b/src/test/kotlin/io/github/smiley4/ktorswaggerui/examples/CompleteExample.kt index f9be583..6529215 100644 --- a/src/test/kotlin/io/github/smiley4/ktorswaggerui/examples/CompleteExample.kt +++ b/src/test/kotlin/io/github/smiley4/ktorswaggerui/examples/CompleteExample.kt @@ -66,6 +66,10 @@ private fun Application.myModule() { version = "latest" description = "Example API for testing and demonstration purposes." } + externalDocs { + url = "https://github.com/SMILEY4/ktor-swagger-ui/wiki" + description = "Sample external documentation object" + } server { url = "http://localhost:8080" description = "Development Server" diff --git a/src/test/kotlin/io/github/smiley4/ktorswaggerui/examples/CompletePluginConfigExample.kt b/src/test/kotlin/io/github/smiley4/ktorswaggerui/examples/CompletePluginConfigExample.kt index f92a416..539b90d 100644 --- a/src/test/kotlin/io/github/smiley4/ktorswaggerui/examples/CompletePluginConfigExample.kt +++ b/src/test/kotlin/io/github/smiley4/ktorswaggerui/examples/CompletePluginConfigExample.kt @@ -66,6 +66,10 @@ private fun Application.myModule() { url = "example.com/license" } } + externalDocs { + url = "https://docs.example.com" + description = "Example external documentation description" + } server { url = "localhost:8080" description = "develop server" diff --git a/src/test/kotlin/io/github/smiley4/ktorswaggerui/tests/openapi/ExternalDocsBuilderTest.kt b/src/test/kotlin/io/github/smiley4/ktorswaggerui/tests/openapi/ExternalDocsBuilderTest.kt new file mode 100644 index 0000000..2213852 --- /dev/null +++ b/src/test/kotlin/io/github/smiley4/ktorswaggerui/tests/openapi/ExternalDocsBuilderTest.kt @@ -0,0 +1,38 @@ +package io.github.smiley4.ktorswaggerui.tests.openapi + +import io.github.smiley4.ktorswaggerui.dsl.OpenApiExternalDocs +import io.github.smiley4.ktorswaggerui.spec.openapi.ExternalDocumentationBuilder +import io.kotest.core.spec.style.StringSpec +import io.kotest.matchers.shouldBe +import io.swagger.v3.oas.models.ExternalDocumentation + +class ExternalDocsBuilderTest : StringSpec({ + + "default external docs object" { + buildExternalDocsObject {}.also { docs -> + docs.url shouldBe "/" + docs.description shouldBe null + } + } + + "complete server object" { + buildExternalDocsObject { + url = "Test URL" + description = "Test Description" + }.also { docs -> + docs.url shouldBe "Test URL" + docs.description shouldBe "Test Description" + } + } + +}) { + + companion object { + + private fun buildExternalDocsObject(builder: OpenApiExternalDocs.() -> Unit): ExternalDocumentation { + return ExternalDocumentationBuilder().build(OpenApiExternalDocs().apply(builder)) + } + + } + +} diff --git a/src/test/kotlin/io/github/smiley4/ktorswaggerui/tests/openapi/OpenApiBuilderTest.kt b/src/test/kotlin/io/github/smiley4/ktorswaggerui/tests/openapi/OpenApiBuilderTest.kt index 9713ab6..b63df8e 100644 --- a/src/test/kotlin/io/github/smiley4/ktorswaggerui/tests/openapi/OpenApiBuilderTest.kt +++ b/src/test/kotlin/io/github/smiley4/ktorswaggerui/tests/openapi/OpenApiBuilderTest.kt @@ -4,28 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper import io.github.smiley4.ktorswaggerui.SwaggerUIPluginConfig import io.github.smiley4.ktorswaggerui.spec.example.ExampleContext import io.github.smiley4.ktorswaggerui.spec.example.ExampleContextBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ComponentsBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ContactBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ContentBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ExampleBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ExternalDocumentationBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.HeaderBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.InfoBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.LicenseBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.OAuthFlowsBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.OpenApiBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.OperationBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.OperationTagsBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ParameterBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.PathBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.PathsBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.RequestBodyBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ResponseBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ResponsesBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.SecurityRequirementsBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.SecuritySchemesBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.ServerBuilder -import io.github.smiley4.ktorswaggerui.spec.openapi.TagBuilder +import io.github.smiley4.ktorswaggerui.spec.openapi.* import io.github.smiley4.ktorswaggerui.spec.route.RouteMeta import io.github.smiley4.ktorswaggerui.spec.schema.SchemaBuilder import io.github.smiley4.ktorswaggerui.spec.schema.SchemaContext @@ -47,6 +26,7 @@ class OpenApiBuilderTest : StringSpec({ openapi.info shouldNotBe null openapi.extensions shouldBe null openapi.servers shouldHaveSize 0 + openapi.externalDocs shouldNotBe null openapi.security shouldBe null openapi.tags shouldHaveSize 0 openapi.paths shouldHaveSize 0 @@ -130,9 +110,10 @@ class OpenApiBuilderTest : StringSpec({ contactBuilder = ContactBuilder(), licenseBuilder = LicenseBuilder() ), + externalDocumentationBuilder = ExternalDocumentationBuilder(), serverBuilder = ServerBuilder(), tagBuilder = TagBuilder( - externalDocumentationBuilder = ExternalDocumentationBuilder() + tagExternalDocumentationBuilder = TagExternalDocumentationBuilder() ), pathsBuilder = PathsBuilder( pathBuilder = PathBuilder( diff --git a/src/test/kotlin/io/github/smiley4/ktorswaggerui/tests/openapi/TagsBuilderTest.kt b/src/test/kotlin/io/github/smiley4/ktorswaggerui/tests/openapi/TagsBuilderTest.kt index d706682..bc2f335 100644 --- a/src/test/kotlin/io/github/smiley4/ktorswaggerui/tests/openapi/TagsBuilderTest.kt +++ b/src/test/kotlin/io/github/smiley4/ktorswaggerui/tests/openapi/TagsBuilderTest.kt @@ -1,8 +1,8 @@ package io.github.smiley4.ktorswaggerui.tests.openapi import io.github.smiley4.ktorswaggerui.dsl.OpenApiTag -import io.github.smiley4.ktorswaggerui.spec.openapi.ExternalDocumentationBuilder import io.github.smiley4.ktorswaggerui.spec.openapi.TagBuilder +import io.github.smiley4.ktorswaggerui.spec.openapi.TagExternalDocumentationBuilder import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe @@ -45,7 +45,7 @@ class TagsBuilderTest : StringSpec({ private fun buildTagObject(name: String, builder: OpenApiTag.() -> Unit): Tag { return TagBuilder( - externalDocumentationBuilder = ExternalDocumentationBuilder() + tagExternalDocumentationBuilder = TagExternalDocumentationBuilder() ).build(OpenApiTag(name).apply(builder)) }