Compare commits

..

15 Commits

Author SHA1 Message Date
bf6d08c2bd chore: prep for 3.14.4 release 2023-06-05 16:13:54 -04:00
68bae4918e fix: References for for protobuf objects (#466) 2023-06-05 16:12:31 -04:00
592c116c3b fix(deps): update dependency io.ktor:ktor-server-core to v2.3.1 (#474)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-01 10:46:44 +00:00
c7fe5c288f fix(deps): update ktor to v2.3.1 (#473)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-31 08:54:22 -04:00
e059633055 fix(deps): update dependency com.google.protobuf:protobuf-java to v3.23.2 (#472)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-26 20:27:33 +00:00
884a50fc83 chore: prep for 3.14.3 release 2023-05-22 09:39:54 -04:00
588e52c9df fix: allow for request bodies to be marked as required=false (#470) 2023-05-22 09:39:04 -04:00
f49fcb2a22 fix(deps): update dependency com.google.protobuf:protobuf-java to v3.23.1 (#469)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-17 23:39:18 +00:00
0a9475a7ab fix(deps): update dependency org.jetbrains.kotlinx:kotlinx-serialization-json to v1.5.1 (#463)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-11 21:54:50 +00:00
f8fbb7ad25 fix(deps): update kotestversion to v5.6.2 (#462)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-11 02:53:10 +00:00
f792fb5d1f fix(deps): update dependency com.google.protobuf:protobuf-java to v3.23.0 (#461)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-10 11:08:22 +00:00
845d1a971d fix(deps): update dependency org.jetbrains.kotlin:kotlin-reflect to v1.8.21 (#460)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-10 06:19:56 +00:00
9396b2ecfe chore(deps): update plugin org.jetbrains.kotlin.plugin.serialization to v1.8.21 (#459)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-10 03:36:01 +00:00
d74b7b3f28 chore(deps): update plugin org.jetbrains.kotlin.jvm to v1.8.21 (#458)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-10 03:31:13 +00:00
e783630845 chore(deps): update dependency gradle to v8.1.1 (#457)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-09 23:17:06 +00:00
26 changed files with 920 additions and 38 deletions

View File

@ -6,14 +6,24 @@
### Changed ### Changed
- Route generation with parameters doesn`t add parameters to the path.
### Remove ### Remove
--- ---
## Released ## Released
## [3.14.4] - June 5th, 2023
### Changed
- Components definitions were not in the proper schema section. Prefixed the path with component slug in `protobuf java converter`.
## [3.14.3] - May 22nd, 2023
### Added
- Added `required` parameter in request info builder.
## [3.14.2] - May 8rd, 2023 ## [3.14.2] - May 8rd, 2023
### Changed ### Changed

View File

@ -1,6 +1,6 @@
plugins { plugins {
kotlin("jvm") version "1.8.20" apply false kotlin("jvm") version "1.8.21" apply false
kotlin("plugin.serialization") version "1.8.20" apply false kotlin("plugin.serialization") version "1.8.21" apply false
id("io.bkbn.sourdough.library.jvm") version "0.12.0" apply false id("io.bkbn.sourdough.library.jvm") version "0.12.0" apply false
id("io.bkbn.sourdough.application.jvm") version "0.12.0" apply false id("io.bkbn.sourdough.application.jvm") version "0.12.0" apply false
id("io.bkbn.sourdough.root") version "0.12.0" id("io.bkbn.sourdough.root") version "0.12.0"

View File

@ -59,7 +59,7 @@ dependencies {
testFixturesApi("dev.forst:ktor-api-key:2.2.4") testFixturesApi("dev.forst:ktor-api-key:2.2.4")
testFixturesApi("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0") testFixturesApi("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
} }
testing { testing {

View File

@ -10,7 +10,8 @@ class RequestInfo private constructor(
val typeEnrichment: TypeEnrichment<*>?, val typeEnrichment: TypeEnrichment<*>?,
val description: String, val description: String,
val examples: Map<String, MediaType.Example>?, val examples: Map<String, MediaType.Example>?,
val mediaTypes: Set<String> val mediaTypes: Set<String>,
val required: Boolean
) { ) {
companion object { companion object {
@ -27,6 +28,11 @@ class RequestInfo private constructor(
private var description: String? = null private var description: String? = null
private var examples: Map<String, MediaType.Example>? = null private var examples: Map<String, MediaType.Example>? = null
private var mediaTypes: Set<String>? = null private var mediaTypes: Set<String>? = null
private var required: Boolean? = null
fun required(r: Boolean) = apply {
this.required = r
}
fun requestType(t: KType) = apply { fun requestType(t: KType) = apply {
this.requestType = t this.requestType = t
@ -56,7 +62,8 @@ class RequestInfo private constructor(
description = description ?: error("Description must be present"), description = description ?: error("Description must be present"),
typeEnrichment = typeEnrichment, typeEnrichment = typeEnrichment,
examples = examples, examples = examples,
mediaTypes = mediaTypes ?: setOf("application/json") mediaTypes = mediaTypes ?: setOf("application/json"),
required = required ?: true
) )
} }
} }

View File

@ -131,7 +131,7 @@ object Helpers {
mediaTypes = reqInfo.mediaTypes, mediaTypes = reqInfo.mediaTypes,
enrichment = reqInfo.typeEnrichment enrichment = reqInfo.typeEnrichment
), ),
required = true required = reqInfo.required
) )
} }

View File

@ -52,6 +52,7 @@ import io.bkbn.kompendium.core.util.polymorphicResponse
import io.bkbn.kompendium.core.util.postNoReqBody import io.bkbn.kompendium.core.util.postNoReqBody
import io.bkbn.kompendium.core.util.primitives import io.bkbn.kompendium.core.util.primitives
import io.bkbn.kompendium.core.util.reqRespExamples import io.bkbn.kompendium.core.util.reqRespExamples
import io.bkbn.kompendium.core.util.optionalReqExample
import io.bkbn.kompendium.core.util.requiredParams import io.bkbn.kompendium.core.util.requiredParams
import io.bkbn.kompendium.core.util.responseHeaders import io.bkbn.kompendium.core.util.responseHeaders
import io.bkbn.kompendium.core.util.returnsList import io.bkbn.kompendium.core.util.returnsList
@ -178,6 +179,9 @@ class KompendiumTest : DescribeSpec({
it("Can describe example parameters") { it("Can describe example parameters") {
openApiTestAllSerializers("T0021__example_parameters.json") { exampleParams() } openApiTestAllSerializers("T0021__example_parameters.json") { exampleParams() }
} }
it("Can generate example optional request body") {
openApiTestAllSerializers("T0069__example_optional_req.json") { optionalReqExample() }
}
} }
describe("Defaults") { describe("Defaults") {
it("Can generate a default parameter value") { it("Can generate a default parameter value") {

View File

@ -55,3 +55,30 @@ fun Routing.exampleParams() = basicGetGenerator<TestResponse>(
) )
) )
) )
fun Routing.optionalReqExample() {
route(rootPath) {
install(NotarizedRoute()) {
post = PostInfo.builder {
summary(defaultPathSummary)
description(defaultPathDescription)
request {
description(defaultRequestDescription)
requestType<TestRequest>()
examples(
"Testerina" to TestRequest(TestNested("asdf"), 1.5, emptyList())
)
required(false)
}
response {
description(defaultResponseDescription)
responseCode(HttpStatusCode.OK)
responseType<TestResponse>()
examples(
"Testerino" to TestResponse("Heya")
)
}
}
}
}
}

View File

@ -0,0 +1,136 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/": {
"post": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"requestBody": {
"description": "You gotta send it",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestRequest"
},
"examples": {
"Testerina": {
"value": {
"fieldName": {
"nesty": "asdf"
},
"b": 1.5,
"aaa": []
}
}
}
}
},
"required": false
},
"responses": {
"200": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestResponse"
},
"examples": {
"Testerino": {
"value": {
"c": "Heya"
}
}
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"TestResponse": {
"type": "object",
"properties": {
"c": {
"type": "string"
}
},
"required": [
"c"
]
},
"TestRequest": {
"type": "object",
"properties": {
"aaa": {
"items": {
"type": "number",
"format": "int64"
},
"type": "array"
},
"b": {
"type": "number",
"format": "double"
},
"fieldName": {
"$ref": "#/components/schemas/TestNested"
}
},
"required": [
"aaa",
"b",
"fieldName"
]
},
"TestNested": {
"type": "object",
"properties": {
"nesty": {
"type": "string"
}
},
"required": [
"nesty"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -1,5 +1,5 @@
# Kompendium # Kompendium
project.version=3.14.2 project.version=3.14.4
# Kotlin # Kotlin
kotlin.code.style=official kotlin.code.style=official
# Gradle # Gradle
@ -9,6 +9,6 @@ org.gradle.jvmargs=-Xmx2000m
org.gradle.parallel=true org.gradle.parallel=true
# Dependencies # Dependencies
ktorVersion=2.3.0 ktorVersion=2.3.1
kotestVersion=5.6.1 kotestVersion=5.6.2
detektVersion=1.22.0 detektVersion=1.22.0

Binary file not shown.

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
networkTimeout=10000 networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

11
gradlew vendored
View File

@ -85,9 +85,6 @@ done
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum
@ -144,7 +141,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #( case $MAX_FD in #(
max*) max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045 # shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) || MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit" warn "Could not query maximum file descriptor limit"
esac esac
@ -152,7 +149,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #( '' | soft) :;; #(
*) *)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045 # shellcheck disable=SC3045
ulimit -n "$MAX_FD" || ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD" warn "Could not set maximum file descriptor limit to $MAX_FD"
esac esac
@ -197,6 +194,10 @@ if "$cygwin" || "$msys" ; then
done done
fi fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command; # Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in # shell script including quotes and variable substitutions, so put them in

View File

@ -23,8 +23,8 @@ dependencies {
// Kompendium // Kompendium
api(projects.kompendiumEnrichment) api(projects.kompendiumEnrichment)
implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.20") implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.21")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
// Formatting // Formatting
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:$detektVersion") detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:$detektVersion")

View File

@ -8,7 +8,7 @@ import kotlin.reflect.KType
object Helpers { object Helpers {
private const val COMPONENT_SLUG = "#/components/schemas" const val COMPONENT_SLUG = "#/components/schemas"
fun KType.getSlug(enrichment: Enrichment? = null) = when (enrichment) { fun KType.getSlug(enrichment: Enrichment? = null) = when (enrichment) {
is TypeEnrichment<*> -> getEnrichedSlug(enrichment) is TypeEnrichment<*> -> getEnrichedSlug(enrichment)

View File

@ -22,8 +22,8 @@ dependencies {
// IMPLEMENTATION // IMPLEMENTATION
implementation(projects.kompendiumCore) implementation(projects.kompendiumCore)
implementation("io.ktor:ktor-server-core:2.3.0") implementation("io.ktor:ktor-server-core:2.3.1")
implementation("io.ktor:ktor-server-locations:2.3.0") implementation("io.ktor:ktor-server-locations:2.3.1")
// TESTING // TESTING

View File

@ -22,7 +22,7 @@ dependencies {
api(projects.kompendiumJsonSchema) api(projects.kompendiumJsonSchema)
api(projects.kompendiumEnrichment) api(projects.kompendiumEnrichment)
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
// Formatting // Formatting
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:$detektVersion") detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:$detektVersion")

View File

@ -41,7 +41,7 @@ dependencies {
implementation("org.slf4j:slf4j-simple:2.0.7") implementation("org.slf4j:slf4j-simple:2.0.7")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0") implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
implementation("joda-time:joda-time:2.12.5") implementation("joda-time:joda-time:2.12.5")

View File

@ -22,9 +22,9 @@ dependencies {
implementation(projects.kompendiumJsonSchema) implementation(projects.kompendiumJsonSchema)
implementation("com.google.protobuf:protobuf-java:3.22.3") implementation("com.google.protobuf:protobuf-java:3.23.2")
implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.20") implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.21")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
// Formatting // Formatting
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:$detektVersion") detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:$detektVersion")

View File

@ -9,6 +9,7 @@ import io.bkbn.kompendium.json.schema.definition.MapDefinition
import io.bkbn.kompendium.json.schema.definition.NullableDefinition import io.bkbn.kompendium.json.schema.definition.NullableDefinition
import io.bkbn.kompendium.json.schema.definition.ReferenceDefinition import io.bkbn.kompendium.json.schema.definition.ReferenceDefinition
import io.bkbn.kompendium.json.schema.definition.TypeDefinition import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.json.schema.util.Helpers
import kotlin.reflect.KType import kotlin.reflect.KType
import kotlin.reflect.full.createType import kotlin.reflect.full.createType
@ -150,7 +151,7 @@ fun fromTypeToSchema(
type = "string", type = "string",
enum = javaProtoField.enumType.values.map { it.name }.toSet() enum = javaProtoField.enumType.values.map { it.name }.toSet()
) )
ReferenceDefinition(javaProtoField.enumType.name) ReferenceDefinition("${Helpers.COMPONENT_SLUG}/${javaProtoField.enumType.name}")
} }
Descriptors.FieldDescriptor.JavaType.MESSAGE -> { Descriptors.FieldDescriptor.JavaType.MESSAGE -> {
// Traverse through possible nested messages // Traverse through possible nested messages
@ -160,7 +161,7 @@ fun fromTypeToSchema(
it.jsonName to fromNestedTypeToSchema(it, cache) it.jsonName to fromNestedTypeToSchema(it, cache)
}.toMap() }.toMap()
) )
ReferenceDefinition(javaProtoField.messageType.name) ReferenceDefinition("${Helpers.COMPONENT_SLUG}/${javaProtoField.messageType.name}")
} }
null -> NullableDefinition() null -> NullableDefinition()
} }

View File

@ -2,17 +2,21 @@ package io.bkbn.kompendium.protobufjavaconverter.converters
import com.google.protobuf.Descriptors import com.google.protobuf.Descriptors
import com.google.protobuf.GeneratedMessageV3 import com.google.protobuf.GeneratedMessageV3
import io.bkbn.kompendium.core.fixtures.TestHelpers.openApiTestAllSerializers
import io.bkbn.kompendium.core.metadata.PostInfo
import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.json.schema.definition.ArrayDefinition import io.bkbn.kompendium.json.schema.definition.ArrayDefinition
import io.bkbn.kompendium.json.schema.definition.EnumDefinition import io.bkbn.kompendium.json.schema.definition.EnumDefinition
import io.bkbn.kompendium.json.schema.definition.JsonSchema import io.bkbn.kompendium.json.schema.definition.JsonSchema
import io.bkbn.kompendium.json.schema.definition.MapDefinition import io.bkbn.kompendium.json.schema.definition.MapDefinition
import io.bkbn.kompendium.json.schema.definition.ReferenceDefinition import io.bkbn.kompendium.json.schema.definition.ReferenceDefinition
import io.bkbn.kompendium.json.schema.definition.TypeDefinition import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.json.schema.util.Helpers
import io.bkbn.kompendium.protobufjavaconverter.Corpus import io.bkbn.kompendium.protobufjavaconverter.Corpus
import io.bkbn.kompendium.protobufjavaconverter.DoubleNestedMessage import io.bkbn.kompendium.protobufjavaconverter.DoubleNestedMessage
import io.bkbn.kompendium.protobufjavaconverter.NestedMapMessage
import io.bkbn.kompendium.protobufjavaconverter.EnumMessage import io.bkbn.kompendium.protobufjavaconverter.EnumMessage
import io.bkbn.kompendium.protobufjavaconverter.GoogleTypes import io.bkbn.kompendium.protobufjavaconverter.GoogleTypes
import io.bkbn.kompendium.protobufjavaconverter.NestedMapMessage
import io.bkbn.kompendium.protobufjavaconverter.NestedMessage import io.bkbn.kompendium.protobufjavaconverter.NestedMessage
import io.bkbn.kompendium.protobufjavaconverter.RepeatedEnumMessage import io.bkbn.kompendium.protobufjavaconverter.RepeatedEnumMessage
import io.bkbn.kompendium.protobufjavaconverter.RepeatedMessage import io.bkbn.kompendium.protobufjavaconverter.RepeatedMessage
@ -23,10 +27,15 @@ import io.kotest.matchers.maps.shouldContainExactly
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import io.kotest.matchers.types.shouldBeTypeOf import io.kotest.matchers.types.shouldBeTypeOf
import io.kotest.matchers.types.shouldNotBeTypeOf import io.kotest.matchers.types.shouldNotBeTypeOf
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.install
import io.ktor.server.routing.Route
import kotlin.reflect.KType import kotlin.reflect.KType
import kotlin.reflect.full.createType import kotlin.reflect.full.createType
class FieldDescriptiorConvertersKtTest : DescribeSpec({ class FieldDescriptiorConvertersKtTest : DescribeSpec({
val componentSlug = Helpers.COMPONENT_SLUG
describe("fromTypeToSchemaTests") { describe("fromTypeToSchemaTests") {
val simpleMessageDescriptor = SimpleTestMessage.getDescriptor() val simpleMessageDescriptor = SimpleTestMessage.getDescriptor()
it("java int field should return TypeDefinition INT") { it("java int field should return TypeDefinition INT") {
@ -77,7 +86,7 @@ class FieldDescriptiorConvertersKtTest : DescribeSpec({
val message = NestedMessage.getDescriptor() val message = NestedMessage.getDescriptor()
val result = fromNestedTypeToSchema(message.findFieldByName("nested_field")) val result = fromNestedTypeToSchema(message.findFieldByName("nested_field"))
result.shouldBeTypeOf<ReferenceDefinition>() result.shouldBeTypeOf<ReferenceDefinition>()
result.`$ref`.shouldBe(message.findFieldByName("nested_field").messageType.name) result.`$ref`.shouldBe("${Helpers.COMPONENT_SLUG}/${message.findFieldByName("nested_field").messageType.name}")
} }
it("Repeated message should return ArrayDefinition") { it("Repeated message should return ArrayDefinition") {
@ -85,7 +94,7 @@ class FieldDescriptiorConvertersKtTest : DescribeSpec({
val result = fromNestedTypeToSchema(message.findFieldByName("repeated_field")) val result = fromNestedTypeToSchema(message.findFieldByName("repeated_field"))
result.shouldBeTypeOf<ArrayDefinition>() result.shouldBeTypeOf<ArrayDefinition>()
result.items.shouldBeTypeOf<ReferenceDefinition>() result.items.shouldBeTypeOf<ReferenceDefinition>()
(result.items as ReferenceDefinition).`$ref`.shouldBe(SimpleTestMessage.getDescriptor().name) (result.items as ReferenceDefinition).`$ref`.shouldBe("$componentSlug/${SimpleTestMessage.getDescriptor().name}")
} }
it("Repeated enum message should return ArrayDefinition") { it("Repeated enum message should return ArrayDefinition") {
@ -93,7 +102,7 @@ class FieldDescriptiorConvertersKtTest : DescribeSpec({
val result: JsonSchema = fromNestedTypeToSchema(message.findFieldByName("repeated_field")) val result: JsonSchema = fromNestedTypeToSchema(message.findFieldByName("repeated_field"))
result.shouldBeTypeOf<ArrayDefinition>() result.shouldBeTypeOf<ArrayDefinition>()
result.items.shouldBeTypeOf<ReferenceDefinition>() result.items.shouldBeTypeOf<ReferenceDefinition>()
(result.items as ReferenceDefinition).`$ref`.shouldBe(Corpus.getDescriptor().name) (result.items as ReferenceDefinition).`$ref`.shouldBe("$componentSlug/${Corpus.getDescriptor().name}")
} }
it("SimpleMapMessage message should return MapDefinition") { it("SimpleMapMessage message should return MapDefinition") {
@ -169,7 +178,7 @@ class FieldDescriptiorConvertersKtTest : DescribeSpec({
// Our nested field should be a reference // Our nested field should be a reference
result.shouldBeTypeOf<ReferenceDefinition>() result.shouldBeTypeOf<ReferenceDefinition>()
// Our nested field should be a reference to simplemessage // Our nested field should be a reference to simplemessage
result.`$ref`.shouldBe(SimpleTestMessage.getDescriptor().name) result.`$ref`.shouldBe("$componentSlug/${SimpleTestMessage.getDescriptor().name}")
} }
it("Double nested message to schema") { it("Double nested message to schema") {
@ -201,11 +210,11 @@ class FieldDescriptiorConvertersKtTest : DescribeSpec({
// Our nested field should be a reference // Our nested field should be a reference
result.shouldBeTypeOf<ReferenceDefinition>() result.shouldBeTypeOf<ReferenceDefinition>()
// it should be a reference to our nested message // it should be a reference to our nested message
result.`$ref`.shouldBe(NestedMessage.getDescriptor().name) result.`$ref`.shouldBe("$componentSlug/${NestedMessage.getDescriptor().name}")
val nestedResult = (resultSchema[NestedMessage::class.createType()] as TypeDefinition).properties!!["nestedField"] val nestedResult = (resultSchema[NestedMessage::class.createType()] as TypeDefinition).properties!!["nestedField"]
nestedResult.shouldBeTypeOf<ReferenceDefinition>() nestedResult.shouldBeTypeOf<ReferenceDefinition>()
// Our nested message reference should be pointing to simpleTest message // Our nested message reference should be pointing to simpleTest message
nestedResult.`$ref`.shouldBe(SimpleTestMessage.getDescriptor().name) nestedResult.`$ref`.shouldBe("$componentSlug/${SimpleTestMessage.getDescriptor().name}")
// last but not least we should have definition for our SimpleTest message which is not a reference // last but not least we should have definition for our SimpleTest message which is not a reference
(resultSchema[SimpleTestMessage::class.createType()] as TypeDefinition).shouldNotBeTypeOf<ReferenceDefinition>() (resultSchema[SimpleTestMessage::class.createType()] as TypeDefinition).shouldNotBeTypeOf<ReferenceDefinition>()
} }
@ -235,6 +244,39 @@ class FieldDescriptiorConvertersKtTest : DescribeSpec({
testMessageBasics(message) testMessageBasics(message)
} }
} }
describe("Test spec generation") {
it("Generates simple message references") {
openApiTestAllSerializers(
"T0001__simpletestmessage_post.json",
testMessageBasics(SimpleTestMessage.getDefaultInstance())
) { testRoute<SimpleTestMessage>() }
}
it("Generates enum references") {
openApiTestAllSerializers(
"T0002__enummessage_post.json",
testMessageBasics(EnumMessage.getDefaultInstance())
) { testRoute<EnumMessage>() }
}
it("Generates repeated type references") {
openApiTestAllSerializers(
"T0003__repeatedmessage_post.json",
testMessageBasics(RepeatedMessage.getDefaultInstance())
) { testRoute<RepeatedMessage>() }
}
it("Generates nested type references") {
openApiTestAllSerializers(
"T0004__nestedmessage_post.json",
testMessageBasics(NestedMessage.getDefaultInstance())
) { testRoute<NestedMessage>() }
}
it("Generates nested map type references") {
openApiTestAllSerializers(
"T0005__nestedmapmessage_post.json",
testMessageBasics(NestedMapMessage.getDefaultInstance())
) { testRoute<NestedMapMessage>() }
}
}
}) })
/** /**
@ -256,3 +298,25 @@ fun testMessageBasics(message: GeneratedMessageV3): Map<KType, JsonSchema> {
} }
return resultSchema return resultSchema
} }
private const val DEFAULT_RESPONSE_DESCRIPTION = "A Successful Endeavor"
private const val DEFAULT_REQUEST_DESCRIPTION = "You gotta send it"
private const val DEFAULT_PATH_SUMMARY = "Great Summary!"
private const val DEFAULT_PATH_DESCRIPTION = "testing more"
private inline fun <reified T> Route.testRoute() {
install(NotarizedRoute()) {
post = PostInfo.builder {
summary(DEFAULT_PATH_SUMMARY)
description(DEFAULT_PATH_DESCRIPTION)
request {
requestType<Unit>()
description(DEFAULT_REQUEST_DESCRIPTION)
}
response {
responseCode(HttpStatusCode.OK)
responseType<T>()
description(DEFAULT_RESPONSE_DESCRIPTION)
}
}
}
}

View File

@ -0,0 +1,127 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/": {
"post": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"requestBody": {
"description": "You gotta send it",
"required": true
},
"responses": {
"200": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SimpleTestMessage"
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"SimpleTestMessage": {
"type": "object",
"properties": {
"myTestDouble": {
"type": "number",
"format": "double"
},
"myTestFloat": {
"type": "number",
"format": "float"
},
"myTestInt32": {
"type": "number",
"format": "int32"
},
"myTestInt64": {
"type": "number",
"format": "int64"
},
"myTestUint32": {
"type": "number",
"format": "int32"
},
"myTestUint64": {
"type": "number",
"format": "int64"
},
"myTestSint32": {
"type": "number",
"format": "int32"
},
"myTestSint64": {
"type": "number",
"format": "int64"
},
"myTestFixed32": {
"type": "number",
"format": "int32"
},
"myTestFixed64": {
"type": "number",
"format": "int64"
},
"myTestSfixed32": {
"type": "number",
"format": "int32"
},
"myTestSfixed64": {
"type": "number",
"format": "int64"
},
"myTestBool": {
"type": "boolean"
},
"myTestBytes": {
"type": "string"
},
"myTestString": {
"type": "string"
}
}
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,86 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/": {
"post": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"requestBody": {
"description": "You gotta send it",
"required": true
},
"responses": {
"200": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/EnumMessage"
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"EnumMessage": {
"type": "object",
"properties": {
"corpus": {
"$ref": "#/components/schemas/Corpus"
}
}
},
"Corpus": {
"type": "string",
"enum": [
"CORPUS_UNSPECIFIED",
"CORPUS_UNIVERSAL",
"CORPUS_WEB",
"CORPUS_IMAGES",
"CORPUS_LOCAL",
"CORPUS_NEWS",
"CORPUS_PRODUCTS",
"CORPUS_VIDEO"
]
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,138 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/": {
"post": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"requestBody": {
"description": "You gotta send it",
"required": true
},
"responses": {
"200": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RepeatedMessage"
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"RepeatedMessage": {
"type": "object",
"properties": {
"repeatedField": {
"items": {
"$ref": "#/components/schemas/SimpleTestMessage"
},
"type": "array"
}
}
},
"SimpleTestMessage": {
"type": "object",
"properties": {
"myTestDouble": {
"type": "number",
"format": "double"
},
"myTestFloat": {
"type": "number",
"format": "float"
},
"myTestInt32": {
"type": "number",
"format": "int32"
},
"myTestInt64": {
"type": "number",
"format": "int64"
},
"myTestUint32": {
"type": "number",
"format": "int32"
},
"myTestUint64": {
"type": "number",
"format": "int64"
},
"myTestSint32": {
"type": "number",
"format": "int32"
},
"myTestSint64": {
"type": "number",
"format": "int64"
},
"myTestFixed32": {
"type": "number",
"format": "int32"
},
"myTestFixed64": {
"type": "number",
"format": "int64"
},
"myTestSfixed32": {
"type": "number",
"format": "int32"
},
"myTestSfixed64": {
"type": "number",
"format": "int64"
},
"myTestBool": {
"type": "boolean"
},
"myTestBytes": {
"type": "string"
},
"myTestString": {
"type": "string"
}
}
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,135 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/": {
"post": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"requestBody": {
"description": "You gotta send it",
"required": true
},
"responses": {
"200": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/NestedMessage"
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"NestedMessage": {
"type": "object",
"properties": {
"nestedField": {
"$ref": "#/components/schemas/SimpleTestMessage"
}
}
},
"SimpleTestMessage": {
"type": "object",
"properties": {
"myTestDouble": {
"type": "number",
"format": "double"
},
"myTestFloat": {
"type": "number",
"format": "float"
},
"myTestInt32": {
"type": "number",
"format": "int32"
},
"myTestInt64": {
"type": "number",
"format": "int64"
},
"myTestUint32": {
"type": "number",
"format": "int32"
},
"myTestUint64": {
"type": "number",
"format": "int64"
},
"myTestSint32": {
"type": "number",
"format": "int32"
},
"myTestSint64": {
"type": "number",
"format": "int64"
},
"myTestFixed32": {
"type": "number",
"format": "int32"
},
"myTestFixed64": {
"type": "number",
"format": "int64"
},
"myTestSfixed32": {
"type": "number",
"format": "int32"
},
"myTestSfixed64": {
"type": "number",
"format": "int64"
},
"myTestBool": {
"type": "boolean"
},
"myTestBytes": {
"type": "string"
},
"myTestString": {
"type": "string"
}
}
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -0,0 +1,146 @@
{
"openapi": "3.1.0",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/": {
"post": {
"tags": [],
"summary": "Great Summary!",
"description": "testing more",
"parameters": [],
"requestBody": {
"description": "You gotta send it",
"required": true
},
"responses": {
"200": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/NestedMapMessage"
}
}
}
}
},
"deprecated": false
},
"parameters": []
}
},
"webhooks": {},
"components": {
"schemas": {
"NestedMapMessage": {
"type": "object",
"properties": {
"mapField": {
"additionalProperties": {
"type": "object",
"properties": {
"myVariable0": {
"$ref": "#/components/schemas/SimpleTestMessage"
},
"myVariable1": {
"$ref": "#/components/schemas/SimpleTestMessage"
}
}
},
"type": "object"
}
}
},
"SimpleTestMessage": {
"type": "object",
"properties": {
"myTestDouble": {
"type": "number",
"format": "double"
},
"myTestFloat": {
"type": "number",
"format": "float"
},
"myTestInt32": {
"type": "number",
"format": "int32"
},
"myTestInt64": {
"type": "number",
"format": "int64"
},
"myTestUint32": {
"type": "number",
"format": "int32"
},
"myTestUint64": {
"type": "number",
"format": "int64"
},
"myTestSint32": {
"type": "number",
"format": "int32"
},
"myTestSint64": {
"type": "number",
"format": "int64"
},
"myTestFixed32": {
"type": "number",
"format": "int32"
},
"myTestFixed64": {
"type": "number",
"format": "int64"
},
"myTestSfixed32": {
"type": "number",
"format": "int32"
},
"myTestSfixed64": {
"type": "number",
"format": "int64"
},
"myTestBool": {
"type": "boolean"
},
"myTestBytes": {
"type": "string"
},
"myTestString": {
"type": "string"
}
}
}
},
"securitySchemes": {}
},
"security": [],
"tags": []
}

View File

@ -22,8 +22,8 @@ dependencies {
// IMPLEMENTATION // IMPLEMENTATION
implementation(projects.kompendiumCore) implementation(projects.kompendiumCore)
implementation("io.ktor:ktor-server-core:2.3.0") implementation("io.ktor:ktor-server-core:2.3.1")
implementation("io.ktor:ktor-server-resources:2.3.0") implementation("io.ktor:ktor-server-resources:2.3.1")
// TESTING // TESTING