From 6efc8cae779bbf3b625c2dacb00965d98aa5fd72 Mon Sep 17 00:00:00 2001 From: Shaps Benkau Date: Wed, 4 Oct 2023 20:30:38 +0100 Subject: [PATCH 1/3] Now compiles with updated Starscream APIs --- Sources/GraphQLWebSocket/Client.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/GraphQLWebSocket/Client.swift b/Sources/GraphQLWebSocket/Client.swift index 637d80b..80002f6 100644 --- a/Sources/GraphQLWebSocket/Client.swift +++ b/Sources/GraphQLWebSocket/Client.swift @@ -74,7 +74,7 @@ public class GraphQLWebSocket: WebSocketDelegate { case connecting /// WebSocket has opened. - case opened(socket: WebSocket) + case opened(socket: WebSocketClient) /// Open WebSocket connection has been acknowledged case acknowledged(payload: [String: AnyCodable]?) @@ -143,7 +143,7 @@ public class GraphQLWebSocket: WebSocketDelegate { // MARK: - Internals - public func didReceive(event: WebSocketEvent, client: WebSocket) { + public func didReceive(event: WebSocketEvent, client: WebSocketClient) { self.config.logger.debug("Received a new message from the server!") switch event { From 19e4efb076bbb5bba219657c75f4c4aded26a1ad Mon Sep 17 00:00:00 2001 From: Shaps Benkau Date: Wed, 4 Oct 2023 21:12:26 +0100 Subject: [PATCH 2/3] Camel case now preserves leading and trailing underscores to properly support the GraphQL spec --- Sources/GraphQLWebSocket/Client.swift | 4 +++- Sources/SwiftGraphQL/Document/Field.swift | 2 +- .../Generator/Codable.swift | 2 +- .../SwiftGraphQLCodegen/Generator/Enum.swift | 4 ++-- .../SwiftGraphQLCodegen/Generator/Field.swift | 8 ++++---- .../Generator/Fragments.swift | 8 ++++---- .../Generator/InputObject.swift | 10 +++++----- .../Extensions/String+Case.swift | 18 +++++++++++++++--- .../Generator/EnumTests.swift | 4 ++-- .../Extensions/String+CaseTests.swift | 10 +++++----- 10 files changed, 42 insertions(+), 28 deletions(-) diff --git a/Sources/GraphQLWebSocket/Client.swift b/Sources/GraphQLWebSocket/Client.swift index 80002f6..b9cbb50 100644 --- a/Sources/GraphQLWebSocket/Client.swift +++ b/Sources/GraphQLWebSocket/Client.swift @@ -75,7 +75,7 @@ public class GraphQLWebSocket: WebSocketDelegate { /// WebSocket has opened. case opened(socket: WebSocketClient) - + /// Open WebSocket connection has been acknowledged case acknowledged(payload: [String: AnyCodable]?) @@ -219,6 +219,8 @@ public class GraphQLWebSocket: WebSocketDelegate { self.close(code: closeCode) break + case .peerClosed: + self.close(code: 1000) } } diff --git a/Sources/SwiftGraphQL/Document/Field.swift b/Sources/SwiftGraphQL/Document/Field.swift index 5cc9379..9d3bac0 100644 --- a/Sources/SwiftGraphQL/Document/Field.swift +++ b/Sources/SwiftGraphQL/Document/Field.swift @@ -52,7 +52,7 @@ public enum GraphQLField { switch self { case let .leaf(name, parent, arguments), let .composite(name, parent, _, arguments, _): - return "\(name.camelCase)\(parent.camelCase)_\(arguments.hash)" + return "\(name.camelCasePreservingSurroundingUnderscores)\(parent.camelCasePreservingSurroundingUnderscores)_\(arguments.hash)" case .fragment: return nil } diff --git a/Sources/SwiftGraphQLCodegen/Generator/Codable.swift b/Sources/SwiftGraphQLCodegen/Generator/Codable.swift index a7f3fba..52c28bb 100644 --- a/Sources/SwiftGraphQLCodegen/Generator/Codable.swift +++ b/Sources/SwiftGraphQLCodegen/Generator/Codable.swift @@ -27,7 +27,7 @@ private extension Collection where Element == ObjectTypeRef { /// Returns an enumerator that we use to decode typename field. func typenamesEnum() -> String { let types = self - .map { "case \($0.name.camelCase.normalize) = \"\($0.name)\"" } + .map { "case \($0.name.camelCasePreservingSurroundingUnderscores.normalize) = \"\($0.name)\"" } .joined(separator: "\n") return """ diff --git a/Sources/SwiftGraphQLCodegen/Generator/Enum.swift b/Sources/SwiftGraphQLCodegen/Generator/Enum.swift index ec88a4e..24f58ba 100644 --- a/Sources/SwiftGraphQLCodegen/Generator/Enum.swift +++ b/Sources/SwiftGraphQLCodegen/Generator/Enum.swift @@ -58,7 +58,7 @@ extension EnumType { /// Mock value declaration. private var mock: String { let value = self.enumValues.first! - return "public static var mockValue = Self.\(value.name.camelCase.normalize)" + return "public static var mockValue = Self.\(value.name.camelCasePreservingSurroundingUnderscores.normalize)" } } @@ -70,7 +70,7 @@ extension EnumValue { fileprivate var declaration: String { """ \(docs) - case \(name.camelCase.normalize) = "\(name)" + case \(name.camelCasePreservingSurroundingUnderscores.normalize) = "\(name)" """ } diff --git a/Sources/SwiftGraphQLCodegen/Generator/Field.swift b/Sources/SwiftGraphQLCodegen/Generator/Field.swift index a2a8776..d91136e 100644 --- a/Sources/SwiftGraphQLCodegen/Generator/Field.swift +++ b/Sources/SwiftGraphQLCodegen/Generator/Field.swift @@ -98,7 +98,7 @@ extension Field { } private var fName: String { - name.camelCase.normalize + name.camelCasePreservingSurroundingUnderscores.normalize } private func fParameters(context: Context) throws -> String { @@ -148,7 +148,7 @@ private extension Collection where Element == InputValue { /// Returns a one-to-one argument mapping. func arguments(field: Field, context: Context) -> String { let args = self - .map { $0.name.camelCase }.map { "\($0): \($0.normalize)" } + .map { $0.name.camelCasePreservingSurroundingUnderscores }.map { "\($0): \($0.normalize)" } .joined(separator: ", ") switch field.type.namedType { @@ -166,7 +166,7 @@ private extension Collection where Element == InputValue { extension InputValue { /// Generates a function parameter for this input value. fileprivate func parameter(context: Context) throws -> String { - "\(name.camelCase.normalize): \(try type.type(scalars: context.scalars)) \(self.default)" + "\(name.camelCasePreservingSurroundingUnderscores.normalize): \(try type.type(scalars: context.scalars)) \(self.default)" } /// Returns the default value of the parameter. @@ -224,7 +224,7 @@ private extension Collection where Element == InputValue { private extension InputValue { /// Returns a SwiftGraphQL Argument definition for a given input value. var argument: String { - #"Argument(name: "\#(name)", type: "\#(type.argument)", value: \#(name.camelCase.normalize))"# + #"Argument(name: "\#(name)", type: "\#(type.argument)", value: \#(name.camelCasePreservingSurroundingUnderscores.normalize))"# } } diff --git a/Sources/SwiftGraphQLCodegen/Generator/Fragments.swift b/Sources/SwiftGraphQLCodegen/Generator/Fragments.swift index 2154b52..2cf279f 100644 --- a/Sources/SwiftGraphQLCodegen/Generator/Fragments.swift +++ b/Sources/SwiftGraphQLCodegen/Generator/Fragments.swift @@ -48,19 +48,19 @@ extension Collection where Element == ObjectTypeRef { /// Type used to private var mock: String { - self.first!.namedType.name.camelCase + self.first!.namedType.name.camelCasePreservingSurroundingUnderscores } } private extension ObjectTypeRef { /// Returns a parameter definition for a given type reference. var parameter: String { - "\(namedType.name.camelCase): Selection" + "\(namedType.name.camelCasePreservingSurroundingUnderscores): Selection" } /// Returns a SwiftGraphQL Fragment selection. func fragment(interface: String) -> String { - #"GraphQLField.fragment(type: "\#(namedType.name)", interface: "\#(interface)", selection: \#(namedType.name.camelCase).__selection())"# + #"GraphQLField.fragment(type: "\#(namedType.name)", interface: "\#(interface)", selection: \#(namedType.name.camelCasePreservingSurroundingUnderscores).__selection())"# } /// Returns a decoder for a fragment. @@ -70,7 +70,7 @@ private extension ObjectTypeRef { let name = namedType.name return """ case "\(name)": - return try \(name.camelCase).__decode(data: data) + return try \(name.camelCasePreservingSurroundingUnderscores).__decode(data: data) """ } } diff --git a/Sources/SwiftGraphQLCodegen/Generator/InputObject.swift b/Sources/SwiftGraphQLCodegen/Generator/InputObject.swift index 38bca72..71e3b64 100644 --- a/Sources/SwiftGraphQLCodegen/Generator/InputObject.swift +++ b/Sources/SwiftGraphQLCodegen/Generator/InputObject.swift @@ -45,19 +45,19 @@ extension InputValue { fileprivate func declaration(context: Context) throws -> String { """ \(docs) - public var \(name.camelCase.normalize): \(try type.type(scalars: context.scalars)) + public var \(name.camelCasePreservingSurroundingUnderscores.normalize): \(try type.type(scalars: context.scalars)) """ } fileprivate func initDeclaration(context: Context, isLast: Bool) throws -> String { """ - \(name.camelCase.normalize): \(try type.type(scalars: context.scalars))\(self.default) + \(name.camelCasePreservingSurroundingUnderscores.normalize): \(try type.type(scalars: context.scalars))\(self.default) """ } fileprivate func initFields(context: Context) throws -> String { """ - self.\(name.camelCase.normalize) = \(name.camelCase.normalize) + self.\(name.camelCasePreservingSurroundingUnderscores.normalize) = \(name.camelCasePreservingSurroundingUnderscores.normalize) """ } @@ -138,7 +138,7 @@ private extension Collection where Element == InputValue { private extension InputValue { /// Returns an encoder for this input value. var encoder: String { - let key = name.camelCase.normalize + let key = name.camelCasePreservingSurroundingUnderscores.normalize switch type.inverted { case .nullable: @@ -152,6 +152,6 @@ private extension InputValue { /// Returns a coding key for this input value. var codingKey: String { - "case \(name.camelCase.normalize) = \"\(name)\"" + "case \(name.camelCasePreservingSurroundingUnderscores.normalize) = \"\(name)\"" } } diff --git a/Sources/SwiftGraphQLUtils/Extensions/String+Case.swift b/Sources/SwiftGraphQLUtils/Extensions/String+Case.swift index 0fce392..f2624c5 100644 --- a/Sources/SwiftGraphQLUtils/Extensions/String+Case.swift +++ b/Sources/SwiftGraphQLUtils/Extensions/String+Case.swift @@ -73,9 +73,21 @@ extension String { return result } - /// Returns the string camelCased. - public var camelCase: String { + /// Returns the string – camelCased – while retaining all leading and trailing underscores + /// + /// _foo_ // returns _foo_ + /// ___foo_bar___ // returns ___fooBar___ + /// + public var camelCasePreservingSurroundingUnderscores: String { + let leading = prefix { $0 == "_" } + let remainder = dropFirst(leading.count) + let trimmed = remainder.trimmingCharacters(in: CharacterSet(["_"])) + let trailing = String.SubSequence(repeating: "_", count: remainder.count - trimmed.count) + let pascal = pascalCase - return pascal[pascal.startIndex].lowercased() + pascal.dropFirst() + return String(leading) + + pascal[pascal.startIndex].lowercased() + + pascal.dropFirst() + + String(trailing) } } diff --git a/Tests/SwiftGraphQLCodegenTests/Generator/EnumTests.swift b/Tests/SwiftGraphQLCodegenTests/Generator/EnumTests.swift index 41a682d..17bcb1b 100644 --- a/Tests/SwiftGraphQLCodegenTests/Generator/EnumTests.swift +++ b/Tests/SwiftGraphQLCodegenTests/Generator/EnumTests.swift @@ -30,7 +30,7 @@ final class EnumTests: XCTestCase { deprecationReason: "Was too good." ), EnumValue( - name: "SKYWALKER", + name: "_SKYWALKER__", description: nil, isDeprecated: true, deprecationReason: nil @@ -53,7 +53,7 @@ final class EnumTests: XCTestCase { /// Released in 1983. case jedi = "JEDI" - case skywalker = "SKYWALKER" + case _skywalker__ = "_SKYWALKER__" } } diff --git a/Tests/SwiftGraphQLUtilsTests/Extensions/String+CaseTests.swift b/Tests/SwiftGraphQLUtilsTests/Extensions/String+CaseTests.swift index 7f91ef0..00f9338 100644 --- a/Tests/SwiftGraphQLUtilsTests/Extensions/String+CaseTests.swift +++ b/Tests/SwiftGraphQLUtilsTests/Extensions/String+CaseTests.swift @@ -3,11 +3,11 @@ import XCTest final class StringExtensionsTest: XCTestCase { func testCamelCase() { - XCTAssertEqual("___a very peculiarNameIndeed__wouldNot.you.agree.AMAZING?____".camelCase, "aVeryPeculiarNameIndeedWouldNotYouAgreeAmazing") - XCTAssertEqual("ENUM".camelCase, "enum") - XCTAssertEqual("linkToURL".camelCase, "linkToUrl") - XCTAssertEqual("grandfather_father.son grandson".camelCase, "grandfatherFatherSonGrandson") - XCTAssertEqual("queryDBShortcuts".camelCase, "queryDbShortcuts") + XCTAssertEqual("___a very peculiarNameIndeed__wouldNot.you.agree.AMAZING?____".camelCasePreservingSurroundingUnderscores, "___aVeryPeculiarNameIndeedWouldNotYouAgreeAmazing____") + XCTAssertEqual("ENUM".camelCasePreservingSurroundingUnderscores, "enum") + XCTAssertEqual("linkToURL".camelCasePreservingSurroundingUnderscores, "linkToUrl") + XCTAssertEqual("grandfather_father.son grandson".camelCasePreservingSurroundingUnderscores, "grandfatherFatherSonGrandson") + XCTAssertEqual("queryDBShortcuts".camelCasePreservingSurroundingUnderscores, "queryDbShortcuts") } func testPascalCase() { From e2855d4e3ad415fd411fe5be8dfead1e1c164902 Mon Sep 17 00:00:00 2001 From: Shaps Date: Thu, 12 Oct 2023 11:43:24 +0100 Subject: [PATCH 3/3] Update Sources/GraphQLWebSocket/Client.swift --- Sources/GraphQLWebSocket/Client.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/GraphQLWebSocket/Client.swift b/Sources/GraphQLWebSocket/Client.swift index b9cbb50..424a965 100644 --- a/Sources/GraphQLWebSocket/Client.swift +++ b/Sources/GraphQLWebSocket/Client.swift @@ -220,7 +220,7 @@ public class GraphQLWebSocket: WebSocketDelegate { break case .peerClosed: - self.close(code: 1000) + self.close(code: 1006) } }