From 4081c8f74169f2ecbefa2b11faf4d083edea3736 Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Fri, 4 Aug 2023 18:55:46 +0200 Subject: [PATCH 1/3] [Generator] Support unexploded query items --- .../StructuredSwiftRepresentation.swift | 5 + .../Renderer/TextBasedRenderer.swift | 2 + .../Translator/CommonTypes/Constants.swift | 7 + .../Parameters/TypedParameter.swift | 40 ++- .../Parameters/translateParameter.swift | 17 +- .../TypesTranslator/TypesFileTranslator.swift | 2 +- .../Articles/Supported-OpenAPI-features.md | 14 +- .../StructureHelpers.swift | 8 +- .../ReferenceSources/Petstore/Client.swift | 8 + .../ReferenceSources/Petstore/Server.swift | 8 + .../Client.swift | 8 + .../Server.swift | 8 + .../SnippetBasedReferenceTests.swift | 228 ++++++++++++++++++ 13 files changed, 336 insertions(+), 19 deletions(-) diff --git a/Sources/_OpenAPIGeneratorCore/Layers/StructuredSwiftRepresentation.swift b/Sources/_OpenAPIGeneratorCore/Layers/StructuredSwiftRepresentation.swift index 78aaf013..6e63a0e0 100644 --- a/Sources/_OpenAPIGeneratorCore/Layers/StructuredSwiftRepresentation.swift +++ b/Sources/_OpenAPIGeneratorCore/Layers/StructuredSwiftRepresentation.swift @@ -97,6 +97,11 @@ enum LiteralDescription: Equatable, Codable { /// For example `42`. case int(Int) + /// A Boolean literal. + /// + /// For example `true`. + case bool(Bool) + /// The nil literal: `nil`. case `nil` diff --git a/Sources/_OpenAPIGeneratorCore/Renderer/TextBasedRenderer.swift b/Sources/_OpenAPIGeneratorCore/Renderer/TextBasedRenderer.swift index b004dd12..72c199c6 100644 --- a/Sources/_OpenAPIGeneratorCore/Renderer/TextBasedRenderer.swift +++ b/Sources/_OpenAPIGeneratorCore/Renderer/TextBasedRenderer.swift @@ -316,6 +316,8 @@ struct TextBasedRenderer: RendererProtocol { return "\"\(string)\"" case let .int(int): return "\(int)" + case let .bool(bool): + return bool ? "true" : "false" case .nil: return "nil" case .array(let items): diff --git a/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/Constants.swift b/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/Constants.swift index 95b8d097..5809bae6 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/Constants.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/CommonTypes/Constants.swift @@ -299,6 +299,13 @@ enum Constants { /// The name of the namespace. static let namespace: String = "Parameters" + + /// Maps to `OpenAPIRuntime.ParameterStyle`. + enum Style { + + /// The form style. + static let form = "form" + } } /// Constants related to the Headers namespace. diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Parameters/TypedParameter.swift b/Sources/_OpenAPIGeneratorCore/Translator/Parameters/TypedParameter.swift index ce9974f4..1418dff3 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Parameters/TypedParameter.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Parameters/TypedParameter.swift @@ -22,6 +22,12 @@ struct TypedParameter { /// The underlying schema. var schema: UnresolvedSchema + /// The parameter serialization style. + var style: OpenAPI.Parameter.SchemaContext.Style + + /// The parameter explode value. + var explode: Bool + /// The computed type usage. var typeUsage: TypeUsage @@ -134,9 +140,13 @@ extension FileTranslator { let schema: UnresolvedSchema let codingStrategy: CodingStrategy + let style: OpenAPI.Parameter.SchemaContext.Style + let explode: Bool switch parameter.schemaOrContent { case let .a(schemaContext): schema = schemaContext.schema + style = schemaContext.style + explode = schemaContext.explode codingStrategy = .text // Check supported exploded/style types @@ -150,13 +160,6 @@ extension FileTranslator { ) return nil } - guard schemaContext.explode else { - diagnostics.emitUnsupported( - "Unexploded query params", - foundIn: foundIn - ) - return nil - } case .header, .path: guard case .simple = schemaContext.style else { diagnostics.emitUnsupported( @@ -189,6 +192,14 @@ extension FileTranslator { .content .contentType .codingStrategy + switch parameter.location { + case .query, .cookie: + style = .form + explode = true + case .path, .header: + style = .simple + explode = false + } } // Check if the underlying schema is supported @@ -221,6 +232,8 @@ extension FileTranslator { return .init( parameter: parameter, schema: schema, + style: style, + explode: explode, typeUsage: usage, codingStrategy: codingStrategy, asSwiftSafeName: swiftSafeName @@ -271,3 +284,16 @@ extension OpenAPI.Parameter.Context.Location { } } } + +extension OpenAPI.Parameter.SchemaContext.Style { + + /// The runtime name for the style. + var runtimeName: String { + switch self { + case .form: + return Constants.Components.Parameters.Style.form + default: + preconditionFailure("Unsupported style") + } + } +} diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift b/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift index eb264dad..4a125508 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Parameters/translateParameter.swift @@ -116,13 +116,16 @@ extension ClientFileTranslator { ) throws -> Expression? { let methodPrefix: String let containerExpr: Expression + let supportsStyleAndExplode: Bool switch parameter.location { case .header: methodPrefix = "HeaderField" containerExpr = .identifier(requestVariableName).dot("headerFields") + supportsStyleAndExplode = false case .query: methodPrefix = "QueryItem" containerExpr = .identifier(requestVariableName) + supportsStyleAndExplode = true default: diagnostics.emitUnsupported( "Parameter of type \(parameter.location.rawValue)", @@ -130,6 +133,15 @@ extension ClientFileTranslator { ) return nil } + let styleAndExplodeArgs: [FunctionArgumentDescription] + if supportsStyleAndExplode { + styleAndExplodeArgs = [ + .init(label: "style", expression: .dot(parameter.style.runtimeName)), + .init(label: "explode", expression: .literal(.bool(parameter.explode))), + ] + } else { + styleAndExplodeArgs = [] + } return .try( .identifier("converter") .dot("set\(methodPrefix)As\(parameter.codingStrategy.runtimeName)") @@ -138,7 +150,8 @@ extension ClientFileTranslator { .init( label: "in", expression: .inOut(containerExpr) - ), + ) + ] + styleAndExplodeArgs + [ .init(label: "name", expression: .literal(parameter.name)), .init( label: "value", @@ -194,6 +207,8 @@ extension ServerFileTranslator { .identifier("converter").dot(methodName("QueryItem")) .call([ .init(label: "in", expression: .identifier("metadata").dot("queryParameters")), + .init(label: "style", expression: .dot(typedParameter.style.runtimeName)), + .init(label: "explode", expression: .literal(.bool(typedParameter.explode))), .init(label: "name", expression: .literal(parameter.name)), .init( label: "as", diff --git a/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/TypesFileTranslator.swift b/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/TypesFileTranslator.swift index 7aa46c68..23e3432f 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/TypesFileTranslator.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/TypesFileTranslator.swift @@ -48,7 +48,7 @@ struct TypesFileTranslator: FileTranslator { let components = try translateComponents(doc.components) let operationDescriptions = try OperationDescription.all( - from: parsedOpenAPI.paths, + from: doc.paths, in: doc.components, asSwiftSafeName: swiftSafeName ) diff --git a/Sources/swift-openapi-generator/Documentation.docc/Articles/Supported-OpenAPI-features.md b/Sources/swift-openapi-generator/Documentation.docc/Articles/Supported-OpenAPI-features.md index 16cbdb33..fd127dfb 100644 --- a/Sources/swift-openapi-generator/Documentation.docc/Articles/Supported-OpenAPI-features.md +++ b/Sources/swift-openapi-generator/Documentation.docc/Articles/Supported-OpenAPI-features.md @@ -81,7 +81,7 @@ Supported features are always provided on _both_ client and server. - [x] requestBody - [x] responses - [ ] callbacks -- [ ] deprecated +- [x] deprecated - [ ] security - [ ] servers @@ -162,7 +162,7 @@ Supported features are always provided on _both_ client and server. - [ ] xml - [ ] externalDocs - [ ] example -- [ ] deprecated +- [x] deprecated #### External Documentation Object @@ -196,15 +196,15 @@ Supported features are always provided on _both_ client and server. - [x] in - [x] description - [x] required -- [ ] deprecated +- [x] deprecated - [ ] allowEmptyValue -- [x] style (not all) -- [x] explode (only explode: `true`) +- [x] style (only defaults) +- [x] explode (non default only for query items) - [ ] allowReserved - [x] schema - [ ] example - [ ] examples -- [ ] content +- [x] content (chooses one from the map) #### Style Values @@ -223,7 +223,7 @@ Supported features are always provided on _both_ client and server. Supported location + styles + exploded combinations: - path + simple + false -- query + form + true +- query + form + true/false - header + simple + false #### Reference Object diff --git a/Tests/OpenAPIGeneratorCoreTests/StructureHelpers.swift b/Tests/OpenAPIGeneratorCoreTests/StructureHelpers.swift index 8e663f07..823dd10d 100644 --- a/Tests/OpenAPIGeneratorCoreTests/StructureHelpers.swift +++ b/Tests/OpenAPIGeneratorCoreTests/StructureHelpers.swift @@ -156,13 +156,15 @@ extension Declaration { extension LiteralDescription { var name: String { switch self { - case .string(_): + case .string: return "string" - case .int(_): + case .int: return "int" + case .bool: + return "bool" case .nil: return "nil" - case .array(_): + case .array: return "array" } } diff --git a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Client.swift b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Client.swift index 363e2337..7ac7b329 100644 --- a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Client.swift +++ b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Client.swift @@ -52,16 +52,22 @@ public struct Client: APIProtocol { suppressMutabilityWarning(&request) try converter.setQueryItemAsText( in: &request, + style: .form, + explode: true, name: "limit", value: input.query.limit ) try converter.setQueryItemAsText( in: &request, + style: .form, + explode: true, name: "habitat", value: input.query.habitat ) try converter.setQueryItemAsText( in: &request, + style: .form, + explode: true, name: "feeds", value: input.query.feeds ) @@ -72,6 +78,8 @@ public struct Client: APIProtocol { ) try converter.setQueryItemAsText( in: &request, + style: .form, + explode: true, name: "since", value: input.query.since ) diff --git a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Server.swift b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Server.swift index cd60e0cd..b53efce2 100644 --- a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Server.swift +++ b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore/Server.swift @@ -87,21 +87,29 @@ fileprivate extension UniversalServer where APIHandler: APIProtocol { let query: Operations.listPets.Input.Query = .init( limit: try converter.getOptionalQueryItemAsText( in: metadata.queryParameters, + style: .form, + explode: true, name: "limit", as: Swift.Int32.self ), habitat: try converter.getOptionalQueryItemAsText( in: metadata.queryParameters, + style: .form, + explode: true, name: "habitat", as: Operations.listPets.Input.Query.habitatPayload.self ), feeds: try converter.getOptionalQueryItemAsText( in: metadata.queryParameters, + style: .form, + explode: true, name: "feeds", as: Operations.listPets.Input.Query.feedsPayload.self ), since: try converter.getOptionalQueryItemAsText( in: metadata.queryParameters, + style: .form, + explode: true, name: "since", as: Components.Parameters.query_born_since.self ) diff --git a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore_FF_MultipleContentTypes/Client.swift b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore_FF_MultipleContentTypes/Client.swift index 2231d78c..ae604978 100644 --- a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore_FF_MultipleContentTypes/Client.swift +++ b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore_FF_MultipleContentTypes/Client.swift @@ -52,16 +52,22 @@ public struct Client: APIProtocol { suppressMutabilityWarning(&request) try converter.setQueryItemAsText( in: &request, + style: .form, + explode: true, name: "limit", value: input.query.limit ) try converter.setQueryItemAsText( in: &request, + style: .form, + explode: true, name: "habitat", value: input.query.habitat ) try converter.setQueryItemAsText( in: &request, + style: .form, + explode: true, name: "feeds", value: input.query.feeds ) @@ -72,6 +78,8 @@ public struct Client: APIProtocol { ) try converter.setQueryItemAsText( in: &request, + style: .form, + explode: true, name: "since", value: input.query.since ) diff --git a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore_FF_MultipleContentTypes/Server.swift b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore_FF_MultipleContentTypes/Server.swift index 1a3753f8..0d4a3472 100644 --- a/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore_FF_MultipleContentTypes/Server.swift +++ b/Tests/OpenAPIGeneratorReferenceTests/Resources/ReferenceSources/Petstore_FF_MultipleContentTypes/Server.swift @@ -87,21 +87,29 @@ fileprivate extension UniversalServer where APIHandler: APIProtocol { let query: Operations.listPets.Input.Query = .init( limit: try converter.getOptionalQueryItemAsText( in: metadata.queryParameters, + style: .form, + explode: true, name: "limit", as: Swift.Int32.self ), habitat: try converter.getOptionalQueryItemAsText( in: metadata.queryParameters, + style: .form, + explode: true, name: "habitat", as: Operations.listPets.Input.Query.habitatPayload.self ), feeds: try converter.getOptionalQueryItemAsText( in: metadata.queryParameters, + style: .form, + explode: true, name: "feeds", as: Operations.listPets.Input.Query.feedsPayload.self ), since: try converter.getOptionalQueryItemAsText( in: metadata.queryParameters, + style: .form, + explode: true, name: "since", as: Components.Parameters.query_born_since.self ) diff --git a/Tests/OpenAPIGeneratorReferenceTests/SnippetBasedReferenceTests.swift b/Tests/OpenAPIGeneratorReferenceTests/SnippetBasedReferenceTests.swift index 205307f9..ad2ee96e 100644 --- a/Tests/OpenAPIGeneratorReferenceTests/SnippetBasedReferenceTests.swift +++ b/Tests/OpenAPIGeneratorReferenceTests/SnippetBasedReferenceTests.swift @@ -969,6 +969,142 @@ final class SnippetBasedReferenceTests: XCTestCase { XCTAssert(error is DecodingError) } } + + func testRequestWithQueryItems() throws { + try self.assertRequestInTypesClientServerTranslation( + """ + /foo: + get: + parameters: + - name: single + in: query + schema: + type: string + - name: manyExploded + in: query + explode: true + schema: + type: array + items: + type: string + - name: manyUnexploded + in: query + explode: false + schema: + type: array + items: + type: string + responses: + default: + description: Response + """, + types: """ + public struct Input: Sendable, Equatable, Hashable { + public struct Path: Sendable, Equatable, Hashable { public init() {} } + public var path: Operations.get_foo.Input.Path + public struct Query: Sendable, Equatable, Hashable { + public var single: Swift.String? + public var manyExploded: [Swift.String]? + public var manyUnexploded: [Swift.String]? + public init( + single: Swift.String? = nil, + manyExploded: [Swift.String]? = nil, + manyUnexploded: [Swift.String]? = nil + ) { + self.single = single + self.manyExploded = manyExploded + self.manyUnexploded = manyUnexploded + } + } + public var query: Operations.get_foo.Input.Query + public struct Headers: Sendable, Equatable, Hashable { public init() {} } + public var headers: Operations.get_foo.Input.Headers + public struct Cookies: Sendable, Equatable, Hashable { public init() {} } + public var cookies: Operations.get_foo.Input.Cookies + @frozen public enum Body: Sendable, Equatable, Hashable {} + public var body: Operations.get_foo.Input.Body? + public init( + path: Operations.get_foo.Input.Path = .init(), + query: Operations.get_foo.Input.Query = .init(), + headers: Operations.get_foo.Input.Headers = .init(), + cookies: Operations.get_foo.Input.Cookies = .init(), + body: Operations.get_foo.Input.Body? = nil + ) { + self.path = path + self.query = query + self.headers = headers + self.cookies = cookies + self.body = body + } + } + """, + client: """ + { input in let path = try converter.renderedRequestPath(template: "/foo", parameters: []) + var request: OpenAPIRuntime.Request = .init(path: path, method: .get) + suppressMutabilityWarning(&request) + try converter.setQueryItemAsText( + in: &request, + style: .form, + explode: true, + name: "single", + value: input.query.single + ) + try converter.setQueryItemAsText( + in: &request, + style: .form, + explode: true, + name: "manyExploded", + value: input.query.manyExploded + ) + try converter.setQueryItemAsText( + in: &request, + style: .form, + explode: false, + name: "manyUnexploded", + value: input.query.manyUnexploded + ) + return request + } + """, + server: """ + { request, metadata in let path: Operations.get_foo.Input.Path = .init() + let query: Operations.get_foo.Input.Query = .init( + single: try converter.getOptionalQueryItemAsText( + in: metadata.queryParameters, + style: .form, + explode: true, + name: "single", + as: Swift.String.self + ), + manyExploded: try converter.getOptionalQueryItemAsText( + in: metadata.queryParameters, + style: .form, + explode: true, + name: "manyExploded", + as: [Swift.String].self + ), + manyUnexploded: try converter.getOptionalQueryItemAsText( + in: metadata.queryParameters, + style: .form, + explode: false, + name: "manyUnexploded", + as: [Swift.String].self + ) + ) + let headers: Operations.get_foo.Input.Headers = .init() + let cookies: Operations.get_foo.Input.Cookies = .init() + return Operations.get_foo.Input( + path: path, + query: query, + headers: headers, + cookies: cookies, + body: nil + ) + } + """ + ) + } + } extension SnippetBasedReferenceTests { @@ -994,6 +1130,31 @@ extension SnippetBasedReferenceTests { ) } + func makeTranslators( + components: OpenAPI.Components = .noComponents, + featureFlags: FeatureFlags = [], + ignoredDiagnosticMessages: Set = [] + ) throws -> (TypesFileTranslator, ClientFileTranslator, ServerFileTranslator) { + let collector = XCTestDiagnosticCollector(test: self, ignoredDiagnosticMessages: ignoredDiagnosticMessages) + return ( + TypesFileTranslator( + config: Config(mode: .types, featureFlags: featureFlags), + diagnostics: collector, + components: components + ), + ClientFileTranslator( + config: Config(mode: .client, featureFlags: featureFlags), + diagnostics: collector, + components: components + ), + ServerFileTranslator( + config: Config(mode: .server, featureFlags: featureFlags), + diagnostics: collector, + components: components + ) + ) + } + func assertHeadersTranslation( _ componentsYAML: String, _ expectedSwift: String, @@ -1016,6 +1177,45 @@ extension SnippetBasedReferenceTests { try XCTAssertSwiftEquivalent(translation, expectedSwift, file: file, line: line) } + func assertRequestInTypesClientServerTranslation( + _ pathsYAML: String, + _ componentsYAML: String? = nil, + types expectedTypesSwift: String, + client expectedClientSwift: String, + server expectedServerSwift: String, + file: StaticString = #filePath, + line: UInt = #line + ) throws { + continueAfterFailure = false + let (types, client, server) = try makeTranslators() + let components = + try componentsYAML.flatMap { componentsYAML in + try YAMLDecoder().decode(OpenAPI.Components.self, from: componentsYAML) + } ?? OpenAPI.Components.noComponents + let paths = try YAMLDecoder().decode(OpenAPI.PathItem.Map.self, from: pathsYAML) + let document = OpenAPI.Document( + openAPIVersion: .v3_0_3, + info: .init(title: "Test", version: "1.0.0"), + servers: [], + paths: paths, + components: components + ) + let operationDescriptions = try OperationDescription.all( + from: document.paths, + in: document.components, + asSwiftSafeName: types.swiftSafeName + ) + let operation = try XCTUnwrap(operationDescriptions.first) + let generatedTypesStructuredSwift = try types.translateOperationInput(operation) + try XCTAssertSwiftEquivalent(generatedTypesStructuredSwift, expectedTypesSwift, file: file, line: line) + + let generatedClientStructuredSwift = try client.translateClientSerializer(operation) + try XCTAssertSwiftEquivalent(generatedClientStructuredSwift, expectedClientSwift, file: file, line: line) + + let generatedServerStructuredSwift = try server.translateServerDeserializer(operation) + try XCTAssertSwiftEquivalent(generatedServerStructuredSwift, expectedServerSwift, file: file, line: line) + } + func assertSchemasTranslation( _ componentsYAML: String, _ expectedSwift: String, @@ -1106,6 +1306,34 @@ private func XCTAssertSwiftEquivalent( ) } +private func XCTAssertSwiftEquivalent( + _ codeBlock: CodeBlock, + _ expectedSwift: String, + file: StaticString = #filePath, + line: UInt = #line +) throws { + try XCTAssertEqualWithDiff( + TextBasedRenderer().renderedCodeBlock(codeBlock).swiftFormatted, + expectedSwift.swiftFormatted, + file: file, + line: line + ) +} + +private func XCTAssertSwiftEquivalent( + _ expression: Expression, + _ expectedSwift: String, + file: StaticString = #filePath, + line: UInt = #line +) throws { + try XCTAssertEqualWithDiff( + TextBasedRenderer().renderedExpression(expression).swiftFormatted, + expectedSwift.swiftFormatted, + file: file, + line: line + ) +} + private func diff(expected: String, actual: String) throws -> String { let process = Process() process.executableURL = URL(fileURLWithPath: "/usr/bin/env") From a71e9b7ccc4a8034bb4f418726edf9311921586f Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Mon, 7 Aug 2023 12:31:33 +0200 Subject: [PATCH 2/3] PR feedback: add a link to the specification --- .../Translator/Parameters/TypedParameter.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Sources/_OpenAPIGeneratorCore/Translator/Parameters/TypedParameter.swift b/Sources/_OpenAPIGeneratorCore/Translator/Parameters/TypedParameter.swift index 1418dff3..a7e7a847 100644 --- a/Sources/_OpenAPIGeneratorCore/Translator/Parameters/TypedParameter.swift +++ b/Sources/_OpenAPIGeneratorCore/Translator/Parameters/TypedParameter.swift @@ -192,6 +192,9 @@ extension FileTranslator { .content .contentType .codingStrategy + + // Defaults are defined by the OpenAPI specification: + // https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#fixed-fields-10 switch parameter.location { case .query, .cookie: style = .form From ce9440dabf1d72940a57f552cf54f86167e26ff4 Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Tue, 8 Aug 2023 09:59:53 +0200 Subject: [PATCH 3/3] Bump the runtime dependency to 0.1.8 --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 76f840bb..d1b0ddd8 100644 --- a/Package.swift +++ b/Package.swift @@ -78,7 +78,7 @@ let package = Package( ), // Tests-only: Runtime library linked by generated code - .package(url: "https://github.com/apple/swift-openapi-runtime", .upToNextMinor(from: "0.1.7")), + .package(url: "https://github.com/apple/swift-openapi-runtime", .upToNextMinor(from: "0.1.8")), // Build and preview docs .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"),