Skip to content

Commit 5cd81b9

Browse files
committed
Merge branch 'develop' into release
2 parents 1637a52 + 0cf2fa9 commit 5cd81b9

File tree

22 files changed

+594
-310
lines changed

22 files changed

+594
-310
lines changed

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ plugins {
88
}
99

1010
group = "io.github.smiley4"
11-
version = "2.0.0-rc.2"
11+
version = "2.0.0-rc.3"
1212

1313
repositories {
1414
mavenCentral()

src/main/kotlin/io/github/smiley4/ktorswaggerui/SwaggerPlugin.kt

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import io.github.smiley4.ktorswaggerui.spec.openapi.SecurityRequirementsBuilder
2222
import io.github.smiley4.ktorswaggerui.spec.openapi.SecuritySchemesBuilder
2323
import io.github.smiley4.ktorswaggerui.spec.openapi.ServerBuilder
2424
import io.github.smiley4.ktorswaggerui.spec.openapi.TagBuilder
25+
import io.github.smiley4.ktorswaggerui.spec.example.ExampleContext
26+
import io.github.smiley4.ktorswaggerui.spec.example.ExampleContextBuilder
2527
import io.github.smiley4.ktorswaggerui.spec.route.RouteCollector
2628
import io.github.smiley4.ktorswaggerui.spec.route.RouteDocumentationMerger
2729
import io.github.smiley4.ktorswaggerui.spec.route.RouteMeta
@@ -52,8 +54,9 @@ val SwaggerUI = createApplicationPlugin(name = "SwaggerUI", createConfiguration
5254
}
5355
val routes = routes(application, pluginConfig)
5456
val schemaContext = schemaContext(pluginConfig, routes)
57+
val exampleContext = exampleContext(pluginConfig, routes)
5558
try {
56-
apiSpecJson = Json.pretty(builder(pluginConfig, schemaContext).build(routes))
59+
apiSpecJson = Json.pretty(builder(pluginConfig, schemaContext, exampleContext).build(routes))
5760
} catch (e: Exception) {
5861
e.printStackTrace()
5962
}
@@ -81,10 +84,20 @@ private fun schemaContext(pluginConfig: SwaggerUIPluginConfig, routes: List<Rout
8184
).build(routes.toList())
8285
}
8386

