diff --git a/src/openapi/build.gradle.kts b/src/openapi/build.gradle.kts index e053973d..5deb6dfa 100644 --- a/src/openapi/build.gradle.kts +++ b/src/openapi/build.gradle.kts @@ -33,7 +33,7 @@ kotlin { dependencies { implementation(project(":src:compiler:core")) implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1") - implementation("community.flock.kotlinx.openapi.bindings:kotlin-openapi-bindings:0.0.15") + implementation("community.flock.kotlinx.openapi.bindings:kotlin-openapi-bindings:0.0.17") } } commonTest { diff --git a/src/openapi/src/commonMain/kotlin/community/flock/wirespec/openapi/v2/OpenApiParser.kt b/src/openapi/src/commonMain/kotlin/community/flock/wirespec/openapi/v2/OpenApiParser.kt index e1988f93..172c72b4 100644 --- a/src/openapi/src/commonMain/kotlin/community/flock/wirespec/openapi/v2/OpenApiParser.kt +++ b/src/openapi/src/commonMain/kotlin/community/flock/wirespec/openapi/v2/OpenApiParser.kt @@ -1,5 +1,6 @@ package community.flock.wirespec.openapi.v2 +import arrow.core.filterIsInstance import community.flock.kotlinx.openapi.bindings.v2.BooleanObject import community.flock.kotlinx.openapi.bindings.v2.OpenAPI import community.flock.kotlinx.openapi.bindings.v2.OperationObject @@ -165,6 +166,7 @@ class OpenApiParser(private val openApi: SwaggerObject) { } private fun parseDefinitions() = openApi.definitions.orEmpty() + .filterIsInstance() .filter { it.value.additionalProperties == null } .flatMap { it.value.flatten(className(it.key)) } @@ -197,19 +199,18 @@ class OpenApiParser(private val openApi: SwaggerObject) { private fun ReferenceObject.resolveSchemaObject() = openApi.definitions ?.get(getReference()) - ?.let { this to it } ?: error("Cannot resolve ref: $ref") private fun SchemaOrReferenceObject.resolve(): SchemaObject = when (this) { is SchemaObject -> this - is ReferenceObject -> this.resolveSchemaObject().second + is ReferenceObject -> this.resolveSchemaObject().resolve() } private fun SchemaOrReferenceOrBooleanObject.resolve(): SchemaObject = when (this) { is SchemaObject -> this - is ReferenceObject -> this.resolveSchemaObject().second + is ReferenceObject -> this.resolveSchemaObject().resolve() is BooleanObject -> TODO() } @@ -298,7 +299,8 @@ class OpenApiParser(private val openApi: SwaggerObject) { } private fun ReferenceObject.toReference(): Reference = - resolveSchemaObject().let { (referencingObject, schema) -> + resolveSchemaObject().let { refOrSchema -> + val schema = refOrSchema.resolve() when { schema.additionalProperties != null -> when (val additionalProperties = schema.additionalProperties!!) { is BooleanObject -> Reference.Any(false, true) @@ -306,16 +308,19 @@ class OpenApiParser(private val openApi: SwaggerObject) { is SchemaObject -> additionalProperties.toReference(getReference()).toMap() } - schema.enum != null -> Reference.Custom(className(referencingObject.getReference()), false, false) + schema.enum != null -> Reference.Custom(className(this.getReference()), false, false) schema.type.isPrimitive() -> Reference.Primitive(schema.type!!.toPrimitive(), false, false) else -> when (schema.type) { OpenapiType.ARRAY -> when (val items = schema.items) { is ReferenceObject -> Reference.Custom(className(items.getReference()), true) - is SchemaObject -> Reference.Custom(className(referencingObject.getReference(), "Array"), true) + is SchemaObject -> Reference.Custom(className(this.getReference(), "Array"), true) null -> error("items cannot be null when type is array: ${this.ref}") } - else -> Reference.Custom(className(referencingObject.getReference()), false) + else -> when(refOrSchema){ + is SchemaObject -> Reference.Custom(className(this.getReference()), false) + is ReferenceObject -> Reference.Custom(className(refOrSchema.getReference()), false) + } } } @@ -376,7 +381,7 @@ class OpenApiParser(private val openApi: SwaggerObject) { is SchemaObject -> { Field( identifier = Field.Identifier(key), - reference = when(value.type){ + reference = when (value.type) { OpenapiType.ARRAY -> value.toReference(className(name, key, "Array")) else -> value.toReference(className(name, key)) }, diff --git a/src/openapi/src/commonTest/resources/v2/alias.json b/src/openapi/src/commonTest/resources/v2/alias.json new file mode 100644 index 00000000..1ffee9e0 --- /dev/null +++ b/src/openapi/src/commonTest/resources/v2/alias.json @@ -0,0 +1,41 @@ +{ + "swagger": "2.0", + "info": { + "title": "Alias", + "version": "1.0.0" + }, + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": { + "/alisa": { + "get": { + "responses": { + "200": { + "description": "Ok", + "schema": { + "$ref": "#/definitions/Bar" + } + } + } + } + } + }, + "definitions": { + "Foo": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + } + }, + "Bar": { + "$ref": "#/definitions/Foo" + } + } +} + diff --git a/src/openapi/src/jvmTest/kotlin/community/flock/wirespec/openapi/v2/OpenApiParserTest.kt b/src/openapi/src/jvmTest/kotlin/community/flock/wirespec/openapi/v2/OpenApiParserTest.kt index 7f5af78a..af220d6c 100644 --- a/src/openapi/src/jvmTest/kotlin/community/flock/wirespec/openapi/v2/OpenApiParserTest.kt +++ b/src/openapi/src/jvmTest/kotlin/community/flock/wirespec/openapi/v2/OpenApiParserTest.kt @@ -219,6 +219,53 @@ class OpenApiParserTest { assertEquals(expectedEndpoint, endpoints) } + @Test + fun alias() { + val json = IO.readOpenApi("v2/alias.json") + + val openApi = OpenAPI.decodeFromString(json) + val ast = OpenApiParser.parse(openApi) + + val expected = listOf( + Endpoint( + name = "AlisaGET", + method = Endpoint.Method.GET, + path = listOf(Endpoint.Segment.Literal(value = "alisa")), + query = emptyList(), + headers = emptyList(), + cookies = emptyList(), + requests = listOf(Endpoint.Request(content = null)), + responses = listOf( + Endpoint.Response( + status = "200", + content = Endpoint.Content( + type = "application/json", + reference = Custom(value = "Foo", isIterable = false, isMap = false), + isNullable = false + ) + ) + ) + ), + Type( + name = "Foo", + shape = Shape( + value = listOf( + Field( + identifier = Identifier(value = "a"), + reference = Primitive( + type = Primitive.Type.String, + isIterable = false, + isMap = false + ), + isNullable = true + ) + ) + ) + ) + ) + assertEquals(expected, ast) + } + @Test fun objectInRequest() { val json = IO.readOpenApi("v2/object-in-request.json") @@ -227,7 +274,6 @@ class OpenApiParserTest { val ast = OpenApiParser.parse(openApi) assertEquals(Expected.objectInRequest, ast) - assertEquals(Expected.objectInRequest, ast) } @Test