diff --git a/Sources/OpenAPIKit/Components Object/Components.swift b/Sources/OpenAPIKit/Components Object/Components.swift index 0cc169a99..b9193e6dd 100644 --- a/Sources/OpenAPIKit/Components Object/Components.swift +++ b/Sources/OpenAPIKit/Components Object/Components.swift @@ -298,7 +298,12 @@ extension OpenAPI.Components { } extension OpenAPI.Components { - internal mutating func externallyDereference(in context: Context.Type) async throws { + internal mutating func externallyDereference(in context: Context.Type, depth: ExternalDereferenceDepth = .iterations(1)) async throws { + if case let .iterations(number) = depth, + number <= 0 { + return + } + let oldSchemas = schemas let oldResponses = responses let oldParameters = parameters @@ -336,15 +341,43 @@ extension OpenAPI.Components { callbacks = newCallbacks - try await merge(c1) - try await merge(c2) - try await merge(c3) - try await merge(c4) - try await merge(c5) - try await merge(c6) - try await merge(c7) - - try merge(c8) + let c1Resolved = try await c1 + let c2Resolved = try await c2 + let c3Resolved = try await c3 + let c4Resolved = try await c4 + let c5Resolved = try await c5 + let c6Resolved = try await c6 + let c7Resolved = try await c7 + let c8Resolved = c8 + + let noNewComponents = + c1Resolved.isEmpty + && c2Resolved.isEmpty + && c3Resolved.isEmpty + && c4Resolved.isEmpty + && c5Resolved.isEmpty + && c6Resolved.isEmpty + && c7Resolved.isEmpty + && c8Resolved.isEmpty + + if noNewComponents { return } + + try merge(c1Resolved) + try merge(c2Resolved) + try merge(c3Resolved) + try merge(c4Resolved) + try merge(c5Resolved) + try merge(c6Resolved) + try merge(c7Resolved) + + try merge(c8Resolved) + + switch depth { + case .iterations(let number): + try await externallyDereference(in: context, depth: .iterations(number - 1)) + case .full: + try await externallyDereference(in: context, depth: .full) + } } } diff --git a/Sources/OpenAPIKit/Document/Document.swift b/Sources/OpenAPIKit/Document/Document.swift index c8eaa0afa..75a703363 100644 --- a/Sources/OpenAPIKit/Document/Document.swift +++ b/Sources/OpenAPIKit/Document/Document.swift @@ -324,6 +324,17 @@ extension OpenAPI.Document { } } +public enum ExternalDereferenceDepth { + case iterations(Int) + case full +} + +extension ExternalDereferenceDepth: ExpressibleByIntegerLiteral { + public init(integerLiteral value: Int) { + self = .iterations(value) + } +} + extension OpenAPI.Document { /// Create a locally-dereferenced OpenAPI /// Document. @@ -351,14 +362,15 @@ extension OpenAPI.Document { return try DereferencedDocument(self) } - public mutating func externallyDereference(in context: Context.Type, depth: Int = 1) async throws { - guard depth > 0 else { return } + public mutating func externallyDereference(in context: Context.Type, depth: ExternalDereferenceDepth = .iterations(1)) async throws { + if case let .iterations(number) = depth, + number <= 0 { + return + } let oldPaths = paths let oldWebhooks = webhooks - try await components.externallyDereference(in: context) - async let (newPaths, c1) = oldPaths.externallyDereferenced(with: context) async let (newWebhooks, c2) = oldWebhooks.externallyDereferenced(with: context) @@ -367,7 +379,7 @@ extension OpenAPI.Document { try await components.merge(c1) try await components.merge(c2) - try await externallyDereference(in: context, depth: depth - 1) + try await components.externallyDereference(in: context, depth: depth) } } diff --git a/Tests/OpenAPIKitTests/Document/DocumentTests.swift b/Tests/OpenAPIKitTests/Document/DocumentTests.swift index 6f1ba6761..7a57f642c 100644 --- a/Tests/OpenAPIKitTests/Document/DocumentTests.swift +++ b/Tests/OpenAPIKitTests/Document/DocumentTests.swift @@ -1264,7 +1264,11 @@ extension DocumentTests { var docCopy2 = document try await docCopy2.externallyDereference(in: ExampleLoader.self, depth: 2) - XCTAssertEqual(String(describing: docCopy1), String(describing: docCopy2)) + var docCopy3 = document + try await docCopy3.externallyDereference(in: ExampleLoader.self, depth: .full) + + XCTAssertEqual(docCopy1, docCopy2) + XCTAssertEqual(docCopy2, docCopy3) // - MARK: After print(