84-
private fun builder(config: SwaggerUIPluginConfig, schemaContext: SchemaContext): OpenApiBuilder {
87+
private fun exampleContext(pluginConfig: SwaggerUIPluginConfig, routes: List<RouteMeta>): ExampleContext {
88+
return ExampleContextBuilder(
89+
config = pluginConfig,
90+
exampleBuilder = ExampleBuilder(
91+
config = pluginConfig
92+
)
93+
).build(routes.toList())
94+
}
95+
96+
private fun builder(config: SwaggerUIPluginConfig, schemaContext: SchemaContext, exampleContext: ExampleContext): OpenApiBuilder {
8597
return OpenApiBuilder(
8698
config = config,
8799
schemaContext = schemaContext,
100+
exampleContext = exampleContext,
88101
infoBuilder = InfoBuilder(
89102
contactBuilder = ContactBuilder(),
90103
licenseBuilder = LicenseBuilder()
@@ -97,13 +110,14 @@ private fun builder(config: SwaggerUIPluginConfig, schemaContext: SchemaContext)
97110
pathBuilder = PathBuilder(
98111
operationBuilder = OperationBuilder(
99112
operationTagsBuilder = OperationTagsBuilder(config),
100-
parameterBuilder = ParameterBuilder(schemaContext),
113+
parameterBuilder = ParameterBuilder(
114+
schemaContext = schemaContext,
115+
exampleContext = exampleContext
116+
),
101117
requestBodyBuilder = RequestBodyBuilder(
102118
contentBuilder = ContentBuilder(
103119
schemaContext = schemaContext,
104-
exampleBuilder = ExampleBuilder(
105-
config = config
106-
),
120+
exampleContext = exampleContext,
107121
headerBuilder = HeaderBuilder(schemaContext)
108122
)
109123
),
@@ -112,9 +126,7 @@ private fun builder(config: SwaggerUIPluginConfig, schemaContext: SchemaContext)
112126
headerBuilder = HeaderBuilder(schemaContext),
113127
contentBuilder = ContentBuilder(
114128
schemaContext = schemaContext,
115-
exampleBuilder = ExampleBuilder(
116-
config = config
117-
),
129+
exampleContext = exampleContext,
118130
headerBuilder = HeaderBuilder(schemaContext)
119131
)
120132
),

src/main/kotlin/io/github/smiley4/ktorswaggerui/SwaggerUIPluginConfig.kt

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
package io.github.smiley4.ktorswaggerui
22

3-
import io.github.smiley4.ktorswaggerui.dsl.*
4-
import io.ktor.http.*
5-
import io.ktor.server.routing.*
3+
import io.github.smiley4.ktorswaggerui.dsl.CustomSchemas
4+
import io.github.smiley4.ktorswaggerui.dsl.EncodingConfig
5+
import io.github.smiley4.ktorswaggerui.dsl.OpenApiDslMarker
6+
import io.github.smiley4.ktorswaggerui.dsl.OpenApiInfo
7+
import io.github.smiley4.ktorswaggerui.dsl.OpenApiResponse
8+
import io.github.smiley4.ktorswaggerui.dsl.OpenApiSecurityScheme
9+
import io.github.smiley4.ktorswaggerui.dsl.OpenApiServer
10+
import io.github.smiley4.ktorswaggerui.dsl.OpenApiTag
11+
import io.github.smiley4.ktorswaggerui.dsl.SwaggerUIDsl
12+
import io.ktor.http.HttpMethod
13+
import io.ktor.http.HttpStatusCode
14+
import io.ktor.server.routing.RouteSelector
615
import kotlin.reflect.KClass
716

817
/**
@@ -36,13 +45,6 @@ class SwaggerUIPluginConfig {
3645
var defaultSecuritySchemeNames: Collection<String>? = null
3746

3847

39-
/**
40-
* function to generate a tag from the given url for a path. Result will be added to the tags defined for each path
41-
*/
42-
@Deprecated("use 'generateTags' instead")
43-
var automaticTagGenerator: ((url: List<String>) -> String?)? = null
44-
45-
4648
/**
4749
* Automatically add tags to the route with the given url.
4850
* The returned (non-null) tags will be added to the tags specified in the route-specific documentation.

src/main/kotlin/io/github/smiley4/ktorswaggerui/dsl/EncodingConfig.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class EncodingConfig {
7171
/**
7272
* encode the given value to a json string
7373
*/
74-
fun encodeExample(value: Any): String {
74+
fun encodeExample(value: Any?): String {
7575
return if (value is String) {
7676
value
7777
} else {

src/main/kotlin/io/github/smiley4/ktorswaggerui/dsl/SchemaType.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package io.github.smiley4.ktorswaggerui.dsl
33
import kotlin.reflect.KClass
44
import kotlin.reflect.KType
55
import kotlin.reflect.full.starProjectedType
6-
import kotlin.reflect.javaType
76
import kotlin.reflect.typeOf
87

98
typealias SchemaType = KType
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package io.github.smiley4.ktorswaggerui.spec.example
2+
3+
import io.github.smiley4.ktorswaggerui.dsl.OpenApiRequestParameter
4+
import io.github.smiley4.ktorswaggerui.dsl.OpenApiSimpleBody
5+
import io.swagger.v3.oas.models.examples.Example
6+
7+
class ExampleContext {
8+
9+
private val examplesParameters = mutableMapOf<OpenApiRequestParameter, String>()
10+
private val examplesBody = mutableMapOf<Pair<OpenApiSimpleBody, String>, Example>()
11+
12+
fun addExample(parameter: OpenApiRequestParameter, value: String) {
13+
examplesParameters[parameter] = value
14+
}
15+
16+
fun addExample(body: OpenApiSimpleBody, name: String, value: Example) {
17+
examplesBody[body to name] = value
18+
}
19+
20+
fun getComponentsSection(): Map<String, Example> = emptyMap()
21+
22+
fun getExample(parameter: OpenApiRequestParameter): String? = examplesParameters[parameter]
23+
24+
fun getExample(body: OpenApiSimpleBody, name: String): Example? = examplesBody[body to name]
25+
26+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package io.github.smiley4.ktorswaggerui.spec.example
2+
3+
import io.github.smiley4.ktorswaggerui.SwaggerUIPluginConfig
4+
import io.github.smiley4.ktorswaggerui.dsl.OpenApiBaseBody
5+
import io.github.smiley4.ktorswaggerui.dsl.OpenApiExample
6+
import io.github.smiley4.ktorswaggerui.dsl.OpenApiRequestParameter
7+
import io.github.smiley4.ktorswaggerui.dsl.OpenApiResponse
8+
import io.github.smiley4.ktorswaggerui.dsl.OpenApiSimpleBody
9+
import io.github.smiley4.ktorswaggerui.dsl.SchemaType
10+
import io.github.smiley4.ktorswaggerui.dsl.getSchemaType
11+
import io.github.smiley4.ktorswaggerui.spec.openapi.ExampleBuilder
12+
import io.github.smiley4.ktorswaggerui.spec.route.RouteMeta
13+
import io.swagger.v3.oas.models.examples.Example
14+
15+
class ExampleContextBuilder(
16+
private val config: SwaggerUIPluginConfig,
17+
private val exampleBuilder: ExampleBuilder
18+
) {
19+
20+
fun build(routes: Collection<RouteMeta>): ExampleContext {
21+
return ExampleContext()
22+
.also { ctx -> routes.forEach { handle(ctx, it) } }
23+
}
24+
25+
26+
private fun handle(ctx: ExampleContext, route: RouteMeta) {
27+
route.documentation.getRequest().getBody()?.also { handle(ctx, it) }
28+
route.documentation.getRequest().getParameters().forEach { handle(ctx, it) }
29+
route.documentation.getResponses().getResponses().forEach { handle(ctx, it) }
30+
}
31+
32+
private fun handle(ctx: ExampleContext, response: OpenApiResponse) {
33+
response.getBody()?.also { handle(ctx, it) }
34+
}
35+
36+
37+
private fun handle(ctx: ExampleContext, body: OpenApiBaseBody) {
38+
return when (body) {
39+
is OpenApiSimpleBody -> handle(ctx, body)
40+
else -> Unit
41+
}
42+
}
43+
44+
45+
private fun handle(ctx: ExampleContext, body: OpenApiSimpleBody) {
46+
body.getExamples().forEach { (name, value) ->
47+
ctx.addExample(body, name, createExample(body.type ?: getSchemaType<String>(), value))
48+
}
49+
}
50+
51+
private fun handle(ctx: ExampleContext, parameter: OpenApiRequestParameter) {
52+
parameter.example?.also { example ->
53+
ctx.addExample(parameter, createExample(parameter.type, example))
54+
}
55+
}
56+
57+
private fun createExample(type: SchemaType?, value: Any): String {
58+
return exampleBuilder.buildExampleValue(type, value)
59+
}
60+
61+
private fun createExample(type: SchemaType?, example: OpenApiExample): Example {
62+
return exampleBuilder.build(type, example)
63+
}
64+
65+
}

src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/ComponentsBuilder.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@ package io.github.smiley4.ktorswaggerui.spec.openapi
22

33
import io.github.smiley4.ktorswaggerui.SwaggerUIPluginConfig
44
import io.swagger.v3.oas.models.Components
5+
import io.swagger.v3.oas.models.examples.Example
56
import io.swagger.v3.oas.models.media.Schema
67

78
class ComponentsBuilder(
89
private val config: SwaggerUIPluginConfig,
910
private val securitySchemesBuilder: SecuritySchemesBuilder
1011
) {
1112

12-
fun build(schemas: Map<String, Schema<*>>): Components {
13+
fun build(schemas: Map<String, Schema<*>>, examples: Map<String, Example>): Components {
1314
return Components().also {
1415
it.schemas = schemas
16+
it.examples = examples
1517
if (config.getSecuritySchemes().isNotEmpty()) {
1618
it.securitySchemes = securitySchemesBuilder.build(config.getSecuritySchemes())
1719
}

src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/ContentBuilder.kt

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
package io.github.smiley4.ktorswaggerui.spec.openapi
22

33
import io.github.smiley4.ktorswaggerui.dsl.OpenApiBaseBody
4-
import io.github.smiley4.ktorswaggerui.dsl.OpenApiExample
54
import io.github.smiley4.ktorswaggerui.dsl.OpenApiMultipartBody
65
import io.github.smiley4.ktorswaggerui.dsl.OpenApiSimpleBody
76
import io.github.smiley4.ktorswaggerui.dsl.OpenApiMultipartPart
8-
import io.github.smiley4.ktorswaggerui.dsl.SchemaType
7+
import io.github.smiley4.ktorswaggerui.spec.example.ExampleContext
98
import io.github.smiley4.ktorswaggerui.spec.schema.SchemaContext
109
import io.ktor.http.ContentType
1110
import io.swagger.v3.oas.models.media.Content
@@ -15,8 +14,6 @@ import io.swagger.v3.oas.models.media.Schema
1514
import kotlin.collections.Map
1615
import kotlin.collections.MutableMap
1716
import kotlin.collections.associateWith
18-
import kotlin.collections.component1
19-
import kotlin.collections.component2
2017
import kotlin.collections.filter
2118
import kotlin.collections.flatMap
2219
import kotlin.collections.forEach
@@ -30,7 +27,7 @@ import kotlin.collections.setOf
3027

3128
class ContentBuilder(
3229
private val schemaContext: SchemaContext,
33-
private val exampleBuilder: ExampleBuilder,
30+
private val exampleContext: ExampleContext,
3431
private val headerBuilder: HeaderBuilder
3532
) {
3633

@@ -57,14 +54,15 @@ class ContentBuilder(
5754

5855
private fun buildSimpleMediaTypes(body: OpenApiSimpleBody, schema: Schema<*>?): Map<ContentType, MediaType> {
5956
val mediaTypes = body.getMediaTypes().ifEmpty { schema?.let { setOf(chooseMediaType(schema)) } ?: setOf() }
60-
return mediaTypes.associateWith { buildSimpleMediaType(schema, body.type, body.getExamples()) }
57+
return mediaTypes.associateWith { buildSimpleMediaType(schema, body) }
6158
}
6259

63-
private fun buildSimpleMediaType(schema: Schema<*>?, type: SchemaType?, examples: Map<String, OpenApiExample>): MediaType {
60+
private fun buildSimpleMediaType(schema: Schema<*>?, body: OpenApiSimpleBody): MediaType {
6461
return MediaType().also {
6562
it.schema = schema
66-
examples.forEach { (name, obj) ->
67-
it.addExamples(name, exampleBuilder.build(type, obj))
63+
body.getExamples().forEach { (name, _) ->
64+
exampleContext.getExample(body, name)
65+
?.also { example -> it.addExamples(name, example) }
6866
}
6967
}
7068
}

src/main/kotlin/io/github/smiley4/ktorswaggerui/spec/openapi/ExampleBuilder.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ class ExampleBuilder(
1616
it.description = example.description
1717
}
1818

19-
private fun buildExampleValue(type: SchemaType?, value: Any): Any {
20-
return config.encodingConfig.getExampleEncoder()(type, value) ?: value
19+
fun buildExampleValue(type: SchemaType?, value: Any): String {
20+
return config.encodingConfig.getExampleEncoder()(type, value) ?: value.toString()
2121
}
2222

2323
}

0 commit comments

Comments
 (0)