diff --git a/Sources/OpenAPIKit/Components Object/Components+JSONReference.swift b/Sources/OpenAPIKit/Components Object/Components+JSONReference.swift index 5a10f642d..e21d933aa 100644 --- a/Sources/OpenAPIKit/Components Object/Components+JSONReference.swift +++ b/Sources/OpenAPIKit/Components Object/Components+JSONReference.swift @@ -230,6 +230,11 @@ extension OpenAPI.Components { /// If you want to look something up without throwing, you might want to use the subscript /// operator on the `Components`. /// + /// If you are recursing through JSONSchema references, you may want to + /// call `flattenToJsonSchema()` on the result of `lookupOnce()` because + /// `lookupOnce()` will wrap any resulting `JSONSchema` reference in an + /// `OpenAPI.Reference` which adds work if all you want to do is recurse. + /// /// If you also want to fully dereference the value in question instead /// of just looking it up see the various `dereference` functions /// on this type for more information. @@ -287,6 +292,11 @@ extension OpenAPI.Components { /// If you want to look something up without throwing, you might want to use the subscript /// operator on the `Components`. /// + /// If you are recursing through JSONSchema references, you may want to + /// call `flattenToJsonSchema()` on the result of `lookupOnce()` because + /// `lookupOnce()` will wrap any resulting `JSONSchema` reference in an + /// `OpenAPI.Reference` which adds work if all you want to do is recurse. + /// /// If you also want to fully dereference the value in question instead /// of just looking it up see the various `dereference` functions /// on this type for more information. diff --git a/Sources/OpenAPIKit/JSONReference.swift b/Sources/OpenAPIKit/JSONReference.swift index e0207c523..d89de9959 100644 --- a/Sources/OpenAPIKit/JSONReference.swift +++ b/Sources/OpenAPIKit/JSONReference.swift @@ -387,6 +387,42 @@ extension OpenAPI { } } +public extension OpenAPI.Reference where ReferenceType == JSONSchema { + /// When an OpenAPI.Reference points at a JSONSchema, it can be represented + /// as a JSONSchema directly because JSONSchema has an innate ability to + /// represent references itself. + /// + /// Example: + /// + /// OpenAPI.Reference.component(named: "hello").asJsonSchema() + /// // results in JSONSchema.reference(.component(named: "hello")) + func asJsonSchema() -> JSONSchema { + .reference(jsonReference) + .overriddenNonNil(summary: summary) + .overriddenNonNil(description: description) + } +} + +public extension Either where A == OpenAPI.Reference, B == JSONSchema { + /// When an Either represents a reference or a schema, it can be + /// "flattened" to a JSONSchema because JSONSchema has an innate ability to + /// represent references itself. + /// + /// Examples: + /// + /// Either, JSONSchema>.a(.component(named: "hello")).flattenToJsonSchema() + /// // results in JSONSchema.reference(.component(named: "hello")) + /// + /// Either, JSONSchema>.b(.string).flattenToJsonSchema() + /// // results in JSONSchema.string + func flattenToJsonSchema() -> JSONSchema { + switch self { + case .a(let reference): reference.asJsonSchema() + case .b(let schema): schema + } + } +} + public extension JSONReference { /// Create an OpenAPI.Reference from the given JSONReference. func openAPIReference(withDescription description: String? = nil) -> OpenAPI.Reference { diff --git a/Tests/OpenAPIKitTests/JSONReferenceTests.swift b/Tests/OpenAPIKitTests/JSONReferenceTests.swift index 7ee1f9885..fc0f5447d 100644 --- a/Tests/OpenAPIKitTests/JSONReferenceTests.swift +++ b/Tests/OpenAPIKitTests/JSONReferenceTests.swift @@ -178,7 +178,36 @@ final class JSONReferenceTests: XCTestCase { // test dynamic member lookup: XCTAssertEqual(t1.openAPIReference().internalValue, .component(name: "hello")) + } + func test_openAPIRefOverridable() { + XCTAssertEqual( + OpenAPI.Reference.component(named: "hello").overriddenNonNil(summary: "hi").overriddenNonNil(description: "hello there"), + .component(named: "hello", summary: "hi", description: "hello there") + ) + XCTAssertEqual( + OpenAPI.Reference.component(named: "hello", summary: "hi").overriddenNonNil(summary: nil), + .component(named: "hello", summary: "hi") + ) + XCTAssertEqual( + OpenAPI.Reference.component(named: "hello", description: "hello there").overriddenNonNil(description: nil), + .component(named: "hello", description: "hello there") + ) + } + + func test_asJsonSchema() { + XCTAssertEqual( + OpenAPI.Reference.component(named: "hello").asJsonSchema(), + JSONSchema.reference(.component(named: "hello")) + ) + XCTAssertEqual( + Either, JSONSchema>.a(.component(named: "hello")).flattenToJsonSchema(), + JSONSchema.reference(.component(named: "hello")) + ) + XCTAssertEqual( + Either, JSONSchema>.b(.string).flattenToJsonSchema(), + .string + ) } }