From 819ff665c45fb23aef617e7193c6a6b8c25250e7 Mon Sep 17 00:00:00 2001 From: Mathew Polzin Date: Thu, 23 Apr 2026 09:45:20 -0500 Subject: [PATCH 1/7] bump minimum swift version to 6.1. Add an as-yet-unimplemented trait for external file loading --- Package.swift | 9 ++++++++- README.md | 23 +++++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/Package.swift b/Package.swift index 104c8985b..85c54de8c 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 6.0 +// swift-tools-version: 6.1 import PackageDescription @@ -19,6 +19,13 @@ let package = Package( name: "OpenAPIKitCompat", targets: ["OpenAPIKitCompat"]), ], + traits: [ + .init( + name: "ExternalLoading", + description: "A framework that allows using OpenAPIKit for loading external JSON references into the Components Object. Building OpenAPKit with this capability is notably slower given its use of Swift Concurrency." + ), + .default(enabledTraits: ["ExternalLoading"]) + ], dependencies: [ .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"), .package(url: "https://github.com/jpsim/Yams.git", "6.0.0"..<"7.0.0") // just for tests diff --git a/README.md b/README.md index 68cdb1f18..8587caa2d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![sswg:sandbox|94x20](https://img.shields.io/badge/sswg-sandbox-lightgrey.svg)](https://github.com/swift-server/sswg/blob/master/process/incubation.md#sandbox-level) [![Swift 6.0+](http://img.shields.io/badge/Swift-6.0+-blue.svg)](https://swift.org) +[![sswg:sandbox|94x20](https://img.shields.io/badge/sswg-sandbox-lightgrey.svg)](https://github.com/swift-server/sswg/blob/master/process/incubation.md#sandbox-level) [![Swift 6.1+](http://img.shields.io/badge/Swift-6.1+-blue.svg)](https://swift.org) [![MIT license](http://img.shields.io/badge/license-MIT-lightgrey.svg)](http://opensource.org/licenses/MIT) ![Tests](https://github.com/mattpolzin/OpenAPIKit/actions/workflows/tests.yml/badge.svg?branch=main) @@ -18,7 +18,7 @@ versions and key features are supported by which OpenAPIKit versions. |------------|-------|--------------------|-----------------------------------|--------------| | v4.x | 5.8+ | ✅ | ✅ | | | v5.x | 5.10+ | ✅ | ✅ | ✅ | -| v6.x | 6.0+ | ✅ | ✅ | ✅ | +| v6.x | 6.1+ | ✅ | ✅ | ✅ | - [Usage](#usage) - [Migration](#migration) @@ -215,6 +215,25 @@ You could also call `oldDoc?.convert(to: .v3_1_4)` if you specifically wanted to work against a 3.1.x document for whatever reason (possibly because you wanted to reserialize the document at a 3.1.x version). +### Traits +The OpenAPIKit package offers an `"ExternalLoading"` trait that is enabled by +default. External Loading (i.e. loading multiple OpenAPI files in order to +resolve references between them) uses Swift Concurrency to parallelize loading +of each file. Swift Concurrency adds enough overhead to the compilation time of +OpenAPIKit that it might be worth disabling this trait if you do not need the +External Loading capability. Note that it is _compile time_ that takes a hit +from enabling External Loading, not _runtime speed_. + +To disable External Loading features, depend on OpenAPIKit with an empty +`traits` argument: +```swift +.package( + url: "https://github/com/mattpolzin/openapikit.git", + from: "6.0.0", + traits: [] +) +``` + ### A note on dictionary ordering The **Foundation** library's `JSONEncoder` and `JSONDecoder` do not make any guarantees about the ordering of keyed containers. This means decoding a JSON From 817e654a630800b7b2bfb16b9a8bf00f5259cf90 Mon Sep 17 00:00:00 2001 From: Mathew Polzin Date: Mon, 27 Apr 2026 09:48:41 -0500 Subject: [PATCH 2/7] implement ExternalLoading trait --- Sources/OpenAPIKit/Components Object/Components.swift | 2 ++ Sources/OpenAPIKit/Content/DereferencedContent.swift | 2 ++ Sources/OpenAPIKit/Content/DereferencedContentEncoding.swift | 2 ++ Sources/OpenAPIKit/Document/Document.swift | 2 ++ .../OpenAPIKit/Either/Either+ExternallyDereferenceable.swift | 2 ++ Sources/OpenAPIKit/Example/Example.swift | 2 ++ Sources/OpenAPIKit/ExternalLoader.swift | 2 ++ Sources/OpenAPIKit/Header/DereferencedHeader.swift | 2 ++ Sources/OpenAPIKit/JSONReference.swift | 4 ++++ Sources/OpenAPIKit/Link.swift | 2 ++ Sources/OpenAPIKit/Operation/DereferencedOperation.swift | 2 ++ Sources/OpenAPIKit/Parameter/DereferencedParameter.swift | 4 ++++ Sources/OpenAPIKit/Parameter/DereferencedSchemaContext.swift | 2 ++ Sources/OpenAPIKit/Path Item/DereferencedPathItem.swift | 2 ++ Sources/OpenAPIKit/Request/DereferencedRequest.swift | 2 ++ Sources/OpenAPIKit/Response/DereferencedResponse.swift | 2 ++ Sources/OpenAPIKit/Schema Object/DereferencedJSONSchema.swift | 2 ++ Sources/OpenAPIKit/Security/SecurityScheme.swift | 2 ++ Sources/OpenAPIKit/Server.swift | 2 ++ .../OpenAPIKit/Utility/Array+ExternallyDereferenceable.swift | 2 ++ .../Utility/Dictionary+ExternallyDereferenceable.swift | 2 ++ .../Utility/Optional+ExternallyDereferenceable.swift | 2 ++ .../Utility/OrderedDictionary+ExternallyDereferenceable.swift | 2 ++ Sources/OpenAPIKit30/Components Object/Components.swift | 2 ++ Sources/OpenAPIKit30/Content/DereferencedContent.swift | 2 ++ .../OpenAPIKit30/Content/DereferencedContentEncoding.swift | 2 ++ Sources/OpenAPIKit30/Document/Document.swift | 2 ++ .../Either/Either+ExternallyDereferenceable.swift | 2 ++ Sources/OpenAPIKit30/Example.swift | 2 ++ Sources/OpenAPIKit30/ExternalLoader.swift | 2 ++ Sources/OpenAPIKit30/Header/DereferencedHeader.swift | 2 ++ Sources/OpenAPIKit30/JSONReference.swift | 2 ++ Sources/OpenAPIKit30/Link.swift | 2 ++ Sources/OpenAPIKit30/Operation/DereferencedOperation.swift | 2 ++ Sources/OpenAPIKit30/Parameter/DereferencedParameter.swift | 2 ++ .../OpenAPIKit30/Parameter/DereferencedSchemaContext.swift | 2 ++ Sources/OpenAPIKit30/Path Item/DereferencedPathItem.swift | 2 ++ Sources/OpenAPIKit30/Request/DereferencedRequest.swift | 2 ++ Sources/OpenAPIKit30/Response/DereferencedResponse.swift | 2 ++ .../OpenAPIKit30/Schema Object/DereferencedJSONSchema.swift | 2 ++ Sources/OpenAPIKit30/Security/SecurityScheme.swift | 2 ++ Sources/OpenAPIKit30/Server.swift | 2 ++ .../Utility/Array+ExternallyDereferenceable.swift | 2 ++ .../Utility/Dictionary+ExternallyDereferenceable.swift | 2 ++ .../Utility/Optional+ExternallyDereferenceable.swift | 2 ++ .../Utility/OrderedDictionary+ExternallyDereferenceable.swift | 2 ++ 46 files changed, 96 insertions(+) diff --git a/Sources/OpenAPIKit/Components Object/Components.swift b/Sources/OpenAPIKit/Components Object/Components.swift index d2a0aa8a7..9f555b091 100644 --- a/Sources/OpenAPIKit/Components Object/Components.swift +++ b/Sources/OpenAPIKit/Components Object/Components.swift @@ -439,6 +439,7 @@ extension OpenAPI.Components { } extension OpenAPI.Components { +#if ExternalLoading internal mutating func externallyDereference(with loader: Loader.Type, depth: ExternalDereferenceDepth = .iterations(1), context: [Loader.Message] = []) async throws -> [Loader.Message] { if case let .iterations(number) = depth, number <= 0 { @@ -542,6 +543,7 @@ extension OpenAPI.Components { return try await externallyDereference(with: loader, depth: .full, context: newMessages) } } +#endif } extension OpenAPI.Components: Validatable {} diff --git a/Sources/OpenAPIKit/Content/DereferencedContent.swift b/Sources/OpenAPIKit/Content/DereferencedContent.swift index 9160b5b35..c31d8e2cd 100644 --- a/Sources/OpenAPIKit/Content/DereferencedContent.swift +++ b/Sources/OpenAPIKit/Content/DereferencedContent.swift @@ -96,6 +96,7 @@ extension OpenAPI.Content: LocallyDereferenceable { } extension OpenAPI.Content: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let oldSchema = schema let oldItemSchema = itemSchema @@ -140,4 +141,5 @@ extension OpenAPI.Content: ExternallyDereferenceable { return (newContent, newComponents, newMessages) } +#endif } diff --git a/Sources/OpenAPIKit/Content/DereferencedContentEncoding.swift b/Sources/OpenAPIKit/Content/DereferencedContentEncoding.swift index b715e7ac7..2525e00f9 100644 --- a/Sources/OpenAPIKit/Content/DereferencedContentEncoding.swift +++ b/Sources/OpenAPIKit/Content/DereferencedContentEncoding.swift @@ -58,6 +58,7 @@ extension OpenAPI.Content.Encoding: LocallyDereferenceable { } extension OpenAPI.Content.Encoding: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let newHeaders: OpenAPI.Header.Map? let newComponents: OpenAPI.Components @@ -81,4 +82,5 @@ extension OpenAPI.Content.Encoding: ExternallyDereferenceable { return (newEncoding, newComponents, newMessages) } +#endif } diff --git a/Sources/OpenAPIKit/Document/Document.swift b/Sources/OpenAPIKit/Document/Document.swift index 94e1d9100..8c1936ed9 100644 --- a/Sources/OpenAPIKit/Document/Document.swift +++ b/Sources/OpenAPIKit/Document/Document.swift @@ -398,6 +398,7 @@ extension OpenAPI.Document { return try DereferencedDocument(self) } +#if ExternalLoading /// Load all remote references into the document. A remote reference is one /// that points to another file rather than a location within the /// same file. @@ -437,6 +438,7 @@ extension OpenAPI.Document { return try await context + m1 + m2 + m3 } +#endif } extension OpenAPI { diff --git a/Sources/OpenAPIKit/Either/Either+ExternallyDereferenceable.swift b/Sources/OpenAPIKit/Either/Either+ExternallyDereferenceable.swift index 62c919355..fc3638565 100644 --- a/Sources/OpenAPIKit/Either/Either+ExternallyDereferenceable.swift +++ b/Sources/OpenAPIKit/Either/Either+ExternallyDereferenceable.swift @@ -10,6 +10,7 @@ import OpenAPIKitCore // MARK: - ExternallyDereferenceable extension Either: ExternallyDereferenceable where A: ExternallyDereferenceable, B: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { switch self { case .a(let a): @@ -20,4 +21,5 @@ extension Either: ExternallyDereferenceable where A: ExternallyDereferenceable, return (.b(newB), components, messages) } } +#endif } diff --git a/Sources/OpenAPIKit/Example/Example.swift b/Sources/OpenAPIKit/Example/Example.swift index f609be708..0f3d955cf 100644 --- a/Sources/OpenAPIKit/Example/Example.swift +++ b/Sources/OpenAPIKit/Example/Example.swift @@ -394,9 +394,11 @@ extension OpenAPI.Example: LocallyDereferenceable { } extension OpenAPI.Example: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { return (self, .init(), []) } +#endif } extension OpenAPI.Example: Validatable {} diff --git a/Sources/OpenAPIKit/ExternalLoader.swift b/Sources/OpenAPIKit/ExternalLoader.swift index c67b8eb5c..a63a7f2a0 100644 --- a/Sources/OpenAPIKit/ExternalLoader.swift +++ b/Sources/OpenAPIKit/ExternalLoader.swift @@ -49,5 +49,7 @@ public protocol ExternalLoader: _ExternalLoaderMetatype where Message: Sendable } public protocol ExternallyDereferenceable { +#if ExternalLoading func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) +#endif } diff --git a/Sources/OpenAPIKit/Header/DereferencedHeader.swift b/Sources/OpenAPIKit/Header/DereferencedHeader.swift index 0972264e3..93c7976d3 100644 --- a/Sources/OpenAPIKit/Header/DereferencedHeader.swift +++ b/Sources/OpenAPIKit/Header/DereferencedHeader.swift @@ -84,6 +84,7 @@ extension OpenAPI.Header: LocallyDereferenceable { } extension OpenAPI.Header: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { // if not for a Swift bug, this whole next bit would just be the @@ -117,4 +118,5 @@ extension OpenAPI.Header: ExternallyDereferenceable { return (newHeader, newComponents, newMessages) } +#endif } diff --git a/Sources/OpenAPIKit/JSONReference.swift b/Sources/OpenAPIKit/JSONReference.swift index d89de9959..fcf7e0119 100644 --- a/Sources/OpenAPIKit/JSONReference.swift +++ b/Sources/OpenAPIKit/JSONReference.swift @@ -602,6 +602,7 @@ extension JSONReference: LocallyDereferenceable where ReferenceType: LocallyDere } extension JSONReference: ExternallyDereferenceable where ReferenceType: ExternallyDereferenceable & Decodable & Equatable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { switch self { case .internal(let ref): @@ -619,6 +620,7 @@ extension JSONReference: ExternallyDereferenceable where ReferenceType: External return (try components.reference(named: componentKey.rawValue, ofType: ReferenceType.self).jsonReference, components, messages) } } +#endif } extension OpenAPI.Reference: LocallyDereferenceable where ReferenceType: LocallyDereferenceable { @@ -649,10 +651,12 @@ extension OpenAPI.Reference: LocallyDereferenceable where ReferenceType: Locally } extension OpenAPI.Reference: ExternallyDereferenceable where ReferenceType: ExternallyDereferenceable & Decodable & Equatable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let (newRef, components, messages) = try await jsonReference.externallyDereferenced(with: loader) return (.init(newRef), components, messages) } +#endif } extension OpenAPI.Reference: Validatable where ReferenceType: Validatable {} diff --git a/Sources/OpenAPIKit/Link.swift b/Sources/OpenAPIKit/Link.swift index 4b393cf25..d1ddd871a 100644 --- a/Sources/OpenAPIKit/Link.swift +++ b/Sources/OpenAPIKit/Link.swift @@ -294,6 +294,7 @@ extension OpenAPI.Link: LocallyDereferenceable { } extension OpenAPI.Link: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let (newServer, newComponents, newMessages) = try await server.externallyDereferenced(with: loader) @@ -302,6 +303,7 @@ extension OpenAPI.Link: ExternallyDereferenceable { return (newLink, newComponents, newMessages) } +#endif } extension OpenAPI.Link: Validatable {} diff --git a/Sources/OpenAPIKit/Operation/DereferencedOperation.swift b/Sources/OpenAPIKit/Operation/DereferencedOperation.swift index 3a4347a19..ccade944a 100644 --- a/Sources/OpenAPIKit/Operation/DereferencedOperation.swift +++ b/Sources/OpenAPIKit/Operation/DereferencedOperation.swift @@ -126,6 +126,7 @@ extension OpenAPI.Operation: LocallyDereferenceable { } extension OpenAPI.Operation: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let oldParameters = parameters let oldRequestBody = requestBody @@ -162,4 +163,5 @@ extension OpenAPI.Operation: ExternallyDereferenceable { return (newOperation, newComponents, newMessages) } +#endif } diff --git a/Sources/OpenAPIKit/Parameter/DereferencedParameter.swift b/Sources/OpenAPIKit/Parameter/DereferencedParameter.swift index 963eb7487..1611a1d93 100644 --- a/Sources/OpenAPIKit/Parameter/DereferencedParameter.swift +++ b/Sources/OpenAPIKit/Parameter/DereferencedParameter.swift @@ -84,6 +84,7 @@ extension OpenAPI.Parameter: LocallyDereferenceable { } extension OpenAPI.Parameter: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { // if not for a Swift bug, this whole function would just be the @@ -131,8 +132,10 @@ extension OpenAPI.Parameter: ExternallyDereferenceable { return (newParameter, newComponents, newMessages) } +#endif } +#if ExternalLoading fileprivate func externallyDereference( schemaOrContent: Either, with loader: Loader.Type @@ -146,3 +149,4 @@ fileprivate func externallyDereference( return (.b(map), components, messages) } } +#endif diff --git a/Sources/OpenAPIKit/Parameter/DereferencedSchemaContext.swift b/Sources/OpenAPIKit/Parameter/DereferencedSchemaContext.swift index 66a4ac06a..3eb4e4ab4 100644 --- a/Sources/OpenAPIKit/Parameter/DereferencedSchemaContext.swift +++ b/Sources/OpenAPIKit/Parameter/DereferencedSchemaContext.swift @@ -71,6 +71,7 @@ extension OpenAPI.Parameter.SchemaContext: LocallyDereferenceable { } extension OpenAPI.Parameter.SchemaContext: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let oldSchema = schema @@ -91,4 +92,5 @@ extension OpenAPI.Parameter.SchemaContext: ExternallyDereferenceable { return (newSchemaContext, newComponents, newMessages) } +#endif } diff --git a/Sources/OpenAPIKit/Path Item/DereferencedPathItem.swift b/Sources/OpenAPIKit/Path Item/DereferencedPathItem.swift index 8bddb1ab7..9e514e46f 100644 --- a/Sources/OpenAPIKit/Path Item/DereferencedPathItem.swift +++ b/Sources/OpenAPIKit/Path Item/DereferencedPathItem.swift @@ -152,6 +152,7 @@ extension OpenAPI.PathItem: LocallyDereferenceable { } extension OpenAPI.PathItem: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let oldParameters = parameters let oldServers = servers @@ -231,4 +232,5 @@ extension OpenAPI.PathItem: ExternallyDereferenceable { return (pathItem, newComponents, newMessages) } +#endif } diff --git a/Sources/OpenAPIKit/Request/DereferencedRequest.swift b/Sources/OpenAPIKit/Request/DereferencedRequest.swift index 36d802767..e97bbafbf 100644 --- a/Sources/OpenAPIKit/Request/DereferencedRequest.swift +++ b/Sources/OpenAPIKit/Request/DereferencedRequest.swift @@ -63,6 +63,7 @@ extension OpenAPI.Request: LocallyDereferenceable { } extension OpenAPI.Request: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { var newRequest = self @@ -71,4 +72,5 @@ extension OpenAPI.Request: ExternallyDereferenceable { newRequest.content = newContent return (newRequest, components, messages) } +#endif } diff --git a/Sources/OpenAPIKit/Response/DereferencedResponse.swift b/Sources/OpenAPIKit/Response/DereferencedResponse.swift index 702da8765..ad501303e 100644 --- a/Sources/OpenAPIKit/Response/DereferencedResponse.swift +++ b/Sources/OpenAPIKit/Response/DereferencedResponse.swift @@ -78,6 +78,7 @@ extension OpenAPI.Response: LocallyDereferenceable { } extension OpenAPI.Response: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let oldContent = content let oldLinks = links @@ -105,4 +106,5 @@ extension OpenAPI.Response: ExternallyDereferenceable { return (response, components, messages) } +#endif } diff --git a/Sources/OpenAPIKit/Schema Object/DereferencedJSONSchema.swift b/Sources/OpenAPIKit/Schema Object/DereferencedJSONSchema.swift index 1e146f1ff..77e46c866 100644 --- a/Sources/OpenAPIKit/Schema Object/DereferencedJSONSchema.swift +++ b/Sources/OpenAPIKit/Schema Object/DereferencedJSONSchema.swift @@ -539,6 +539,7 @@ extension JSONSchema: LocallyDereferenceable { } extension JSONSchema: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let newSchema: JSONSchema let newComponents: OpenAPI.Components @@ -653,4 +654,5 @@ extension JSONSchema: ExternallyDereferenceable { return (newSchema, newComponents, newMessages) } +#endif } diff --git a/Sources/OpenAPIKit/Security/SecurityScheme.swift b/Sources/OpenAPIKit/Security/SecurityScheme.swift index 675c73c1f..4e26391b8 100644 --- a/Sources/OpenAPIKit/Security/SecurityScheme.swift +++ b/Sources/OpenAPIKit/Security/SecurityScheme.swift @@ -341,9 +341,11 @@ extension OpenAPI.SecurityScheme: LocallyDereferenceable { } extension OpenAPI.SecurityScheme: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { return (self, .init(), []) } +#endif } extension OpenAPI.SecurityScheme: Validatable {} diff --git a/Sources/OpenAPIKit/Server.swift b/Sources/OpenAPIKit/Server.swift index e527876b1..c0f413e46 100644 --- a/Sources/OpenAPIKit/Server.swift +++ b/Sources/OpenAPIKit/Server.swift @@ -304,9 +304,11 @@ extension OpenAPI.Server.Variable { } extension OpenAPI.Server: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { return (self, .init(), []) } +#endif } extension OpenAPI.Server: Validatable {} diff --git a/Sources/OpenAPIKit/Utility/Array+ExternallyDereferenceable.swift b/Sources/OpenAPIKit/Utility/Array+ExternallyDereferenceable.swift index ca1f3dd54..f1e6d84a2 100644 --- a/Sources/OpenAPIKit/Utility/Array+ExternallyDereferenceable.swift +++ b/Sources/OpenAPIKit/Utility/Array+ExternallyDereferenceable.swift @@ -6,6 +6,7 @@ import OpenAPIKitCore extension Array where Element: ExternallyDereferenceable & Sendable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { try await withThrowingTaskGroup(of: (Int, (Element, OpenAPI.Components, [Loader.Message])).self) { group in for (idx, elem) in zip(self.indices, self) { @@ -29,4 +30,5 @@ extension Array where Element: ExternallyDereferenceable & Sendable { return (newElems.map { $0.1 }, newComponents, newMessages) } } +#endif } diff --git a/Sources/OpenAPIKit/Utility/Dictionary+ExternallyDereferenceable.swift b/Sources/OpenAPIKit/Utility/Dictionary+ExternallyDereferenceable.swift index 0bc061a0f..4168ecd58 100644 --- a/Sources/OpenAPIKit/Utility/Dictionary+ExternallyDereferenceable.swift +++ b/Sources/OpenAPIKit/Utility/Dictionary+ExternallyDereferenceable.swift @@ -7,6 +7,7 @@ import OpenAPIKitCore extension Dictionary where Key: Sendable, Value: ExternallyDereferenceable & Sendable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { try await withThrowingTaskGroup(of: (Key, Value, OpenAPI.Components, [Loader.Message]).self) { group in for (key, value) in self { @@ -28,4 +29,5 @@ extension Dictionary where Key: Sendable, Value: ExternallyDereferenceable & Sen return (newDict, newComponents, newMessage) } } +#endif } diff --git a/Sources/OpenAPIKit/Utility/Optional+ExternallyDereferenceable.swift b/Sources/OpenAPIKit/Utility/Optional+ExternallyDereferenceable.swift index 87c7a0649..fa1f916be 100644 --- a/Sources/OpenAPIKit/Utility/Optional+ExternallyDereferenceable.swift +++ b/Sources/OpenAPIKit/Utility/Optional+ExternallyDereferenceable.swift @@ -6,8 +6,10 @@ import OpenAPIKitCore extension Optional where Wrapped: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { guard let wrapped = self else { return (nil, .init(), []) } return try await wrapped.externallyDereferenced(with: loader) } +#endif } diff --git a/Sources/OpenAPIKit/Utility/OrderedDictionary+ExternallyDereferenceable.swift b/Sources/OpenAPIKit/Utility/OrderedDictionary+ExternallyDereferenceable.swift index 66e78ab4f..62d94b506 100644 --- a/Sources/OpenAPIKit/Utility/OrderedDictionary+ExternallyDereferenceable.swift +++ b/Sources/OpenAPIKit/Utility/OrderedDictionary+ExternallyDereferenceable.swift @@ -9,6 +9,7 @@ import OpenAPIKitCore extension OrderedDictionary where Key: Sendable, Value: ExternallyDereferenceable & Sendable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { try await withThrowingTaskGroup(of: (Key, Value, OpenAPI.Components, [Loader.Message]).self) { group in for (key, value) in self { @@ -33,4 +34,5 @@ extension OrderedDictionary where Key: Sendable, Value: ExternallyDereferenceabl return (newDict, newComponents, newMessages) } } +#endif } diff --git a/Sources/OpenAPIKit30/Components Object/Components.swift b/Sources/OpenAPIKit30/Components Object/Components.swift index ad266bf13..8a65441e4 100644 --- a/Sources/OpenAPIKit30/Components Object/Components.swift +++ b/Sources/OpenAPIKit30/Components Object/Components.swift @@ -316,6 +316,7 @@ extension OpenAPI.Components { } extension OpenAPI.Components { +#if ExternalLoading internal mutating func externallyDereference(with loader: Loader.Type, depth: ExternalDereferenceDepth = .iterations(1), context: [Loader.Message] = []) async throws -> [Loader.Message] { if case let .iterations(number) = depth, number <= 0 { @@ -413,6 +414,7 @@ extension OpenAPI.Components { return try await externallyDereference(with: loader, depth: .full, context: newMessages) } } +#endif } extension OpenAPI.Components: Validatable {} diff --git a/Sources/OpenAPIKit30/Content/DereferencedContent.swift b/Sources/OpenAPIKit30/Content/DereferencedContent.swift index ebfa10f07..60cd2839e 100644 --- a/Sources/OpenAPIKit30/Content/DereferencedContent.swift +++ b/Sources/OpenAPIKit30/Content/DereferencedContent.swift @@ -77,6 +77,7 @@ extension OpenAPI.Content: LocallyDereferenceable { } extension OpenAPI.Content: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let oldSchema = schema @@ -104,4 +105,5 @@ extension OpenAPI.Content: ExternallyDereferenceable { return (newContent, newComponents, newMessages) } +#endif } diff --git a/Sources/OpenAPIKit30/Content/DereferencedContentEncoding.swift b/Sources/OpenAPIKit30/Content/DereferencedContentEncoding.swift index aaa9a1fd5..19c11c25a 100644 --- a/Sources/OpenAPIKit30/Content/DereferencedContentEncoding.swift +++ b/Sources/OpenAPIKit30/Content/DereferencedContentEncoding.swift @@ -58,6 +58,7 @@ extension OpenAPI.Content.Encoding: LocallyDereferenceable { } extension OpenAPI.Content.Encoding: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let newHeaders: OpenAPI.Header.Map? let newComponents: OpenAPI.Components @@ -81,4 +82,5 @@ extension OpenAPI.Content.Encoding: ExternallyDereferenceable { return (newEncoding, newComponents, newMessages) } +#endif } diff --git a/Sources/OpenAPIKit30/Document/Document.swift b/Sources/OpenAPIKit30/Document/Document.swift index a47cafaee..f5935b4fa 100644 --- a/Sources/OpenAPIKit30/Document/Document.swift +++ b/Sources/OpenAPIKit30/Document/Document.swift @@ -351,6 +351,7 @@ extension OpenAPI.Document { return try DereferencedDocument(self) } +#if ExternalLoading /// Load all remote references into the document. A remote reference is one /// that points to another file rather than a location within the /// same file. @@ -386,6 +387,7 @@ extension OpenAPI.Document { return try await context + m1 + m2 } +#endif } extension OpenAPI { diff --git a/Sources/OpenAPIKit30/Either/Either+ExternallyDereferenceable.swift b/Sources/OpenAPIKit30/Either/Either+ExternallyDereferenceable.swift index 62c919355..fc3638565 100644 --- a/Sources/OpenAPIKit30/Either/Either+ExternallyDereferenceable.swift +++ b/Sources/OpenAPIKit30/Either/Either+ExternallyDereferenceable.swift @@ -10,6 +10,7 @@ import OpenAPIKitCore // MARK: - ExternallyDereferenceable extension Either: ExternallyDereferenceable where A: ExternallyDereferenceable, B: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { switch self { case .a(let a): @@ -20,4 +21,5 @@ extension Either: ExternallyDereferenceable where A: ExternallyDereferenceable, return (.b(newB), components, messages) } } +#endif } diff --git a/Sources/OpenAPIKit30/Example.swift b/Sources/OpenAPIKit30/Example.swift index 2add5a313..e145d39ac 100644 --- a/Sources/OpenAPIKit30/Example.swift +++ b/Sources/OpenAPIKit30/Example.swift @@ -189,9 +189,11 @@ extension OpenAPI.Example: LocallyDereferenceable { } extension OpenAPI.Example: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { return (self, .init(), []) } +#endif } extension OpenAPI.Example: Validatable {} diff --git a/Sources/OpenAPIKit30/ExternalLoader.swift b/Sources/OpenAPIKit30/ExternalLoader.swift index c67b8eb5c..a63a7f2a0 100644 --- a/Sources/OpenAPIKit30/ExternalLoader.swift +++ b/Sources/OpenAPIKit30/ExternalLoader.swift @@ -49,5 +49,7 @@ public protocol ExternalLoader: _ExternalLoaderMetatype where Message: Sendable } public protocol ExternallyDereferenceable { +#if ExternalLoading func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) +#endif } diff --git a/Sources/OpenAPIKit30/Header/DereferencedHeader.swift b/Sources/OpenAPIKit30/Header/DereferencedHeader.swift index 40509234a..bb90a24f1 100644 --- a/Sources/OpenAPIKit30/Header/DereferencedHeader.swift +++ b/Sources/OpenAPIKit30/Header/DereferencedHeader.swift @@ -84,6 +84,7 @@ extension OpenAPI.Header: LocallyDereferenceable { } extension OpenAPI.Header: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { // if not for a Swift bug, this whole next bit would just be the @@ -117,4 +118,5 @@ extension OpenAPI.Header: ExternallyDereferenceable { return (newHeader, newComponents, newMessages) } +#endif } diff --git a/Sources/OpenAPIKit30/JSONReference.swift b/Sources/OpenAPIKit30/JSONReference.swift index 5c9b211a4..0574a2b8a 100644 --- a/Sources/OpenAPIKit30/JSONReference.swift +++ b/Sources/OpenAPIKit30/JSONReference.swift @@ -389,6 +389,7 @@ extension JSONReference: LocallyDereferenceable where ReferenceType: LocallyDere // MARK: - ExternallyDereferenceable extension JSONReference: ExternallyDereferenceable where ReferenceType: ExternallyDereferenceable & Decodable & Equatable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { switch self { case .internal(let ref): @@ -401,6 +402,7 @@ extension JSONReference: ExternallyDereferenceable where ReferenceType: External return (try components.reference(named: componentKey.rawValue, ofType: ReferenceType.self), components, messages) } } +#endif } extension JSONReference: Validatable where ReferenceType: Validatable {} diff --git a/Sources/OpenAPIKit30/Link.swift b/Sources/OpenAPIKit30/Link.swift index 790450e77..4ed6e2059 100644 --- a/Sources/OpenAPIKit30/Link.swift +++ b/Sources/OpenAPIKit30/Link.swift @@ -283,6 +283,7 @@ extension OpenAPI.Link: LocallyDereferenceable { } extension OpenAPI.Link: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let (newServer, newComponents, newMessages) = try await server.externallyDereferenced(with: loader) @@ -291,6 +292,7 @@ extension OpenAPI.Link: ExternallyDereferenceable { return (newLink, newComponents, newMessages) } +#endif } extension OpenAPI.Link: Validatable {} diff --git a/Sources/OpenAPIKit30/Operation/DereferencedOperation.swift b/Sources/OpenAPIKit30/Operation/DereferencedOperation.swift index a9daeb843..f77021c9f 100644 --- a/Sources/OpenAPIKit30/Operation/DereferencedOperation.swift +++ b/Sources/OpenAPIKit30/Operation/DereferencedOperation.swift @@ -126,6 +126,7 @@ extension OpenAPI.Operation: LocallyDereferenceable { } extension OpenAPI.Operation: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let oldParameters = parameters let oldRequestBody = requestBody @@ -164,4 +165,5 @@ extension OpenAPI.Operation: ExternallyDereferenceable { return (newOperation, newComponents, newMessages) } +#endif } diff --git a/Sources/OpenAPIKit30/Parameter/DereferencedParameter.swift b/Sources/OpenAPIKit30/Parameter/DereferencedParameter.swift index acb30c8d2..e4e88318d 100644 --- a/Sources/OpenAPIKit30/Parameter/DereferencedParameter.swift +++ b/Sources/OpenAPIKit30/Parameter/DereferencedParameter.swift @@ -84,6 +84,7 @@ extension OpenAPI.Parameter: LocallyDereferenceable { } extension OpenAPI.Parameter: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { // if not for a Swift bug, this whole function would just be the @@ -112,4 +113,5 @@ extension OpenAPI.Parameter: ExternallyDereferenceable { return (newParameter, newComponents, newMessages) } +#endif } diff --git a/Sources/OpenAPIKit30/Parameter/DereferencedSchemaContext.swift b/Sources/OpenAPIKit30/Parameter/DereferencedSchemaContext.swift index 9a035f1e7..545c55935 100644 --- a/Sources/OpenAPIKit30/Parameter/DereferencedSchemaContext.swift +++ b/Sources/OpenAPIKit30/Parameter/DereferencedSchemaContext.swift @@ -70,6 +70,7 @@ extension OpenAPI.Parameter.SchemaContext: LocallyDereferenceable { } extension OpenAPI.Parameter.SchemaContext: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let oldSchema = schema @@ -90,4 +91,5 @@ extension OpenAPI.Parameter.SchemaContext: ExternallyDereferenceable { return (newSchemaContext, newComponents, newMessages) } +#endif } diff --git a/Sources/OpenAPIKit30/Path Item/DereferencedPathItem.swift b/Sources/OpenAPIKit30/Path Item/DereferencedPathItem.swift index ae9d6e3be..6388a64c4 100644 --- a/Sources/OpenAPIKit30/Path Item/DereferencedPathItem.swift +++ b/Sources/OpenAPIKit30/Path Item/DereferencedPathItem.swift @@ -141,6 +141,7 @@ extension OpenAPI.PathItem: LocallyDereferenceable { } extension OpenAPI.PathItem: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let oldParameters = parameters let oldServers = servers @@ -208,4 +209,5 @@ extension OpenAPI.PathItem: ExternallyDereferenceable { return (pathItem, newComponents, newMessages) } +#endif } diff --git a/Sources/OpenAPIKit30/Request/DereferencedRequest.swift b/Sources/OpenAPIKit30/Request/DereferencedRequest.swift index 6c7fd3189..8b8c26352 100644 --- a/Sources/OpenAPIKit30/Request/DereferencedRequest.swift +++ b/Sources/OpenAPIKit30/Request/DereferencedRequest.swift @@ -63,6 +63,7 @@ extension OpenAPI.Request: LocallyDereferenceable { } extension OpenAPI.Request: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { var newRequest = self @@ -71,4 +72,5 @@ extension OpenAPI.Request: ExternallyDereferenceable { newRequest.content = newContent return (newRequest, components, messages) } +#endif } diff --git a/Sources/OpenAPIKit30/Response/DereferencedResponse.swift b/Sources/OpenAPIKit30/Response/DereferencedResponse.swift index ced58ae20..c25078079 100644 --- a/Sources/OpenAPIKit30/Response/DereferencedResponse.swift +++ b/Sources/OpenAPIKit30/Response/DereferencedResponse.swift @@ -78,6 +78,7 @@ extension OpenAPI.Response: LocallyDereferenceable { } extension OpenAPI.Response: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let oldContent = content let oldLinks = links @@ -106,4 +107,5 @@ extension OpenAPI.Response: ExternallyDereferenceable { return (response, components, messages) } +#endif } diff --git a/Sources/OpenAPIKit30/Schema Object/DereferencedJSONSchema.swift b/Sources/OpenAPIKit30/Schema Object/DereferencedJSONSchema.swift index 496ec328e..814ff72fa 100644 --- a/Sources/OpenAPIKit30/Schema Object/DereferencedJSONSchema.swift +++ b/Sources/OpenAPIKit30/Schema Object/DereferencedJSONSchema.swift @@ -410,6 +410,7 @@ extension JSONSchema: LocallyDereferenceable { } extension JSONSchema: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { let newSchema: JSONSchema let newComponents: OpenAPI.Components @@ -527,4 +528,5 @@ extension JSONSchema: ExternallyDereferenceable { return (newSchema, newComponents, newMessages) } +#endif } diff --git a/Sources/OpenAPIKit30/Security/SecurityScheme.swift b/Sources/OpenAPIKit30/Security/SecurityScheme.swift index cc3920d62..b1621e867 100644 --- a/Sources/OpenAPIKit30/Security/SecurityScheme.swift +++ b/Sources/OpenAPIKit30/Security/SecurityScheme.swift @@ -256,9 +256,11 @@ extension OpenAPI.SecurityScheme: LocallyDereferenceable { } extension OpenAPI.SecurityScheme: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { return (self, .init(), []) } +#endif } extension OpenAPI.SecurityScheme.SecurityType.Name: Validatable {} diff --git a/Sources/OpenAPIKit30/Server.swift b/Sources/OpenAPIKit30/Server.swift index 81c7e6c6c..dc2174dd4 100644 --- a/Sources/OpenAPIKit30/Server.swift +++ b/Sources/OpenAPIKit30/Server.swift @@ -253,9 +253,11 @@ extension OpenAPI.Server.Variable { } extension OpenAPI.Server: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { return (self, .init(), []) } +#endif } extension OpenAPI.Server: Validatable {} diff --git a/Sources/OpenAPIKit30/Utility/Array+ExternallyDereferenceable.swift b/Sources/OpenAPIKit30/Utility/Array+ExternallyDereferenceable.swift index ca1f3dd54..f1e6d84a2 100644 --- a/Sources/OpenAPIKit30/Utility/Array+ExternallyDereferenceable.swift +++ b/Sources/OpenAPIKit30/Utility/Array+ExternallyDereferenceable.swift @@ -6,6 +6,7 @@ import OpenAPIKitCore extension Array where Element: ExternallyDereferenceable & Sendable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { try await withThrowingTaskGroup(of: (Int, (Element, OpenAPI.Components, [Loader.Message])).self) { group in for (idx, elem) in zip(self.indices, self) { @@ -29,4 +30,5 @@ extension Array where Element: ExternallyDereferenceable & Sendable { return (newElems.map { $0.1 }, newComponents, newMessages) } } +#endif } diff --git a/Sources/OpenAPIKit30/Utility/Dictionary+ExternallyDereferenceable.swift b/Sources/OpenAPIKit30/Utility/Dictionary+ExternallyDereferenceable.swift index 16ddfcd8d..c25600481 100644 --- a/Sources/OpenAPIKit30/Utility/Dictionary+ExternallyDereferenceable.swift +++ b/Sources/OpenAPIKit30/Utility/Dictionary+ExternallyDereferenceable.swift @@ -7,6 +7,7 @@ import OpenAPIKitCore extension Dictionary where Key: Sendable, Value: ExternallyDereferenceable & Sendable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { try await withThrowingTaskGroup(of: (Key, Value, OpenAPI.Components, [Loader.Message]).self) { group in for (key, value) in self { @@ -28,4 +29,5 @@ extension Dictionary where Key: Sendable, Value: ExternallyDereferenceable & Sen return (newDict, newComponents, newMessages) } } +#endif } diff --git a/Sources/OpenAPIKit30/Utility/Optional+ExternallyDereferenceable.swift b/Sources/OpenAPIKit30/Utility/Optional+ExternallyDereferenceable.swift index 87c7a0649..fa1f916be 100644 --- a/Sources/OpenAPIKit30/Utility/Optional+ExternallyDereferenceable.swift +++ b/Sources/OpenAPIKit30/Utility/Optional+ExternallyDereferenceable.swift @@ -6,8 +6,10 @@ import OpenAPIKitCore extension Optional where Wrapped: ExternallyDereferenceable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { guard let wrapped = self else { return (nil, .init(), []) } return try await wrapped.externallyDereferenced(with: loader) } +#endif } diff --git a/Sources/OpenAPIKit30/Utility/OrderedDictionary+ExternallyDereferenceable.swift b/Sources/OpenAPIKit30/Utility/OrderedDictionary+ExternallyDereferenceable.swift index 66e78ab4f..62d94b506 100644 --- a/Sources/OpenAPIKit30/Utility/OrderedDictionary+ExternallyDereferenceable.swift +++ b/Sources/OpenAPIKit30/Utility/OrderedDictionary+ExternallyDereferenceable.swift @@ -9,6 +9,7 @@ import OpenAPIKitCore extension OrderedDictionary where Key: Sendable, Value: ExternallyDereferenceable & Sendable { +#if ExternalLoading public func externallyDereferenced(with loader: Loader.Type) async throws -> (Self, OpenAPI.Components, [Loader.Message]) { try await withThrowingTaskGroup(of: (Key, Value, OpenAPI.Components, [Loader.Message]).self) { group in for (key, value) in self { @@ -33,4 +34,5 @@ extension OrderedDictionary where Key: Sendable, Value: ExternallyDereferenceabl return (newDict, newComponents, newMessages) } } +#endif } From daa157edf65bdb14c3c9fec2b92bcd1bbd098501 Mon Sep 17 00:00:00 2001 From: Mathew Polzin Date: Mon, 27 Apr 2026 10:09:16 -0500 Subject: [PATCH 3/7] build and test without default traits in CI --- .github/workflows/traits.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/workflows/traits.yml diff --git a/.github/workflows/traits.yml b/.github/workflows/traits.yml new file mode 100644 index 000000000..6a89e3c4a --- /dev/null +++ b/.github/workflows/traits.yml @@ -0,0 +1,12 @@ +name: Traits + +on: [pull_request] + +jobs: + without-default-traits: + container: + image: swift:6.3 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - run: swift test --enable-test-discovery --disable-default-traits From c579ecbeeb004c7d1c61ebff70148ee8b826c551 Mon Sep 17 00:00:00 2001 From: Mathew Polzin Date: Mon, 27 Apr 2026 10:10:55 -0500 Subject: [PATCH 4/7] update Swift versions in CI test matrix --- .github/workflows/tests.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1f9091a79..aede3cd7f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,16 +13,15 @@ jobs: fail-fast: false matrix: image: - - swift:6.0-focal - - swift:6.0-jammy - - swift:6.0-noble - swift:6.1-focal - swift:6.1-jammy - swift:6.1-noble - swift:6.2-jammy - swift:6.2-noble + - swift:6.3-jammy + - swift:6.3-noble - swiftlang/swift:nightly-focal -# - swiftlang/swift:nightly-jammy + - swiftlang/swift:nightly-jammy container: ${{ matrix.image }} steps: - name: Checkout code From 7251ab95c297528719b898984175b0706442ad82 Mon Sep 17 00:00:00 2001 From: Mathew Polzin Date: Mon, 27 Apr 2026 10:36:35 -0500 Subject: [PATCH 5/7] replace unannotated warning/error with an annotated warning --- .../OrderedDictionary/OrderedDictionary.swift | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Sources/OpenAPIKitCore/OrderedDictionary/OrderedDictionary.swift b/Sources/OpenAPIKitCore/OrderedDictionary/OrderedDictionary.swift index 1b9eedf8b..c8ac0859d 100644 --- a/Sources/OpenAPIKitCore/OrderedDictionary/OrderedDictionary.swift +++ b/Sources/OpenAPIKitCore/OrderedDictionary/OrderedDictionary.swift @@ -282,14 +282,14 @@ extension OrderedDictionary: Sendable where Key: Sendable, Value: Sendable {} public struct AnyCodingKey: CodingKey { public let stringValue: String - public let originalValue: Any + public let originalValue: any Sendable public init(stringValue: String) { self.stringValue = stringValue self.originalValue = stringValue } - public init(stringValue: String, originalValue: Any) { + public init(stringValue: String, originalValue: any Sendable) { self.stringValue = stringValue self.originalValue = originalValue } @@ -375,14 +375,20 @@ internal func encodeKeyValuePairs( /// Encode a sequence of `String`/`Value` pairs as a hash keeping track of the /// original RawRepresentable values. -internal func encodeKeyValuePairs( +internal func encodeKeyValuePairs ( _ keyValuePairs: Zip2Sequence, [Value]>, to encoder: Encoder ) throws { var container = encoder.container(keyedBy: AnyCodingKey.self) for (key, value) in keyValuePairs { - try container.encode(value, forKey: .init(stringValue: key.1, originalValue: key.0)) + // NOTE: This is a bit of a hack -- Because OrderedDictionary is used + // internally but not meant to be vendored to downstream projects for + // arbitrary use outside of OpenAPIKit types, we do know that all Keys + //are sendable. It is just difficult to prove that to the compiler so + // I will have to work at that later. + let anyValue = (key.0 as Any) as! any Sendable + try container.encode(value, forKey: .init(stringValue: key.1, originalValue: anyValue)) } } From 2eec266f28c384e6dacf0d04c1b5e1befaf86f25 Mon Sep 17 00:00:00 2001 From: Mathew Polzin Date: Mon, 27 Apr 2026 10:38:28 -0500 Subject: [PATCH 6/7] update test matrix to remove old macos version with outdated swift --- .github/workflows/tests.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index aede3cd7f..96afb32b3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -33,7 +33,6 @@ jobs: fail-fast: false matrix: os: - - macos-14 - macos-15 runs-on: ${{ matrix.os }} steps: From d9bf43df1e23b0b60a976fe3cbdc8288a735f9b0 Mon Sep 17 00:00:00 2001 From: Mathew Polzin Date: Mon, 27 Apr 2026 20:47:51 -0500 Subject: [PATCH 7/7] update tests around new trait --- .../Document/ExternalDereferencingDocumentTests.swift | 2 ++ Tests/OpenAPIKit30Tests/JSONReferenceTests.swift | 2 ++ .../Document/ExternalDereferencingDocumentTests.swift | 2 ++ Tests/OpenAPIKitTests/JSONReferenceTests.swift | 2 ++ 4 files changed, 8 insertions(+) diff --git a/Tests/OpenAPIKit30Tests/Document/ExternalDereferencingDocumentTests.swift b/Tests/OpenAPIKit30Tests/Document/ExternalDereferencingDocumentTests.swift index 0c5c9898d..8950cd03f 100644 --- a/Tests/OpenAPIKit30Tests/Document/ExternalDereferencingDocumentTests.swift +++ b/Tests/OpenAPIKit30Tests/Document/ExternalDereferencingDocumentTests.swift @@ -12,6 +12,7 @@ import Yams import OpenAPIKit30 import XCTest +#if ExternalLoading final class ExternalDereferencingDocumentTests: XCTestCase { // temporarily test with an example of the new interface func test_example() async throws { @@ -291,3 +292,4 @@ final class ExternalDereferencingDocumentTests: XCTestCase { ) } } +#endif diff --git a/Tests/OpenAPIKit30Tests/JSONReferenceTests.swift b/Tests/OpenAPIKit30Tests/JSONReferenceTests.swift index f30622660..13e23598b 100644 --- a/Tests/OpenAPIKit30Tests/JSONReferenceTests.swift +++ b/Tests/OpenAPIKit30Tests/JSONReferenceTests.swift @@ -359,6 +359,7 @@ extension JSONReferenceTests { } // MARK: - External Dereferencing +#if ExternalLoading extension JSONReferenceTests { func test_externalDerefNoFragment() async throws { let reference: JSONReference = .external(.init(string: "./schema.json")!) @@ -390,3 +391,4 @@ extension JSONReferenceTests { XCTAssertEqual(messages, ["./schema.json#/components/schemas/test"]) } } +#endif diff --git a/Tests/OpenAPIKitTests/Document/ExternalDereferencingDocumentTests.swift b/Tests/OpenAPIKitTests/Document/ExternalDereferencingDocumentTests.swift index 6c63be7fc..a6b53bd04 100644 --- a/Tests/OpenAPIKitTests/Document/ExternalDereferencingDocumentTests.swift +++ b/Tests/OpenAPIKitTests/Document/ExternalDereferencingDocumentTests.swift @@ -12,6 +12,7 @@ import Yams import OpenAPIKit import XCTest +#if ExternalLoading final class ExternalDereferencingDocumentTests: XCTestCase { // temporarily test with an example of the new interface func test_example() async throws { @@ -338,3 +339,4 @@ final class ExternalDereferencingDocumentTests: XCTestCase { ) } } +#endif diff --git a/Tests/OpenAPIKitTests/JSONReferenceTests.swift b/Tests/OpenAPIKitTests/JSONReferenceTests.swift index fc0f5447d..2974dd04b 100644 --- a/Tests/OpenAPIKitTests/JSONReferenceTests.swift +++ b/Tests/OpenAPIKitTests/JSONReferenceTests.swift @@ -417,6 +417,7 @@ extension JSONReferenceTests { } // MARK: - External Dereferencing +#if ExternalLoading extension JSONReferenceTests { func test_externalDerefNoFragment() async throws { let reference: JSONReference = .external(.init(string: "./schema.json")!) @@ -448,6 +449,7 @@ extension JSONReferenceTests { XCTAssertEqual(messages, ["./schema.json#/components/schemas/test"]) } } +#endif // MARK: - Test Types extension JSONReferenceTests {