From 080185c41bcd6b85b6b4faf4631ac7e6104d3733 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Thu, 27 Feb 2025 16:30:00 -0500 Subject: [PATCH 01/28] Sources/DataConnectError.swift: add classes to support partial errors. --- Sources/DataConnectError.swift | 36 ++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index b12b49c..0eff657 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -24,7 +24,7 @@ public enum DataConnectError: Error { case grpcNotConfigured /// failed to decode results from server - case decodeFailed + case decodeFailed(response: AnyDataConnectOperationResponse) /// Invalid uuid format during encoding / decoding of data case invalidUUID @@ -36,5 +36,37 @@ public enum DataConnectError: Error { case invalidTimestampFormat /// generic operation execution error - case operationExecutionFailed(messages: String?) + case operationExecutionFailed(response: AnyDataConnectOperationResponse) } + +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) +public protocol AnyDataConnectOperationResponse { + // JSON string + var data: String? { get } + + var errors: [DataConnectOperationErrorInfo] { get } +} + +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) +public struct DataConnectOperationResponse : AnyDataConnectOperationResponse { + // JSON string + public let data: String? + + public let errors: [DataConnectOperationErrorInfo] + + public let decodedData: T? +} + +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) +public struct DataConnectOperationErrorInfo { + public let message: String + public let path: [PathSegment] + + @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + public enum PathSegment { + case field(String) + case listIndex(Int) + } + +} + From d5b1f19ed03629be52e0d3b0c58278509a79b2b1 Mon Sep 17 00:00:00 2001 From: Aashish <112133849+aashishpatil-g@users.noreply.github.com> Date: Fri, 28 Feb 2025 12:20:03 -0800 Subject: [PATCH 02/28] Update DataConnectError.swift --- Sources/DataConnectError.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index 0eff657..7e2c251 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -58,12 +58,12 @@ public struct DataConnectOperationResponse : AnyDataConnectOperationResponse } @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -public struct DataConnectOperationErrorInfo { +public struct DataConnectOperationErrorInfo: Codable { public let message: String public let path: [PathSegment] @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) - public enum PathSegment { + public enum PathSegment: Codable { case field(String) case listIndex(Int) } From 3f277ce22f4309a7f2ae548aff5c77f7d6d96de7 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Mon, 3 Mar 2025 13:56:22 -0500 Subject: [PATCH 03/28] DataConnectError.swift: minor tweaks from offline discussion --- Sources/DataConnectError.swift | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index 7e2c251..f27cb9c 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -24,7 +24,7 @@ public enum DataConnectError: Error { case grpcNotConfigured /// failed to decode results from server - case decodeFailed(response: AnyDataConnectOperationResponse) + case decodeFailed(message: String, response: AnyOperationFailureResponse) /// Invalid uuid format during encoding / decoding of data case invalidUUID @@ -36,37 +36,36 @@ public enum DataConnectError: Error { case invalidTimestampFormat /// generic operation execution error - case operationExecutionFailed(response: AnyDataConnectOperationResponse) + case operationExecutionFailed(message: String, response: AnyOperationFailureResponse) } @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -public protocol AnyDataConnectOperationResponse { +public protocol AnyOperationFailureResponse { // JSON string var data: String? { get } - var errors: [DataConnectOperationErrorInfo] { get } + var errors: [OperationFailureResponse.ErrorInfo] { get } } @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -public struct DataConnectOperationResponse : AnyDataConnectOperationResponse { +public struct OperationFailureResponse : AnyOperationFailureResponse { // JSON string public let data: String? - public let errors: [DataConnectOperationErrorInfo] + public let errors: [ErrorInfo] public let decodedData: T? -} - -@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -public struct DataConnectOperationErrorInfo: Codable { - public let message: String - public let path: [PathSegment] @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) - public enum PathSegment: Codable { - case field(String) - case listIndex(Int) - } + public struct ErrorInfo: Codable { + public let message: String + public let path: [PathSegment] -} + @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + public enum PathSegment: Codable { + case field(String) + case listIndex(Int) + } + } +} From c3cef5a7a8b3bd081f9eb2f3df2196aaeb98119f Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Mon, 3 Mar 2025 13:58:08 -0500 Subject: [PATCH 04/28] DataConnectError.swift: remove message string parameter --- Sources/DataConnectError.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index f27cb9c..86aaff8 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -24,7 +24,7 @@ public enum DataConnectError: Error { case grpcNotConfigured /// failed to decode results from server - case decodeFailed(message: String, response: AnyOperationFailureResponse) + case decodeFailed(response: AnyOperationFailureResponse) /// Invalid uuid format during encoding / decoding of data case invalidUUID @@ -36,7 +36,7 @@ public enum DataConnectError: Error { case invalidTimestampFormat /// generic operation execution error - case operationExecutionFailed(message: String, response: AnyOperationFailureResponse) + case operationExecutionFailed(response: AnyOperationFailureResponse) } @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) From 3a03ef9ea14f0ace310590b57f38220bcb78b9e4 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Mon, 3 Mar 2025 15:41:45 -0500 Subject: [PATCH 05/28] DataConnectError.swift: move OperationFailureResponse.ErrorInfo to top-level struct --- Sources/DataConnectError.swift | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index 86aaff8..457a25a 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -44,7 +44,7 @@ public protocol AnyOperationFailureResponse { // JSON string var data: String? { get } - var errors: [OperationFailureResponse.ErrorInfo] { get } + var errors: [OperationFailureResponseErrorInfo] { get } } @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) @@ -52,20 +52,21 @@ public struct OperationFailureResponse : AnyOperationFailureResponse { // JSON string public let data: String? - public let errors: [ErrorInfo] + public let errors: [OperationFailureResponseErrorInfo] public let decodedData: T? - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) - public struct ErrorInfo: Codable { - public let message: String - public let path: [PathSegment] +} - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) - public enum PathSegment: Codable { - case field(String) - case listIndex(Int) - } +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) +public struct OperationFailureResponseErrorInfo: Codable { + public let message: String + public let path: [PathSegment] + @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + public enum PathSegment: Codable { + case field(String) + case listIndex(Int) } + } From ad7cc64bf03d8ad79659bc500d3a4f47dc96bd1c Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 14 Mar 2025 15:52:48 -0400 Subject: [PATCH 06/28] DataConnectError.swift: update to match api proposal --- Sources/DataConnectError.swift | 49 +++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index 457a25a..c8f9c85 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -23,9 +23,6 @@ public enum DataConnectError: Error { /// failed to configure gRPC case grpcNotConfigured - /// failed to decode results from server - case decodeFailed(response: AnyOperationFailureResponse) - /// Invalid uuid format during encoding / decoding of data case invalidUUID @@ -36,37 +33,45 @@ public enum DataConnectError: Error { case invalidTimestampFormat /// generic operation execution error - case operationExecutionFailed(response: AnyOperationFailureResponse) + case operationExecutionFailed(messages: String?, response: OperationFailureResponse) } +// The data and errors sent to us from the backend in its response. @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -public protocol AnyOperationFailureResponse { - // JSON string - var data: String? { get } - - var errors: [OperationFailureResponseErrorInfo] { get } -} - -@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -public struct OperationFailureResponse : AnyOperationFailureResponse { - // JSON string - public let data: String? - - public let errors: [OperationFailureResponseErrorInfo] - - public let decodedData: T? - +public struct OperationFailureResponse { + // JSON string whose value is the "data" property provided by the backend in its response + // payload; may be `nil` if the "data" property was not provided in the backend response and/or + // was `null` in the backend response. + public let jsonData: String? + + // The list of errors in the "error" property provided by the backend in its response payload; + // may be empty if the "errors" property was not provided in the backend response and/or was an + // empty list in the backend response. + public let errorInfoList: [OperationFailureResponseErrorInfo] + + // Returns `jsonData` string decoded into the given type, if decoding was successful when the + // operation was executed. Returns `nil` if `jsonData` is `nil`, if `jsonData` was _not_ able to + // be decoded when the operation was executed, or if the given type is _not_ equal to the `Data` + // type that was used when the operation was executed. + // + // This function does _not_ do the decoding itself, but simply returns the decoded data, if any, + // that was decoded at the time of the operation's execution. + public func decodedData(asType: Data.Type = Data.self) -> Data? } +// Information about an error provided by the backend in its response. @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public struct OperationFailureResponseErrorInfo: Codable { + // The error message. public let message: String + + // The path to the field to which this error applies. public let path: [PathSegment] @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) - public enum PathSegment: Codable { + public enum PathSegment: Codable, Equatable { case field(String) case listIndex(Int) } - } + From 477e464ee6a26aafcb655b83efcc204d3a356571 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 14 Mar 2025 16:11:07 -0400 Subject: [PATCH 07/28] get it to build --- Sources/DataConnectError.swift | 18 +++++++++++--- Sources/Internal/CodableHelpers.swift | 2 +- Sources/Internal/GrpcClient.swift | 35 ++++++++++++++++++++++----- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index c8f9c85..79cfc19 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -38,16 +38,16 @@ public enum DataConnectError: Error { // The data and errors sent to us from the backend in its response. @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -public struct OperationFailureResponse { +public protocol OperationFailureResponse { // JSON string whose value is the "data" property provided by the backend in its response // payload; may be `nil` if the "data" property was not provided in the backend response and/or // was `null` in the backend response. - public let jsonData: String? + var jsonData: String? { get } // The list of errors in the "error" property provided by the backend in its response payload; // may be empty if the "errors" property was not provided in the backend response and/or was an // empty list in the backend response. - public let errorInfoList: [OperationFailureResponseErrorInfo] + var errorInfoList: [OperationFailureResponseErrorInfo] { get } // Returns `jsonData` string decoded into the given type, if decoding was successful when the // operation was executed. Returns `nil` if `jsonData` is `nil`, if `jsonData` was _not_ able to @@ -56,7 +56,17 @@ public struct OperationFailureResponse { // // This function does _not_ do the decoding itself, but simply returns the decoded data, if any, // that was decoded at the time of the operation's execution. - public func decodedData(asType: Data.Type = Data.self) -> Data? + func decodedData(asType: Data.Type) -> Data? +} + +struct OperationFailureResponseImpl : OperationFailureResponse { + public let jsonData: String? + + public let errorInfoList: [OperationFailureResponseErrorInfo] + + func decodedData(asType: Data.Type = Data.self) -> Data? { + return nil; + } } // Information about an error provided by the backend in its response. diff --git a/Sources/Internal/CodableHelpers.swift b/Sources/Internal/CodableHelpers.swift index 114c305..ca6506b 100644 --- a/Sources/Internal/CodableHelpers.swift +++ b/Sources/Internal/CodableHelpers.swift @@ -40,7 +40,7 @@ class Int64CodableConverter: CodableConverter { } guard let int64Value = Int64(input) else { - throw DataConnectError.decodeFailed + throw DataConnectError.appNotConfigured } return int64Value } diff --git a/Sources/Internal/GrpcClient.swift b/Sources/Internal/GrpcClient.swift index d98bda9..6f49166 100644 --- a/Sources/Internal/GrpcClient.swift +++ b/Sources/Internal/GrpcClient.swift @@ -151,10 +151,16 @@ actor GrpcClient: CustomStringConvertible { DataConnectLogger .debug("executeQuery() receives response: \(resultsString, privacy: .private).") + // Not doing error decoding here guard results.errors.isEmpty else { - throw DataConnectError - .operationExecutionFailed(messages: createErrorJson(errors: results.errors)) + throw DataConnectError.operationExecutionFailed( + messages: createErrorJson(errors: results.errors), + response: OperationFailureResponseImpl( + jsonData: resultsString, + errorInfoList: [] + ) + ) } if let decodedResults = try codec.decode(result: results.data, asType: resultType) { @@ -163,7 +169,13 @@ actor GrpcClient: CustomStringConvertible { // In future, set this as error in OperationResult DataConnectLogger .debug("executeQuery() response: \(resultsString, privacy: .private) decode failed.") - throw DataConnectError.decodeFailed + throw DataConnectError.operationExecutionFailed( + messages: "decode failed", + response: OperationFailureResponseImpl( + jsonData: resultsString, + errorInfoList: [] + ) + ) } } catch { DataConnectLogger.error( @@ -201,8 +213,13 @@ actor GrpcClient: CustomStringConvertible { .debug("executeMutation() receives response: \(resultsString, privacy: .private).") guard results.errors.isEmpty else { - throw DataConnectError - .operationExecutionFailed(messages: createErrorJson(errors: results.errors)) + throw DataConnectError.operationExecutionFailed( + messages: createErrorJson(errors: results.errors), + response: OperationFailureResponseImpl( + jsonData: resultsString, + errorInfoList: [] + ) + ) } if let decodedResults = try codec.decode(result: results.data, asType: resultType) { @@ -210,7 +227,13 @@ actor GrpcClient: CustomStringConvertible { } else { DataConnectLogger .debug("executeMutation() response: \(resultsString, privacy: .private) decode failed.") - throw DataConnectError.decodeFailed + throw DataConnectError.operationExecutionFailed( + messages: "decode failed", + response: OperationFailureResponseImpl( + jsonData: resultsString, + errorInfoList: [] + ) + ) } } catch { DataConnectLogger.error( From 7ab5f8368d99e14e7907fd5999f3bc486470dfc9 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 14 Mar 2025 16:29:01 -0400 Subject: [PATCH 08/28] PartialErrorsDemo.swift added --- .../Sources/KitchenSinkClient.swift | 98 +- .../KitchenSink/Sources/KitchenSinkKeys.swift | 348 ++- .../Sources/KitchenSinkOperations.swift | 2272 +++++++++++------ Tests/Integration/PartialErrorsDemo.swift | 54 + .../dataconnect/default/mutations.gql | 8 + .../dataconnect/schema/schema.gql | 5 + 6 files changed, 1821 insertions(+), 964 deletions(-) create mode 100644 Tests/Integration/PartialErrorsDemo.swift diff --git a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkClient.swift b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkClient.swift index 8cdb90b..c49c571 100644 --- a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkClient.swift +++ b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkClient.swift @@ -1,71 +1,69 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -import FirebaseDataConnect import Foundation +import FirebaseCore +import FirebaseDataConnect + + + + + + + + public extension DataConnect { - static var kitchenSinkConnector: KitchenSinkConnector = { - let dc = DataConnect.dataConnect(connectorConfig: KitchenSinkConnector.connectorConfig) + + static let kitchenSinkConnector: KitchenSinkConnector = { + let dc = DataConnect.dataConnect(connectorConfig: KitchenSinkConnector.connectorConfig, callerSDKType: .generated) return KitchenSinkConnector(dataConnect: dc) }() + } public class KitchenSinkConnector { - var dataConnect: DataConnect - public static let connectorConfig = ConnectorConfig( - serviceId: "fdc-kitchensink", - location: "us-central1", - connector: "kitchen-sink" - ) + let dataConnect: DataConnect + + public static let connectorConfig = ConnectorConfig(serviceId: "fdc-kitchensink", location: "us-central1", connector: "kitchen-sink") init(dataConnect: DataConnect) { self.dataConnect = dataConnect - // init operations - createTestIdMutation = CreateTestIdMutation(dataConnect: dataConnect) - createTestAutoIdMutation = CreateTestAutoIdMutation(dataConnect: dataConnect) - createStandardScalarMutation = CreateStandardScalarMutation(dataConnect: dataConnect) - createScalarBoundaryMutation = CreateScalarBoundaryMutation(dataConnect: dataConnect) - createLargeNumMutation = CreateLargeNumMutation(dataConnect: dataConnect) - createLocalDateMutation = CreateLocalDateMutation(dataConnect: dataConnect) - createAnyValueTypeMutation = CreateAnyValueTypeMutation(dataConnect: dataConnect) - getStandardScalarQuery = GetStandardScalarQuery(dataConnect: dataConnect) - getScalarBoundaryQuery = GetScalarBoundaryQuery(dataConnect: dataConnect) - getLargeNumQuery = GetLargeNumQuery(dataConnect: dataConnect) - getLocalDateTypeQuery = GetLocalDateTypeQuery(dataConnect: dataConnect) - getAnyValueTypeQuery = GetAnyValueTypeQuery(dataConnect: dataConnect) + // init operations + self.createTestIdMutation = CreateTestIdMutation(dataConnect: dataConnect) + self.createTestAutoIdMutation = CreateTestAutoIdMutation(dataConnect: dataConnect) + self.createStandardScalarMutation = CreateStandardScalarMutation(dataConnect: dataConnect) + self.createScalarBoundaryMutation = CreateScalarBoundaryMutation(dataConnect: dataConnect) + self.createLargeNumMutation = CreateLargeNumMutation(dataConnect: dataConnect) + self.createLocalDateMutation = CreateLocalDateMutation(dataConnect: dataConnect) + self.createAnyValueTypeMutation = CreateAnyValueTypeMutation(dataConnect: dataConnect) + self.insertMultiplePeopleMutation = InsertMultiplePeopleMutation(dataConnect: dataConnect) + self.getStandardScalarQuery = GetStandardScalarQuery(dataConnect: dataConnect) + self.getScalarBoundaryQuery = GetScalarBoundaryQuery(dataConnect: dataConnect) + self.getLargeNumQuery = GetLargeNumQuery(dataConnect: dataConnect) + self.getLocalDateTypeQuery = GetLocalDateTypeQuery(dataConnect: dataConnect) + self.getAnyValueTypeQuery = GetAnyValueTypeQuery(dataConnect: dataConnect) + } - public func useEmulator(host: String = DataConnect.EmulatorDefaults.host, - port: Int = DataConnect.EmulatorDefaults.port) { - dataConnect.useEmulator(host: host, port: port) + public func useEmulator(host: String = DataConnect.EmulatorDefaults.host, port: Int = DataConnect.EmulatorDefaults.port) { + self.dataConnect.useEmulator(host: host, port: port) } // MARK: Operations +public let createTestIdMutation: CreateTestIdMutation +public let createTestAutoIdMutation: CreateTestAutoIdMutation +public let createStandardScalarMutation: CreateStandardScalarMutation +public let createScalarBoundaryMutation: CreateScalarBoundaryMutation +public let createLargeNumMutation: CreateLargeNumMutation +public let createLocalDateMutation: CreateLocalDateMutation +public let createAnyValueTypeMutation: CreateAnyValueTypeMutation +public let insertMultiplePeopleMutation: InsertMultiplePeopleMutation +public let getStandardScalarQuery: GetStandardScalarQuery +public let getScalarBoundaryQuery: GetScalarBoundaryQuery +public let getLargeNumQuery: GetLargeNumQuery +public let getLocalDateTypeQuery: GetLocalDateTypeQuery +public let getAnyValueTypeQuery: GetAnyValueTypeQuery + - public let createTestIdMutation: CreateTestIdMutation - public let createTestAutoIdMutation: CreateTestAutoIdMutation - public let createStandardScalarMutation: CreateStandardScalarMutation - public let createScalarBoundaryMutation: CreateScalarBoundaryMutation - public let createLargeNumMutation: CreateLargeNumMutation - public let createLocalDateMutation: CreateLocalDateMutation - public let createAnyValueTypeMutation: CreateAnyValueTypeMutation - public let getStandardScalarQuery: GetStandardScalarQuery - public let getScalarBoundaryQuery: GetScalarBoundaryQuery - public let getLargeNumQuery: GetLargeNumQuery - public let getLocalDateTypeQuery: GetLocalDateTypeQuery - public let getAnyValueTypeQuery: GetAnyValueTypeQuery } diff --git a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkKeys.swift b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkKeys.swift index cef156a..064af2a 100644 --- a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkKeys.swift +++ b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkKeys.swift @@ -1,297 +1,453 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - import Foundation import FirebaseDataConnect + + public struct AnyValueTypeKey { + public private(set) var id: UUID + enum CodingKeys: String, CodingKey { - case id + + case id + } } -extension AnyValueTypeKey: Codable { +extension AnyValueTypeKey : Codable { public init(from decoder: any Decoder) throws { var container = try decoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + + self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + } public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - try codecHelper.encode(id, forKey: .id, container: &container) - } + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + + try codecHelper.encode(id, forKey: .id, container: &container) + + + } } -extension AnyValueTypeKey: Equatable { +extension AnyValueTypeKey : Equatable { public static func == (lhs: AnyValueTypeKey, rhs: AnyValueTypeKey) -> Bool { + if lhs.id != rhs.id { return false } - + return true } } -extension AnyValueTypeKey: Hashable { +extension AnyValueTypeKey : Hashable { public func hash(into hasher: inout Hasher) { - hasher.combine(id) + + hasher.combine(self.id) + } } +extension AnyValueTypeKey : Sendable {} + + + public struct LargeIntTypeKey { + public private(set) var id: UUID + enum CodingKeys: String, CodingKey { - case id + + case id + } } -extension LargeIntTypeKey: Codable { +extension LargeIntTypeKey : Codable { public init(from decoder: any Decoder) throws { var container = try decoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + + self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + } public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - try codecHelper.encode(id, forKey: .id, container: &container) - } + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + + try codecHelper.encode(id, forKey: .id, container: &container) + + + } } -extension LargeIntTypeKey: Equatable { +extension LargeIntTypeKey : Equatable { public static func == (lhs: LargeIntTypeKey, rhs: LargeIntTypeKey) -> Bool { + if lhs.id != rhs.id { return false } - + return true } } -extension LargeIntTypeKey: Hashable { +extension LargeIntTypeKey : Hashable { public func hash(into hasher: inout Hasher) { - hasher.combine(id) + + hasher.combine(self.id) + } } +extension LargeIntTypeKey : Sendable {} + + + public struct LocalDateTypeKey { + public private(set) var id: UUID + enum CodingKeys: String, CodingKey { - case id + + case id + } } -extension LocalDateTypeKey: Codable { +extension LocalDateTypeKey : Codable { public init(from decoder: any Decoder) throws { var container = try decoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + + self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + } public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - try codecHelper.encode(id, forKey: .id, container: &container) - } + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + + try codecHelper.encode(id, forKey: .id, container: &container) + + + } } -extension LocalDateTypeKey: Equatable { +extension LocalDateTypeKey : Equatable { public static func == (lhs: LocalDateTypeKey, rhs: LocalDateTypeKey) -> Bool { + if lhs.id != rhs.id { return false } - + return true } } -extension LocalDateTypeKey: Hashable { +extension LocalDateTypeKey : Hashable { public func hash(into hasher: inout Hasher) { - hasher.combine(id) + + hasher.combine(self.id) + } } -public struct ScalarBoundaryKey { +extension LocalDateTypeKey : Sendable {} + + + +public struct PersonKey { + public private(set) var id: UUID + enum CodingKeys: String, CodingKey { - case id + + case id + } } -extension ScalarBoundaryKey: Codable { +extension PersonKey : Codable { public init(from decoder: any Decoder) throws { var container = try decoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + + self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + } public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + + try codecHelper.encode(id, forKey: .id, container: &container) + + + } +} + +extension PersonKey : Equatable { + public static func == (lhs: PersonKey, rhs: PersonKey) -> Bool { + + if lhs.id != rhs.id { + return false + } + + return true + } +} + +extension PersonKey : Hashable { + public func hash(into hasher: inout Hasher) { + + hasher.combine(self.id) + + } +} + +extension PersonKey : Sendable {} + + + +public struct ScalarBoundaryKey { + + public private(set) var id: UUID + + + enum CodingKeys: String, CodingKey { + + case id + + } +} + +extension ScalarBoundaryKey : Codable { + public init(from decoder: any Decoder) throws { + var container = try decoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - try codecHelper.encode(id, forKey: .id, container: &container) + + self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + + try codecHelper.encode(id, forKey: .id, container: &container) + + + } } -extension ScalarBoundaryKey: Equatable { +extension ScalarBoundaryKey : Equatable { public static func == (lhs: ScalarBoundaryKey, rhs: ScalarBoundaryKey) -> Bool { + if lhs.id != rhs.id { return false } - + return true } } -extension ScalarBoundaryKey: Hashable { +extension ScalarBoundaryKey : Hashable { public func hash(into hasher: inout Hasher) { - hasher.combine(id) + + hasher.combine(self.id) + } } +extension ScalarBoundaryKey : Sendable {} + + + public struct StandardScalarsKey { + public private(set) var id: UUID + enum CodingKeys: String, CodingKey { - case id + + case id + } } -extension StandardScalarsKey: Codable { +extension StandardScalarsKey : Codable { public init(from decoder: any Decoder) throws { var container = try decoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + + self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + } public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - try codecHelper.encode(id, forKey: .id, container: &container) - } + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + + try codecHelper.encode(id, forKey: .id, container: &container) + + + } } -extension StandardScalarsKey: Equatable { +extension StandardScalarsKey : Equatable { public static func == (lhs: StandardScalarsKey, rhs: StandardScalarsKey) -> Bool { + if lhs.id != rhs.id { return false } - + return true } } -extension StandardScalarsKey: Hashable { +extension StandardScalarsKey : Hashable { public func hash(into hasher: inout Hasher) { - hasher.combine(id) + + hasher.combine(self.id) + } } +extension StandardScalarsKey : Sendable {} + + + public struct TestAutoIdKey { + public private(set) var id: UUID + enum CodingKeys: String, CodingKey { - case id + + case id + } } -extension TestAutoIdKey: Codable { +extension TestAutoIdKey : Codable { public init(from decoder: any Decoder) throws { var container = try decoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + + self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + } public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - try codecHelper.encode(id, forKey: .id, container: &container) - } + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + + try codecHelper.encode(id, forKey: .id, container: &container) + + + } } -extension TestAutoIdKey: Equatable { +extension TestAutoIdKey : Equatable { public static func == (lhs: TestAutoIdKey, rhs: TestAutoIdKey) -> Bool { + if lhs.id != rhs.id { return false } - + return true } } -extension TestAutoIdKey: Hashable { +extension TestAutoIdKey : Hashable { public func hash(into hasher: inout Hasher) { - hasher.combine(id) + + hasher.combine(self.id) + } } +extension TestAutoIdKey : Sendable {} + + + public struct TestIdKey { + public private(set) var id: UUID + enum CodingKeys: String, CodingKey { - case id + + case id + } } -extension TestIdKey: Codable { +extension TestIdKey : Codable { public init(from decoder: any Decoder) throws { var container = try decoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + + self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + } public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - try codecHelper.encode(id, forKey: .id, container: &container) - } + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + + try codecHelper.encode(id, forKey: .id, container: &container) + + + } } -extension TestIdKey: Equatable { +extension TestIdKey : Equatable { public static func == (lhs: TestIdKey, rhs: TestIdKey) -> Bool { + if lhs.id != rhs.id { return false } - + return true } } -extension TestIdKey: Hashable { +extension TestIdKey : Hashable { public func hash(into hasher: inout Hasher) { - hasher.combine(id) + + hasher.combine(self.id) + } } + +extension TestIdKey : Sendable {} + + diff --git a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkOperations.swift b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkOperations.swift index 6c83203..d46042c 100644 --- a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkOperations.swift +++ b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkOperations.swift @@ -1,1313 +1,1949 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +import Foundation +import FirebaseCore import FirebaseDataConnect -import Foundation + + + + + + + + + + + + + + + + + + + // MARK: Common Enums -public enum OrderDirection: String, Codable { - case ASC - case DESC -} +public enum OrderDirection: String, Codable, Sendable { + case ASC = "ASC" + case DESC = "DESC" + } // End enum definitions -public class CreateTestIdMutation { + + + + + + + + +public class CreateTestIdMutation{ + let dataConnect: DataConnect - public init(dataConnect: DataConnect) { + init(dataConnect: DataConnect) { self.dataConnect = dataConnect } public static let OperationName = "createTestId" - public typealias Ref = MutationRef + public typealias Ref = MutationRef public struct Variables: OperationVariable { - public var - id: UUID + + + public var +id: UUID + + + + + + public init ( + +id: UUID + + + ) { + self.id = id + - public init(id: UUID) { - self.id = id + } public static func == (lhs: Variables, rhs: Variables) -> Bool { - return lhs.id == rhs.id + + return lhs.id == rhs.id + } - public func hash(into hasher: inout Hasher) { - hasher.combine(id) - } + +public func hash(into hasher: inout Hasher) { + + hasher.combine(id) + +} enum CodingKeys: String, CodingKey { + case id + } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - + + try codecHelper.encode(id, forKey: .id, container: &container) + + } - } - public struct Data: Decodable { - public var - testId_insert: TestIdKey } - public func ref(id: UUID) - -> MutationRef { - let variables = CreateTestIdMutation.Variables(id: id) + public struct Data: Decodable, Sendable { - let ref = dataConnect.mutation( - name: "createTestId", - variables: variables, - resultsDataType: CreateTestIdMutation.Data.self - ) - return ref as MutationRef - } - public func execute(id: UUID) async throws -> OperationResult { - let variables = CreateTestIdMutation.Variables(id: id) - let ref = dataConnect.mutation( - name: "createTestId", - variables: variables, - resultsDataType: CreateTestIdMutation.Data.self - ) +public var +testId_insert: TestIdKey - return try await ref.execute() } + + public func ref( + +id: UUID + + ) -> MutationRef { + var variables = CreateTestIdMutation.Variables(id:id) + + + let ref = dataConnect.mutation(name: "createTestId", variables: variables, resultsDataType:CreateTestIdMutation.Data.self) + return ref as MutationRef + } + + @MainActor + public func execute( + +id: UUID + + ) async throws -> OperationResult { + var variables = CreateTestIdMutation.Variables(id:id) + + + let ref = dataConnect.mutation(name: "createTestId", variables: variables, resultsDataType:CreateTestIdMutation.Data.self) + + return try await ref.execute() + + } } -public class CreateTestAutoIdMutation { + + + + + +public class CreateTestAutoIdMutation{ + let dataConnect: DataConnect - public init(dataConnect: DataConnect) { + init(dataConnect: DataConnect) { self.dataConnect = dataConnect } public static let OperationName = "createTestAutoId" - public typealias Ref = MutationRef< - CreateTestAutoIdMutation.Data, - CreateTestAutoIdMutation.Variables - > + public typealias Ref = MutationRef - public struct Variables: OperationVariable {} + public struct Variables: OperationVariable { - public struct Data: Decodable { - public var - testAutoId_insert: TestAutoIdKey + + } - public func ref( - ) -> MutationRef { - let variables = CreateTestAutoIdMutation.Variables() + public struct Data: Decodable, Sendable { - let ref = dataConnect.mutation( - name: "createTestAutoId", - variables: variables, - resultsDataType: CreateTestAutoIdMutation.Data.self - ) - return ref as MutationRef - } - public func execute( - ) async throws -> OperationResult { - let variables = CreateTestAutoIdMutation.Variables() - let ref = dataConnect.mutation( - name: "createTestAutoId", - variables: variables, - resultsDataType: CreateTestAutoIdMutation.Data.self - ) +public var +testAutoId_insert: TestAutoIdKey - return try await ref.execute() } -} -public class CreateStandardScalarMutation { - let dataConnect: DataConnect + public func ref( + + ) -> MutationRef { + var variables = CreateTestAutoIdMutation.Variables() + + + let ref = dataConnect.mutation(name: "createTestAutoId", variables: variables, resultsDataType:CreateTestAutoIdMutation.Data.self) + return ref as MutationRef + } + + @MainActor + public func execute( + + ) async throws -> OperationResult { + var variables = CreateTestAutoIdMutation.Variables() + + + let ref = dataConnect.mutation(name: "createTestAutoId", variables: variables, resultsDataType:CreateTestAutoIdMutation.Data.self) + + return try await ref.execute() + + } +} - public init(dataConnect: DataConnect) { - self.dataConnect = dataConnect - } - public static let OperationName = "createStandardScalar" - public typealias Ref = MutationRef< - CreateStandardScalarMutation.Data, - CreateStandardScalarMutation.Variables - > - public struct Variables: OperationVariable { - public var - id: UUID - public var - number: Int - public var - text: String +public class CreateStandardScalarMutation{ - public var - decimal: Double + let dataConnect: DataConnect - public init(id: UUID, + init(dataConnect: DataConnect) { + self.dataConnect = dataConnect + } - number: Int, + public static let OperationName = "createStandardScalar" - text: String, + public typealias Ref = MutationRef - decimal: Double) { - self.id = id - self.number = number - self.text = text - self.decimal = decimal + public struct Variables: OperationVariable { + + + public var +id: UUID + + + + public var +number: Int + + + + public var +text: String + + + + public var +decimal: Double + + + + + + public init ( + +id: UUID +, + +number: Int +, + +text: String +, + +decimal: Double + + + ) { + self.id = id + self.number = number + self.text = text + self.decimal = decimal + + + } public static func == (lhs: Variables, rhs: Variables) -> Bool { - return lhs.id == rhs.id && - lhs.number == rhs.number && - lhs.text == rhs.text && - lhs.decimal == rhs.decimal + + return lhs.id == rhs.id && + lhs.number == rhs.number && + lhs.text == rhs.text && + lhs.decimal == rhs.decimal + } - public func hash(into hasher: inout Hasher) { - hasher.combine(id) - - hasher.combine(number) - - hasher.combine(text) - - hasher.combine(decimal) - } + +public func hash(into hasher: inout Hasher) { + + hasher.combine(id) + + hasher.combine(number) + + hasher.combine(text) + + hasher.combine(decimal) + +} enum CodingKeys: String, CodingKey { + case id - + case number - + case text - + case decimal + } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - + + try codecHelper.encode(id, forKey: .id, container: &container) - + + + try codecHelper.encode(number, forKey: .number, container: &container) - + + + try codecHelper.encode(text, forKey: .text, container: &container) - + + + try codecHelper.encode(decimal, forKey: .decimal, container: &container) + + } - } - public struct Data: Decodable { - public var - standardScalars_insert: StandardScalarsKey } - public func ref(id: UUID, + public struct Data: Decodable, Sendable { - number: Int, - text: String, - decimal: Double) - -> MutationRef { - let variables = CreateStandardScalarMutation.Variables( - id: id, - number: number, - text: text, - decimal: decimal - ) +public var +standardScalars_insert: StandardScalarsKey - let ref = dataConnect.mutation( - name: "createStandardScalar", - variables: variables, - resultsDataType: CreateStandardScalarMutation.Data.self - ) - return ref as MutationRef< - CreateStandardScalarMutation.Data, - CreateStandardScalarMutation.Variables - > } - public func execute(id: UUID, + public func ref( + +id: UUID +, +number: Int +, +text: String +, +decimal: Double + + ) -> MutationRef { + var variables = CreateStandardScalarMutation.Variables(id:id,number:number,text:text,decimal:decimal) + + + let ref = dataConnect.mutation(name: "createStandardScalar", variables: variables, resultsDataType:CreateStandardScalarMutation.Data.self) + return ref as MutationRef + } + + @MainActor + public func execute( + +id: UUID +, +number: Int +, +text: String +, +decimal: Double + + ) async throws -> OperationResult { + var variables = CreateStandardScalarMutation.Variables(id:id,number:number,text:text,decimal:decimal) + + + let ref = dataConnect.mutation(name: "createStandardScalar", variables: variables, resultsDataType:CreateStandardScalarMutation.Data.self) + + return try await ref.execute() + + } +} - number: Int, - text: String, - decimal: Double) async throws - -> OperationResult { - let variables = CreateStandardScalarMutation.Variables( - id: id, - number: number, - text: text, - decimal: decimal - ) - let ref = dataConnect.mutation( - name: "createStandardScalar", - variables: variables, - resultsDataType: CreateStandardScalarMutation.Data.self - ) - return try await ref.execute() - } -} -public class CreateScalarBoundaryMutation { +public class CreateScalarBoundaryMutation{ + let dataConnect: DataConnect - public init(dataConnect: DataConnect) { + init(dataConnect: DataConnect) { self.dataConnect = dataConnect } public static let OperationName = "createScalarBoundary" - public typealias Ref = MutationRef< - CreateScalarBoundaryMutation.Data, - CreateScalarBoundaryMutation.Variables - > + public typealias Ref = MutationRef public struct Variables: OperationVariable { - public var - id: UUID - - public var - maxNumber: Int - - public var - minNumber: Int - - public var - maxDecimal: Double - - public var - minDecimal: Double - - public init(id: UUID, - - maxNumber: Int, - - minNumber: Int, - - maxDecimal: Double, - - minDecimal: Double) { - self.id = id - self.maxNumber = maxNumber - self.minNumber = minNumber - self.maxDecimal = maxDecimal - self.minDecimal = minDecimal + + + public var +id: UUID + + + + public var +maxNumber: Int + + + + public var +minNumber: Int + + + + public var +maxDecimal: Double + + + + public var +minDecimal: Double + + + + + + public init ( + +id: UUID +, + +maxNumber: Int +, + +minNumber: Int +, + +maxDecimal: Double +, + +minDecimal: Double + + + ) { + self.id = id + self.maxNumber = maxNumber + self.minNumber = minNumber + self.maxDecimal = maxDecimal + self.minDecimal = minDecimal + + + } public static func == (lhs: Variables, rhs: Variables) -> Bool { - return lhs.id == rhs.id && - lhs.maxNumber == rhs.maxNumber && - lhs.minNumber == rhs.minNumber && - lhs.maxDecimal == rhs.maxDecimal && - lhs.minDecimal == rhs.minDecimal + + return lhs.id == rhs.id && + lhs.maxNumber == rhs.maxNumber && + lhs.minNumber == rhs.minNumber && + lhs.maxDecimal == rhs.maxDecimal && + lhs.minDecimal == rhs.minDecimal + } - public func hash(into hasher: inout Hasher) { - hasher.combine(id) - - hasher.combine(maxNumber) - - hasher.combine(minNumber) - - hasher.combine(maxDecimal) - - hasher.combine(minDecimal) - } + +public func hash(into hasher: inout Hasher) { + + hasher.combine(id) + + hasher.combine(maxNumber) + + hasher.combine(minNumber) + + hasher.combine(maxDecimal) + + hasher.combine(minDecimal) + +} enum CodingKeys: String, CodingKey { + case id - + case maxNumber - + case minNumber - + case maxDecimal - + case minDecimal + } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - + + try codecHelper.encode(id, forKey: .id, container: &container) - + + + try codecHelper.encode(maxNumber, forKey: .maxNumber, container: &container) - + + + try codecHelper.encode(minNumber, forKey: .minNumber, container: &container) - + + + try codecHelper.encode(maxDecimal, forKey: .maxDecimal, container: &container) - + + + try codecHelper.encode(minDecimal, forKey: .minDecimal, container: &container) + + } - } - public struct Data: Decodable { - public var - scalarBoundary_insert: ScalarBoundaryKey } - public func ref(id: UUID, - - maxNumber: Int, + public struct Data: Decodable, Sendable { - minNumber: Int, - maxDecimal: Double, - minDecimal: Double) - -> MutationRef { - let variables = CreateScalarBoundaryMutation.Variables( - id: id, - maxNumber: maxNumber, - minNumber: minNumber, - maxDecimal: maxDecimal, - minDecimal: minDecimal - ) +public var +scalarBoundary_insert: ScalarBoundaryKey - let ref = dataConnect.mutation( - name: "createScalarBoundary", - variables: variables, - resultsDataType: CreateScalarBoundaryMutation.Data.self - ) - return ref as MutationRef< - CreateScalarBoundaryMutation.Data, - CreateScalarBoundaryMutation.Variables - > } - public func execute(id: UUID, + public func ref( + +id: UUID +, +maxNumber: Int +, +minNumber: Int +, +maxDecimal: Double +, +minDecimal: Double + + ) -> MutationRef { + var variables = CreateScalarBoundaryMutation.Variables(id:id,maxNumber:maxNumber,minNumber:minNumber,maxDecimal:maxDecimal,minDecimal:minDecimal) + + + let ref = dataConnect.mutation(name: "createScalarBoundary", variables: variables, resultsDataType:CreateScalarBoundaryMutation.Data.self) + return ref as MutationRef + } + + @MainActor + public func execute( + +id: UUID +, +maxNumber: Int +, +minNumber: Int +, +maxDecimal: Double +, +minDecimal: Double + + ) async throws -> OperationResult { + var variables = CreateScalarBoundaryMutation.Variables(id:id,maxNumber:maxNumber,minNumber:minNumber,maxDecimal:maxDecimal,minDecimal:minDecimal) + + + let ref = dataConnect.mutation(name: "createScalarBoundary", variables: variables, resultsDataType:CreateScalarBoundaryMutation.Data.self) + + return try await ref.execute() + + } +} - maxNumber: Int, - minNumber: Int, - maxDecimal: Double, - minDecimal: Double) async throws - -> OperationResult { - let variables = CreateScalarBoundaryMutation.Variables( - id: id, - maxNumber: maxNumber, - minNumber: minNumber, - maxDecimal: maxDecimal, - minDecimal: minDecimal - ) - let ref = dataConnect.mutation( - name: "createScalarBoundary", - variables: variables, - resultsDataType: CreateScalarBoundaryMutation.Data.self - ) - return try await ref.execute() - } -} +public class CreateLargeNumMutation{ -public class CreateLargeNumMutation { let dataConnect: DataConnect - public init(dataConnect: DataConnect) { + init(dataConnect: DataConnect) { self.dataConnect = dataConnect } public static let OperationName = "createLargeNum" - public typealias Ref = MutationRef + public typealias Ref = MutationRef public struct Variables: OperationVariable { - public var - id: UUID - - public var - num: Int64 - - public var - maxNum: Int64 - - public var - minNum: Int64 - - public init(id: UUID, - - num: Int64, - - maxNum: Int64, - - minNum: Int64) { - self.id = id - self.num = num - self.maxNum = maxNum - self.minNum = minNum + + + public var +id: UUID + + + + public var +num: Int64 + + + + public var +maxNum: Int64 + + + + public var +minNum: Int64 + + + + + + public init ( + +id: UUID +, + +num: Int64 +, + +maxNum: Int64 +, + +minNum: Int64 + + + ) { + self.id = id + self.num = num + self.maxNum = maxNum + self.minNum = minNum + + + } public static func == (lhs: Variables, rhs: Variables) -> Bool { - return lhs.id == rhs.id && - lhs.num == rhs.num && - lhs.maxNum == rhs.maxNum && - lhs.minNum == rhs.minNum + + return lhs.id == rhs.id && + lhs.num == rhs.num && + lhs.maxNum == rhs.maxNum && + lhs.minNum == rhs.minNum + } - public func hash(into hasher: inout Hasher) { - hasher.combine(id) - - hasher.combine(num) - - hasher.combine(maxNum) - - hasher.combine(minNum) - } + +public func hash(into hasher: inout Hasher) { + + hasher.combine(id) + + hasher.combine(num) + + hasher.combine(maxNum) + + hasher.combine(minNum) + +} enum CodingKeys: String, CodingKey { + case id - + case num - + case maxNum - + case minNum + } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - + + try codecHelper.encode(id, forKey: .id, container: &container) - + + + try codecHelper.encode(num, forKey: .num, container: &container) - + + + try codecHelper.encode(maxNum, forKey: .maxNum, container: &container) - + + + try codecHelper.encode(minNum, forKey: .minNum, container: &container) + + } - } - public struct Data: Decodable { - public var - largeIntType_insert: LargeIntTypeKey } - public func ref(id: UUID, + public struct Data: Decodable, Sendable { - num: Int64, - maxNum: Int64, - minNum: Int64) - -> MutationRef { - let variables = CreateLargeNumMutation.Variables( - id: id, - num: num, - maxNum: maxNum, - minNum: minNum - ) +public var +largeIntType_insert: LargeIntTypeKey - let ref = dataConnect.mutation( - name: "createLargeNum", - variables: variables, - resultsDataType: CreateLargeNumMutation.Data.self - ) - return ref as MutationRef } - public func execute(id: UUID, + public func ref( + +id: UUID +, +num: Int64 +, +maxNum: Int64 +, +minNum: Int64 + + ) -> MutationRef { + var variables = CreateLargeNumMutation.Variables(id:id,num:num,maxNum:maxNum,minNum:minNum) + + + let ref = dataConnect.mutation(name: "createLargeNum", variables: variables, resultsDataType:CreateLargeNumMutation.Data.self) + return ref as MutationRef + } + + @MainActor + public func execute( + +id: UUID +, +num: Int64 +, +maxNum: Int64 +, +minNum: Int64 + + ) async throws -> OperationResult { + var variables = CreateLargeNumMutation.Variables(id:id,num:num,maxNum:maxNum,minNum:minNum) + + + let ref = dataConnect.mutation(name: "createLargeNum", variables: variables, resultsDataType:CreateLargeNumMutation.Data.self) + + return try await ref.execute() + + } +} - num: Int64, - maxNum: Int64, - minNum: Int64) async throws -> OperationResult { - let variables = CreateLargeNumMutation.Variables( - id: id, - num: num, - maxNum: maxNum, - minNum: minNum - ) - let ref = dataConnect.mutation( - name: "createLargeNum", - variables: variables, - resultsDataType: CreateLargeNumMutation.Data.self - ) - return try await ref.execute() - } -} -public class CreateLocalDateMutation { +public class CreateLocalDateMutation{ + let dataConnect: DataConnect - public init(dataConnect: DataConnect) { + init(dataConnect: DataConnect) { self.dataConnect = dataConnect } public static let OperationName = "createLocalDate" - public typealias Ref = MutationRef< - CreateLocalDateMutation.Data, - CreateLocalDateMutation.Variables - > + public typealias Ref = MutationRef public struct Variables: OperationVariable { - public var - id: UUID - - public var - localDate: LocalDate - - public init(id: UUID, - - localDate: LocalDate) { - self.id = id - self.localDate = localDate + + + public var +id: UUID + + + + public var +localDate: LocalDate + + + + + + public init ( + +id: UUID +, + +localDate: LocalDate + + + ) { + self.id = id + self.localDate = localDate + + + } public static func == (lhs: Variables, rhs: Variables) -> Bool { - return lhs.id == rhs.id && - lhs.localDate == rhs.localDate + + return lhs.id == rhs.id && + lhs.localDate == rhs.localDate + } - public func hash(into hasher: inout Hasher) { - hasher.combine(id) - - hasher.combine(localDate) - } + +public func hash(into hasher: inout Hasher) { + + hasher.combine(id) + + hasher.combine(localDate) + +} enum CodingKeys: String, CodingKey { + case id - + case localDate + } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - + + try codecHelper.encode(id, forKey: .id, container: &container) - + + + try codecHelper.encode(localDate, forKey: .localDate, container: &container) + + } - } - public struct Data: Decodable { - public var - localDateType_insert: LocalDateTypeKey } - public func ref(id: UUID, + public struct Data: Decodable, Sendable { - localDate: LocalDate) - -> MutationRef { - let variables = CreateLocalDateMutation.Variables(id: id, localDate: localDate) - let ref = dataConnect.mutation( - name: "createLocalDate", - variables: variables, - resultsDataType: CreateLocalDateMutation.Data.self - ) - return ref as MutationRef + +public var +localDateType_insert: LocalDateTypeKey + } - public func execute(id: UUID, + public func ref( + +id: UUID +, +localDate: LocalDate + + ) -> MutationRef { + var variables = CreateLocalDateMutation.Variables(id:id,localDate:localDate) + + + let ref = dataConnect.mutation(name: "createLocalDate", variables: variables, resultsDataType:CreateLocalDateMutation.Data.self) + return ref as MutationRef + } + + @MainActor + public func execute( + +id: UUID +, +localDate: LocalDate + + ) async throws -> OperationResult { + var variables = CreateLocalDateMutation.Variables(id:id,localDate:localDate) + + + let ref = dataConnect.mutation(name: "createLocalDate", variables: variables, resultsDataType:CreateLocalDateMutation.Data.self) + + return try await ref.execute() + + } +} + - localDate: LocalDate) async throws - -> OperationResult { - let variables = CreateLocalDateMutation.Variables(id: id, localDate: localDate) - let ref = dataConnect.mutation( - name: "createLocalDate", - variables: variables, - resultsDataType: CreateLocalDateMutation.Data.self - ) - return try await ref.execute() - } -} -public class CreateAnyValueTypeMutation { + +public class CreateAnyValueTypeMutation{ + let dataConnect: DataConnect - public init(dataConnect: DataConnect) { + init(dataConnect: DataConnect) { self.dataConnect = dataConnect } public static let OperationName = "createAnyValueType" - public typealias Ref = MutationRef< - CreateAnyValueTypeMutation.Data, - CreateAnyValueTypeMutation.Variables - > + public typealias Ref = MutationRef public struct Variables: OperationVariable { - public var - id: UUID - - public var - props: AnyValue - - public init(id: UUID, - - props: AnyValue) { - self.id = id - self.props = props + + + public var +id: UUID + + + + public var +props: AnyValue + + + + + + public init ( + +id: UUID +, + +props: AnyValue + + + ) { + self.id = id + self.props = props + + + } public static func == (lhs: Variables, rhs: Variables) -> Bool { - return lhs.id == rhs.id && - lhs.props == rhs.props + + return lhs.id == rhs.id && + lhs.props == rhs.props + } - public func hash(into hasher: inout Hasher) { - hasher.combine(id) - - hasher.combine(props) - } + +public func hash(into hasher: inout Hasher) { + + hasher.combine(id) + + hasher.combine(props) + +} enum CodingKeys: String, CodingKey { + case id - + case props + } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - + + try codecHelper.encode(id, forKey: .id, container: &container) - + + + try codecHelper.encode(props, forKey: .props, container: &container) + + } + } - public struct Data: Decodable { - public var - anyValueType_insert: AnyValueTypeKey + public struct Data: Decodable, Sendable { + + + +public var +anyValueType_insert: AnyValueTypeKey + } - public func ref(id: UUID, + public func ref( + +id: UUID +, +props: AnyValue + + ) -> MutationRef { + var variables = CreateAnyValueTypeMutation.Variables(id:id,props:props) + + + let ref = dataConnect.mutation(name: "createAnyValueType", variables: variables, resultsDataType:CreateAnyValueTypeMutation.Data.self) + return ref as MutationRef + } + + @MainActor + public func execute( + +id: UUID +, +props: AnyValue + + ) async throws -> OperationResult { + var variables = CreateAnyValueTypeMutation.Variables(id:id,props:props) + + + let ref = dataConnect.mutation(name: "createAnyValueType", variables: variables, resultsDataType:CreateAnyValueTypeMutation.Data.self) + + return try await ref.execute() + + } +} + - props: AnyValue) -> MutationRef< - CreateAnyValueTypeMutation.Data, - CreateAnyValueTypeMutation.Variables - > { - let variables = CreateAnyValueTypeMutation.Variables(id: id, props: props) - let ref = dataConnect.mutation( - name: "createAnyValueType", - variables: variables, - resultsDataType: CreateAnyValueTypeMutation.Data.self - ) - return ref as MutationRef< - CreateAnyValueTypeMutation.Data, - CreateAnyValueTypeMutation.Variables - > + + + +public class InsertMultiplePeopleMutation{ + + let dataConnect: DataConnect + + init(dataConnect: DataConnect) { + self.dataConnect = dataConnect } - public func execute(id: UUID, + public static let OperationName = "InsertMultiplePeople" - props: AnyValue) async throws - -> OperationResult { - let variables = CreateAnyValueTypeMutation.Variables(id: id, props: props) + public typealias Ref = MutationRef - let ref = dataConnect.mutation( - name: "createAnyValueType", - variables: variables, - resultsDataType: CreateAnyValueTypeMutation.Data.self - ) + public struct Variables: OperationVariable { + + + public var +id: UUID + + + + public var +name1: String + + + + public var +name2: String + + + + + + public init ( + +id: UUID +, + +name1: String +, + +name2: String + + + ) { + self.id = id + self.name1 = name1 + self.name2 = name2 + + + + } + + public static func == (lhs: Variables, rhs: Variables) -> Bool { + + return lhs.id == rhs.id && + lhs.name1 == rhs.name1 && + lhs.name2 == rhs.name2 + + } + + +public func hash(into hasher: inout Hasher) { + + hasher.combine(id) + + hasher.combine(name1) + + hasher.combine(name2) + +} + + enum CodingKeys: String, CodingKey { + + case id + + case name1 + + case name2 + + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + + try codecHelper.encode(id, forKey: .id, container: &container) + + + + try codecHelper.encode(name1, forKey: .name1, container: &container) + + + + try codecHelper.encode(name2, forKey: .name2, container: &container) + + + } - return try await ref.execute() } + + public struct Data: Decodable, Sendable { + + + +public var +person1: PersonKey + + + + +public var +person2: PersonKey + + } + + public func ref( + +id: UUID +, +name1: String +, +name2: String + + ) -> MutationRef { + var variables = InsertMultiplePeopleMutation.Variables(id:id,name1:name1,name2:name2) + + + let ref = dataConnect.mutation(name: "InsertMultiplePeople", variables: variables, resultsDataType:InsertMultiplePeopleMutation.Data.self) + return ref as MutationRef + } + + @MainActor + public func execute( + +id: UUID +, +name1: String +, +name2: String + + ) async throws -> OperationResult { + var variables = InsertMultiplePeopleMutation.Variables(id:id,name1:name1,name2:name2) + + + let ref = dataConnect.mutation(name: "InsertMultiplePeople", variables: variables, resultsDataType:InsertMultiplePeopleMutation.Data.self) + + return try await ref.execute() + + } } -public class GetStandardScalarQuery { + + + + + +public class GetStandardScalarQuery{ + let dataConnect: DataConnect - public init(dataConnect: DataConnect) { + init(dataConnect: DataConnect) { self.dataConnect = dataConnect } public static let OperationName = "GetStandardScalar" - public typealias Ref = QueryRefObservableObject< - GetStandardScalarQuery.Data, - GetStandardScalarQuery.Variables - > + public typealias Ref = QueryRefObservableObject public struct Variables: OperationVariable { - public var - id: UUID + + + public var +id: UUID - public init(id: UUID) { - self.id = id + + + + + public init ( + +id: UUID + + + ) { + self.id = id + + + } public static func == (lhs: Variables, rhs: Variables) -> Bool { - return lhs.id == rhs.id + + return lhs.id == rhs.id + } - public func hash(into hasher: inout Hasher) { - hasher.combine(id) - } + +public func hash(into hasher: inout Hasher) { + + hasher.combine(id) + +} enum CodingKeys: String, CodingKey { + case id + } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - + + try codecHelper.encode(id, forKey: .id, container: &container) + + } - } - public struct Data: Decodable { - public struct StandardScalars: Decodable, Hashable, Equatable, Identifiable { - public var - id: UUID + } - public var - number: Int + public struct Data: Decodable, Sendable { - public var - text: String - public var - decimal: Double - public var standardScalarsKey: StandardScalarsKey { - return StandardScalarsKey( - id: id - ) - } - public func hash(into hasher: inout Hasher) { - hasher.combine(id) - } +public struct StandardScalars: Decodable, Sendable ,Hashable, Equatable, Identifiable { + - public static func == (lhs: StandardScalars, rhs: StandardScalars) -> Bool { - return lhs.id == rhs.id - } - enum CodingKeys: String, CodingKey { - case id +public var +id: UUID - case number - case text - case decimal - } +public var +number: Int - public init(from decoder: any Decoder) throws { - var container = try decoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) - number = try codecHelper.decode(Int.self, forKey: .number, container: &container) +public var +text: String - text = try codecHelper.decode(String.self, forKey: .text, container: &container) - decimal = try codecHelper.decode(Double.self, forKey: .decimal, container: &container) - } - } - public var - standardScalars: StandardScalars? - } +public var +decimal: Double - public func ref(id: UUID) - -> QueryRefObservableObject { - let variables = GetStandardScalarQuery.Variables(id: id) - let ref = dataConnect.query( - name: "GetStandardScalar", - variables: variables, - resultsDataType: GetStandardScalarQuery.Data.self, - publisher: .observableObject + + public var standardScalarsKey: StandardScalarsKey { + return StandardScalarsKey( + + id: id ) - return ref as! QueryRefObservableObject< - GetStandardScalarQuery.Data, - GetStandardScalarQuery.Variables - > } - public func execute(id: UUID) async throws -> OperationResult { - let variables = GetStandardScalarQuery.Variables(id: id) + +public func hash(into hasher: inout Hasher) { + + hasher.combine(id) + +} +public static func == (lhs: StandardScalars, rhs: StandardScalars) -> Bool { + + return lhs.id == rhs.id + + } - let ref = dataConnect.query( - name: "GetStandardScalar", - variables: variables, - resultsDataType: GetStandardScalarQuery.Data.self, - publisher: .observableObject - ) + + + + enum CodingKeys: String, CodingKey { + + case id + + case number + + case text + + case decimal + + } + + public init(from decoder: any Decoder) throws { + var container = try decoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + + + self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + + + + self.number = try codecHelper.decode(Int.self, forKey: .number, container: &container) + + + + self.text = try codecHelper.decode(String.self, forKey: .text, container: &container) + + + + self.decimal = try codecHelper.decode(Double.self, forKey: .decimal, container: &container) + + + } +} +public var +standardScalars: StandardScalars? - let refCast = ref as! QueryRefObservableObject< - GetStandardScalarQuery.Data, - GetStandardScalarQuery.Variables - > - return try await refCast.execute() } + + public func ref( + +id: UUID + + ) -> QueryRefObservableObject { + var variables = GetStandardScalarQuery.Variables(id:id) + + + let ref = dataConnect.query(name: "GetStandardScalar", variables: variables, resultsDataType:GetStandardScalarQuery.Data.self, publisher: .observableObject) + return ref as! QueryRefObservableObject + } + + @MainActor + public func execute( + +id: UUID + + ) async throws -> OperationResult { + var variables = GetStandardScalarQuery.Variables(id:id) + + + let ref = dataConnect.query(name: "GetStandardScalar", variables: variables, resultsDataType:GetStandardScalarQuery.Data.self, publisher: .observableObject) + + let refCast = ref as! QueryRefObservableObject + return try await refCast.execute() + + } } -public class GetScalarBoundaryQuery { + + + + + +public class GetScalarBoundaryQuery{ + let dataConnect: DataConnect - public init(dataConnect: DataConnect) { + init(dataConnect: DataConnect) { self.dataConnect = dataConnect } public static let OperationName = "GetScalarBoundary" - public typealias Ref = QueryRefObservableObject< - GetScalarBoundaryQuery.Data, - GetScalarBoundaryQuery.Variables - > + public typealias Ref = QueryRefObservableObject public struct Variables: OperationVariable { - public var - id: UUID + + + public var +id: UUID + + + + + + public init ( + +id: UUID - public init(id: UUID) { - self.id = id + + ) { + self.id = id + + + } public static func == (lhs: Variables, rhs: Variables) -> Bool { - return lhs.id == rhs.id + + return lhs.id == rhs.id + } - public func hash(into hasher: inout Hasher) { - hasher.combine(id) - } + +public func hash(into hasher: inout Hasher) { + + hasher.combine(id) + +} enum CodingKeys: String, CodingKey { + case id + } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - + + try codecHelper.encode(id, forKey: .id, container: &container) + + } + } - public struct Data: Decodable { - public struct ScalarBoundary: Decodable { - public var - maxNumber: Int + public struct Data: Decodable, Sendable { - public var - minNumber: Int - public var - maxDecimal: Double - public var - minDecimal: Double - enum CodingKeys: String, CodingKey { - case maxNumber +public struct ScalarBoundary: Decodable, Sendable { + - case minNumber - case maxDecimal +public var +maxNumber: Int - case minDecimal - } - public init(from decoder: any Decoder) throws { - var container = try decoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - maxNumber = try codecHelper.decode(Int.self, forKey: .maxNumber, container: &container) +public var +minNumber: Int - minNumber = try codecHelper.decode(Int.self, forKey: .minNumber, container: &container) - maxDecimal = try codecHelper.decode(Double.self, forKey: .maxDecimal, container: &container) - minDecimal = try codecHelper.decode(Double.self, forKey: .minDecimal, container: &container) - } - } +public var +maxDecimal: Double - public var - scalarBoundary: ScalarBoundary? - } - public func ref(id: UUID) - -> QueryRefObservableObject { - let variables = GetScalarBoundaryQuery.Variables(id: id) - let ref = dataConnect.query( - name: "GetScalarBoundary", - variables: variables, - resultsDataType: GetScalarBoundaryQuery.Data.self, - publisher: .observableObject - ) - return ref as! QueryRefObservableObject< - GetScalarBoundaryQuery.Data, - GetScalarBoundaryQuery.Variables - > - } +public var +minDecimal: Double - public func execute(id: UUID) async throws -> OperationResult { - let variables = GetScalarBoundaryQuery.Variables(id: id) - let ref = dataConnect.query( - name: "GetScalarBoundary", - variables: variables, - resultsDataType: GetScalarBoundaryQuery.Data.self, - publisher: .observableObject - ) + - let refCast = ref as! QueryRefObservableObject< - GetScalarBoundaryQuery.Data, - GetScalarBoundaryQuery.Variables - > - return try await refCast.execute() + + enum CodingKeys: String, CodingKey { + + case maxNumber + + case minNumber + + case maxDecimal + + case minDecimal + } + + public init(from decoder: any Decoder) throws { + var container = try decoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + + + self.maxNumber = try codecHelper.decode(Int.self, forKey: .maxNumber, container: &container) + + + + self.minNumber = try codecHelper.decode(Int.self, forKey: .minNumber, container: &container) + + + + self.maxDecimal = try codecHelper.decode(Double.self, forKey: .maxDecimal, container: &container) + + + + self.minDecimal = try codecHelper.decode(Double.self, forKey: .minDecimal, container: &container) + + + } +} +public var +scalarBoundary: ScalarBoundary? + + } + + public func ref( + +id: UUID + + ) -> QueryRefObservableObject { + var variables = GetScalarBoundaryQuery.Variables(id:id) + + + let ref = dataConnect.query(name: "GetScalarBoundary", variables: variables, resultsDataType:GetScalarBoundaryQuery.Data.self, publisher: .observableObject) + return ref as! QueryRefObservableObject + } + + @MainActor + public func execute( + +id: UUID + + ) async throws -> OperationResult { + var variables = GetScalarBoundaryQuery.Variables(id:id) + + + let ref = dataConnect.query(name: "GetScalarBoundary", variables: variables, resultsDataType:GetScalarBoundaryQuery.Data.self, publisher: .observableObject) + + let refCast = ref as! QueryRefObservableObject + return try await refCast.execute() + + } } -public class GetLargeNumQuery { + + + + + +public class GetLargeNumQuery{ + let dataConnect: DataConnect - public init(dataConnect: DataConnect) { + init(dataConnect: DataConnect) { self.dataConnect = dataConnect } public static let OperationName = "GetLargeNum" - public typealias Ref = QueryRefObservableObject + public typealias Ref = QueryRefObservableObject public struct Variables: OperationVariable { - public var - id: UUID + + + public var +id: UUID + + + + + + public init ( + +id: UUID - public init(id: UUID) { - self.id = id + + ) { + self.id = id + + + } public static func == (lhs: Variables, rhs: Variables) -> Bool { - return lhs.id == rhs.id + + return lhs.id == rhs.id + } - public func hash(into hasher: inout Hasher) { - hasher.combine(id) - } + +public func hash(into hasher: inout Hasher) { + + hasher.combine(id) + +} enum CodingKeys: String, CodingKey { + case id + } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - + + try codecHelper.encode(id, forKey: .id, container: &container) + + } + } - public struct Data: Decodable { - public struct LargeIntType: Decodable { - public var - num: Int64 + public struct Data: Decodable, Sendable { - public var - maxNum: Int64 - public var - minNum: Int64 - enum CodingKeys: String, CodingKey { - case num - case maxNum +public struct LargeIntType: Decodable, Sendable { + - case minNum - } - public init(from decoder: any Decoder) throws { - var container = try decoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() +public var +num: Int64 - num = try codecHelper.decode(Int64.self, forKey: .num, container: &container) - maxNum = try codecHelper.decode(Int64.self, forKey: .maxNum, container: &container) - minNum = try codecHelper.decode(Int64.self, forKey: .minNum, container: &container) - } - } +public var +maxNum: Int64 - public var - largeIntType: LargeIntType? - } - public func ref(id: UUID) -> QueryRefObservableObject< - GetLargeNumQuery.Data, - GetLargeNumQuery.Variables - > { - let variables = GetLargeNumQuery.Variables(id: id) - - let ref = dataConnect.query( - name: "GetLargeNum", - variables: variables, - resultsDataType: GetLargeNumQuery.Data.self, - publisher: .observableObject - ) - return ref as! QueryRefObservableObject - } - public func execute(id: UUID) async throws -> OperationResult { - let variables = GetLargeNumQuery.Variables(id: id) +public var +minNum: Int64 - let ref = dataConnect.query( - name: "GetLargeNum", - variables: variables, - resultsDataType: GetLargeNumQuery.Data.self, - publisher: .observableObject - ) - let refCast = ref as! QueryRefObservableObject< - GetLargeNumQuery.Data, - GetLargeNumQuery.Variables - > - return try await refCast.execute() + + + + enum CodingKeys: String, CodingKey { + + case num + + case maxNum + + case minNum + + } + + public init(from decoder: any Decoder) throws { + var container = try decoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + + + self.num = try codecHelper.decode(Int64.self, forKey: .num, container: &container) + + + + self.maxNum = try codecHelper.decode(Int64.self, forKey: .maxNum, container: &container) + + + + self.minNum = try codecHelper.decode(Int64.self, forKey: .minNum, container: &container) + + } } +public var +largeIntType: LargeIntType? + + } + + public func ref( + +id: UUID + + ) -> QueryRefObservableObject { + var variables = GetLargeNumQuery.Variables(id:id) + + + let ref = dataConnect.query(name: "GetLargeNum", variables: variables, resultsDataType:GetLargeNumQuery.Data.self, publisher: .observableObject) + return ref as! QueryRefObservableObject + } + + @MainActor + public func execute( + +id: UUID + + ) async throws -> OperationResult { + var variables = GetLargeNumQuery.Variables(id:id) + + + let ref = dataConnect.query(name: "GetLargeNum", variables: variables, resultsDataType:GetLargeNumQuery.Data.self, publisher: .observableObject) + + let refCast = ref as! QueryRefObservableObject + return try await refCast.execute() + + } +} + + + + + + +public class GetLocalDateTypeQuery{ -public class GetLocalDateTypeQuery { let dataConnect: DataConnect - public init(dataConnect: DataConnect) { + init(dataConnect: DataConnect) { self.dataConnect = dataConnect } public static let OperationName = "GetLocalDateType" - public typealias Ref = QueryRefObservableObject< - GetLocalDateTypeQuery.Data, - GetLocalDateTypeQuery.Variables - > + public typealias Ref = QueryRefObservableObject public struct Variables: OperationVariable { - public var - id: UUID + + + public var +id: UUID + - public init(id: UUID) { - self.id = id + + + + public init ( + +id: UUID + + + ) { + self.id = id + + + } public static func == (lhs: Variables, rhs: Variables) -> Bool { - return lhs.id == rhs.id + + return lhs.id == rhs.id + } - public func hash(into hasher: inout Hasher) { - hasher.combine(id) - } + +public func hash(into hasher: inout Hasher) { + + hasher.combine(id) + +} enum CodingKeys: String, CodingKey { + case id + } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - + + try codecHelper.encode(id, forKey: .id, container: &container) + + } + } - public struct Data: Decodable { - public struct LocalDateType: Decodable { - public var - localDate: LocalDate? - - enum CodingKeys: String, CodingKey { - case localDate - } - - public init(from decoder: any Decoder) throws { - var container = try decoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - localDate = try codecHelper.decode( - LocalDate?.self, - forKey: .localDate, - container: &container - ) - } - } + public struct Data: Decodable, Sendable { - public var - localDateType: LocalDateType? - } - public func ref(id: UUID) -> QueryRefObservableObject< - GetLocalDateTypeQuery.Data, - GetLocalDateTypeQuery.Variables - > { - let variables = GetLocalDateTypeQuery.Variables(id: id) - - let ref = dataConnect.query( - name: "GetLocalDateType", - variables: variables, - resultsDataType: GetLocalDateTypeQuery.Data.self, - publisher: .observableObject - ) - return ref as! QueryRefObservableObject< - GetLocalDateTypeQuery.Data, - GetLocalDateTypeQuery.Variables - > + + +public struct LocalDateType: Decodable, Sendable { + + + +public var +localDate: LocalDate? + + + + + + enum CodingKeys: String, CodingKey { + + case localDate + } - public func execute(id: UUID) async throws -> OperationResult { - let variables = GetLocalDateTypeQuery.Variables(id: id) + public init(from decoder: any Decoder) throws { + var container = try decoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() - let ref = dataConnect.query( - name: "GetLocalDateType", - variables: variables, - resultsDataType: GetLocalDateTypeQuery.Data.self, - publisher: .observableObject - ) + + + self.localDate = try codecHelper.decode(LocalDate?.self, forKey: .localDate, container: &container) + + + } +} +public var +localDateType: LocalDateType? - let refCast = ref as! QueryRefObservableObject< - GetLocalDateTypeQuery.Data, - GetLocalDateTypeQuery.Variables - > - return try await refCast.execute() } + + public func ref( + +id: UUID + + ) -> QueryRefObservableObject { + var variables = GetLocalDateTypeQuery.Variables(id:id) + + + let ref = dataConnect.query(name: "GetLocalDateType", variables: variables, resultsDataType:GetLocalDateTypeQuery.Data.self, publisher: .observableObject) + return ref as! QueryRefObservableObject + } + + @MainActor + public func execute( + +id: UUID + + ) async throws -> OperationResult { + var variables = GetLocalDateTypeQuery.Variables(id:id) + + + let ref = dataConnect.query(name: "GetLocalDateType", variables: variables, resultsDataType:GetLocalDateTypeQuery.Data.self, publisher: .observableObject) + + let refCast = ref as! QueryRefObservableObject + return try await refCast.execute() + + } } -public class GetAnyValueTypeQuery { + + + + + +public class GetAnyValueTypeQuery{ + let dataConnect: DataConnect - public init(dataConnect: DataConnect) { + init(dataConnect: DataConnect) { self.dataConnect = dataConnect } public static let OperationName = "GetAnyValueType" - public typealias Ref = QueryRefObservableObject< - GetAnyValueTypeQuery.Data, - GetAnyValueTypeQuery.Variables - > + public typealias Ref = QueryRefObservableObject public struct Variables: OperationVariable { - public var - id: UUID + + + public var +id: UUID - public init(id: UUID) { - self.id = id + + + + + public init ( + +id: UUID + + + ) { + self.id = id + + + } public static func == (lhs: Variables, rhs: Variables) -> Bool { - return lhs.id == rhs.id + + return lhs.id == rhs.id + } - public func hash(into hasher: inout Hasher) { - hasher.combine(id) - } + +public func hash(into hasher: inout Hasher) { + + hasher.combine(id) + +} enum CodingKeys: String, CodingKey { + case id + } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - + + try codecHelper.encode(id, forKey: .id, container: &container) + + } + } - public struct Data: Decodable { - public struct AnyValueType: Decodable { - public var - props: AnyValue + public struct Data: Decodable, Sendable { - enum CodingKeys: String, CodingKey { - case props - } - public init(from decoder: any Decoder) throws { - var container = try decoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - props = try codecHelper.decode(AnyValue.self, forKey: .props, container: &container) - } - } - public var - anyValueType: AnyValueType? - } +public struct AnyValueType: Decodable, Sendable { + - public func ref(id: UUID) -> QueryRefObservableObject< - GetAnyValueTypeQuery.Data, - GetAnyValueTypeQuery.Variables - > { - let variables = GetAnyValueTypeQuery.Variables(id: id) - - let ref = dataConnect.query( - name: "GetAnyValueType", - variables: variables, - resultsDataType: GetAnyValueTypeQuery.Data.self, - publisher: .observableObject - ) - return ref as! QueryRefObservableObject< - GetAnyValueTypeQuery.Data, - GetAnyValueTypeQuery.Variables - > + +public var +props: AnyValue + + + + + + enum CodingKeys: String, CodingKey { + + case props + } - public func execute(id: UUID) async throws -> OperationResult { - let variables = GetAnyValueTypeQuery.Variables(id: id) + public init(from decoder: any Decoder) throws { + var container = try decoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() - let ref = dataConnect.query( - name: "GetAnyValueType", - variables: variables, - resultsDataType: GetAnyValueTypeQuery.Data.self, - publisher: .observableObject - ) + + + self.props = try codecHelper.decode(AnyValue.self, forKey: .props, container: &container) + + + } +} +public var +anyValueType: AnyValueType? - let refCast = ref as! QueryRefObservableObject< - GetAnyValueTypeQuery.Data, - GetAnyValueTypeQuery.Variables - > - return try await refCast.execute() } + + public func ref( + +id: UUID + + ) -> QueryRefObservableObject { + var variables = GetAnyValueTypeQuery.Variables(id:id) + + + let ref = dataConnect.query(name: "GetAnyValueType", variables: variables, resultsDataType:GetAnyValueTypeQuery.Data.self, publisher: .observableObject) + return ref as! QueryRefObservableObject + } + + @MainActor + public func execute( + +id: UUID + + ) async throws -> OperationResult { + var variables = GetAnyValueTypeQuery.Variables(id:id) + + + let ref = dataConnect.query(name: "GetAnyValueType", variables: variables, resultsDataType:GetAnyValueTypeQuery.Data.self, publisher: .observableObject) + + let refCast = ref as! QueryRefObservableObject + return try await refCast.execute() + + } } + + diff --git a/Tests/Integration/PartialErrorsDemo.swift b/Tests/Integration/PartialErrorsDemo.swift new file mode 100644 index 0000000..f00142e --- /dev/null +++ b/Tests/Integration/PartialErrorsDemo.swift @@ -0,0 +1,54 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import XCTest + +import FirebaseCore +@testable import FirebaseDataConnect + +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) +func demo(id: UUID, connector: KitchenSinkConnector) async throws + -> InsertMultiplePeopleMutation.Data { + + do { + return try await connector.insertMultiplePeopleMutation.execute( + id: id, name1: "name1", name2: "name2").data + } catch let dcError { + guard let dcError = dcError as? DataConnectError else { + throw dcError + } + + let response = switch dcError { + case .operationExecutionFailed(let messages, let response): response + default: throw dcError + } + + let foo1Path = [OperationFailureResponseErrorInfo.PathSegment.field("foo1")] + if let error = response.errorInfoList.first(where: { $0.path == foo1Path }) { + print("Inserting 1st entry with ID \(id) failed: \(error.message)") + } else { + print("Inserting 1st entry with ID \(id) succeeded") + } + + let foo2Path = [OperationFailureResponseErrorInfo.PathSegment.field("foo2")] + if let error = response.errorInfoList.first(where: { $0.path == foo2Path }) { + print("Inserting 2nd entry with ID \(id) failed: \(error.message)") + } else { + print("Inserting 2nd entry with ID \(id) succeeded") + } + + throw dcError + } +} + diff --git a/Tests/Integration/Resources/fdc-kitchensink/dataconnect/default/mutations.gql b/Tests/Integration/Resources/fdc-kitchensink/dataconnect/default/mutations.gql index 6557068..82a34de 100644 --- a/Tests/Integration/Resources/fdc-kitchensink/dataconnect/default/mutations.gql +++ b/Tests/Integration/Resources/fdc-kitchensink/dataconnect/default/mutations.gql @@ -63,3 +63,11 @@ mutation createAnyValueType($id: UUID!, $props: Any!) @auth(level: PUBLIC) { props: $props }) } + +# Notice how both "inserts" use the same ID; this means that one of them +# will necessarily fail because you can't have two rows with the same ID. +mutation InsertMultiplePeople($id: UUID!, $name1: String!, $name2: String!) { + person1: person_insert(data: { id: $id, name: $name1 }) + person2: person_insert(data: { id: $id, name: $name2 }) +} + diff --git a/Tests/Integration/Resources/fdc-kitchensink/dataconnect/schema/schema.gql b/Tests/Integration/Resources/fdc-kitchensink/dataconnect/schema/schema.gql index 82db457..f837a87 100644 --- a/Tests/Integration/Resources/fdc-kitchensink/dataconnect/schema/schema.gql +++ b/Tests/Integration/Resources/fdc-kitchensink/dataconnect/schema/schema.gql @@ -54,3 +54,8 @@ type AnyValueType @table { id: UUID! props: Any! } + +type Person @table { + name: String! +} + From f55305a9c9f2453b922ea4f98f4d1482041b0481 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Fri, 14 Mar 2025 16:42:43 -0400 Subject: [PATCH 09/28] PartialErrorsDemo.swift: add usage of decodedData() to demo its use. --- Tests/Integration/PartialErrorsDemo.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Tests/Integration/PartialErrorsDemo.swift b/Tests/Integration/PartialErrorsDemo.swift index f00142e..d0bcd14 100644 --- a/Tests/Integration/PartialErrorsDemo.swift +++ b/Tests/Integration/PartialErrorsDemo.swift @@ -30,7 +30,7 @@ func demo(id: UUID, connector: KitchenSinkConnector) async throws } let response = switch dcError { - case .operationExecutionFailed(let messages, let response): response + case .operationExecutionFailed(_, let response): response default: throw dcError } @@ -48,6 +48,12 @@ func demo(id: UUID, connector: KitchenSinkConnector) async throws print("Inserting 2nd entry with ID \(id) succeeded") } + if let decodedData = response.decodedData(asType: InsertMultiplePeopleMutation.Data.self) { + print("Even though there was an error, decoding the data was successful:") + print("person1=\(decodedData.person1) person2=\(decodedData.person2)") + return decodedData + } + throw dcError } } From 98faec49f00c8b62d0690d657a101004ab013057 Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Fri, 21 Mar 2025 16:39:23 -0700 Subject: [PATCH 10/28] Updates matching API review and Refactored Errors --- Sources/DataConnectError.swift | 303 +++++++++++++++--- Sources/Internal/CodableHelpers.swift | 4 +- Sources/Internal/CodableTimestamp.swift | 4 +- Sources/Internal/Codec.swift | 2 +- Sources/Internal/GrpcClient.swift | 136 +++++--- Sources/QueryRef.swift | 12 +- Sources/Scalars/LocalDate.swift | 6 +- .../Sources/KitchenSinkClient.swift | 2 + .../Sources/KitchenSinkOperations.swift | 113 +++++++ Tests/Integration/IntegrationTestBase.swift | 1 + Tests/Integration/PartialErrorsDemo.swift | 60 ---- Tests/Integration/PartialErrorsTest.swift | 88 +++++ .../dataconnect/default/mutations.gql | 11 +- 13 files changed, 570 insertions(+), 172 deletions(-) delete mode 100644 Tests/Integration/PartialErrorsDemo.swift create mode 100644 Tests/Integration/PartialErrorsTest.swift diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index 79cfc19..3a2e6e2 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,74 +14,277 @@ import Foundation -/// Represents an error returned by the DataConnect service +// MARK: Base Error Definitions + +/// Protocol representing an error returned by the DataConnect service +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) +public protocol DataConnectError: Error, CustomDebugStringConvertible, CustomStringConvertible { + var message: String? { get } + var cause: Error? { get } +} + @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -public enum DataConnectError: Error { - /// no firebase app specified. configure not complete - case appNotConfigured +public extension DataConnectError { + var debugDescription: String { + return "{\(Self.self), message: \(message ?? "nil"), cause: \(String(describing: cause))}" + } + + var description: String { + return debugDescription + } +} - /// failed to configure gRPC - case grpcNotConfigured +/// Type erased DataConnectError +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) +public struct AnyDataConnectError: DataConnectError { - /// Invalid uuid format during encoding / decoding of data - case invalidUUID + private let dataConnectError: DataConnectError - /// date components specified to initialize LocalDate are invalid - case invalidLocalDateFormat + init(dataConnectError: E) { + self.dataConnectError = dataConnectError + } - /// timestamp components specified to initialize Timestamp are invalid - case invalidTimestampFormat + public var message: String? { + return dataConnectError.message + } - /// generic operation execution error - case operationExecutionFailed(messages: String?, response: OperationFailureResponse) + public var cause: (any Error)? { + return dataConnectError.cause + } } -// The data and errors sent to us from the backend in its response. @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -public protocol OperationFailureResponse { - // JSON string whose value is the "data" property provided by the backend in its response - // payload; may be `nil` if the "data" property was not provided in the backend response and/or - // was `null` in the backend response. - var jsonData: String? { get } - - // The list of errors in the "error" property provided by the backend in its response payload; - // may be empty if the "errors" property was not provided in the backend response and/or was an - // empty list in the backend response. - var errorInfoList: [OperationFailureResponseErrorInfo] { get } - - // Returns `jsonData` string decoded into the given type, if decoding was successful when the - // operation was executed. Returns `nil` if `jsonData` is `nil`, if `jsonData` was _not_ able to - // be decoded when the operation was executed, or if the given type is _not_ equal to the `Data` - // type that was used when the operation was executed. - // - // This function does _not_ do the decoding itself, but simply returns the decoded data, if any, - // that was decoded at the time of the operation's execution. - func decodedData(asType: Data.Type) -> Data? +/// Represents an error domain which can have more granular error codes +public protocol DataConnectDomainError: DataConnectError { + associatedtype ErrorCode: DataConnectErrorCode + + var code: ErrorCode { get } +} + +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) +public extension DataConnectDomainError { + var debugDescription: String { + return "{\(Self.self), code: \(code), message: \(message ?? "nil"), cause: \(String(describing: cause))}" + } + + var description: String { + return debugDescription + } +} + + +/// Error code within an error domain +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) +public protocol DataConnectErrorCode: CustomStringConvertible, Equatable, Sendable, CaseIterable { } + +// MARK: Data Connect Initialization Errors + +/// Error initializing Data Connect +public struct DataConnectInitError: DataConnectDomainError { + + public struct Code: DataConnectErrorCode { + private let code: String + private init(_ code: String) { self.code = code } + + + public static let appNotConfigured = Code("appNotConfigured") + public static let grpcNotConfigured = Code("grpcNotConfigured") + + public static var allCases: [DataConnectInitError.Code] { + return [appNotConfigured, grpcNotConfigured] + } + + public var description: String { return code } + } + + public let code: Code + + public private(set) var message: String? + + public private(set) var cause: Error? + + private init(code: Code, message: String? = nil, cause: Error? = nil) { + self.code = code + self.cause = cause + self.message = message + } + + static func appNotConfigured(message: String? = nil, cause: Error? = nil) -> DataConnectInitError { + return DataConnectInitError(code: .appNotConfigured, message: message, cause: cause) + } + + static func grpcNotConfigured(message: String? = nil, cause: Error? = nil) -> DataConnectInitError { + return DataConnectInitError(code: .grpcNotConfigured, message: message, cause: cause) + } +} + +// MARK: Data Codec Errors + +/// Data Encoding / Decoding Error +public struct DataConnectCodecError: DataConnectDomainError { + public struct Code: DataConnectErrorCode { + private let code: String + + private init(_ code: String) { self.code = code } + + public static let encodingFailed = Code("encodingFailed") + public static let decodingFailed = Code("decodingFailed") + public static let invalidUUID = Code("invalidUUID") + public static let invalidTimestampFormat = Code("invalidTimestampFormat") + public static let invalidLocalDateFormat = Code("invalidLocalDateFormat") + + public static var allCases: [DataConnectCodecError.Code] { + return [ + encodingFailed, + decodingFailed, + invalidUUID, + invalidTimestampFormat, + invalidLocalDateFormat + ] + } + + public var description: String { return code } + } + + public let code: Code + + public var message: String? + + public var cause: (any Error)? + + private init(code: Code, message: String? = nil, cause: Error? = nil) { + self.code = code + self.message = message + self.cause = cause + } + + static func encodingFailed(message: String? = nil, cause: Error? = nil) -> DataConnectCodecError { + return DataConnectCodecError(code: .encodingFailed, message: message, cause: cause) + } + + static func decodingFailed(message: String? = nil, cause: Error? = nil) -> DataConnectCodecError { + return DataConnectCodecError(code: .decodingFailed, message: message, cause: cause) + } + + static func invalidUUID(message: String? = nil, cause: Error? = nil) -> DataConnectCodecError { + return DataConnectCodecError(code: .invalidUUID, message: message, cause: cause) + } + + static func invalidTimestampFormat(message: String? = nil, cause: Error? = nil) -> DataConnectCodecError { + return DataConnectCodecError(code: .invalidTimestampFormat, message: message, cause: cause) + } + + static func invalidLocalDateFormat(message: String? = nil, cause: Error? = nil) -> DataConnectCodecError { + return DataConnectCodecError(code: .invalidLocalDateFormat, message: message, cause: cause) + } + +} + + +// MARK: Operation Execution Error including Partial Errors + +/// Data Connect Operation Failed +public struct DataConnectOperationError: DataConnectError { + public var kind: String { + return "operationError" + } + + public var message: String? + + public var cause: (any Error)? + + public private(set) var response: OperationFailureResponse? = nil + + private init(message: String? = nil, cause: Error? = nil, response: OperationFailureResponse?) { + self.response = response + self.message = message + } + + static func executionFailed(message: String? = nil, cause: Error? = nil, response: OperationFailureResponse? = nil) -> DataConnectOperationError { + return DataConnectOperationError(message: message, cause: cause, response: response) + } + } -struct OperationFailureResponseImpl : OperationFailureResponse { - public let jsonData: String? - public let errorInfoList: [OperationFailureResponseErrorInfo] +// The data and errors sent to us from the backend in its response. +// New struct, that contains the data and errors sent to us +// from the backend in its response. +public struct OperationFailureResponse : Sendable { + // JSON string whose value is the "data" property provided by the backend in + // its response payload; may be `nil` if the "data" property was not provided + // in the backend response and/or was `null` in the backend response. + public private(set) var rawJsonData: String? + + // The list of errors in the "error" property provided by the backend in + // its response payload; may be empty if the "errors" property was not + // provided in the backend response and/or was an empty list in the backend response. + public private(set) var errors: [ErrorInfo] + + // (Partially) decoded data + private let data: Sendable? - func decodedData(asType: Data.Type = Data.self) -> Data? { - return nil; + // Returns `jsonData` string decoded into the given type, if decoding was + // successful when the operation was executed. Returns `nil` if `jsonData` + // is `nil`, if `jsonData` was _not_ able to be decoded when the operation + // was executed, or if the given type is _not_ equal to the `Data` type that + // was used when the operation was executed. + // + // This function does _not_ do the decoding itself, but simply returns + // the decoded data, if any, that was decoded at the time of the + // operation's execution. + func data(asType: Data.Type = Data.self) -> Data? { + return data as? Data + } + + internal init( + rawJsonData: String? = nil, + errors: [ErrorInfo], + data: Sendable? + ) { + self.rawJsonData = rawJsonData + self.errors = errors + self.data = data + } + + public struct ErrorInfo: Codable, Sendable { + // The error message. + public let message: String + // The path to the field to which this error applies. + public let path: [PathSegment] + + public enum PathSegment: Codable, Equatable, Sendable { + case field(String) + case listIndex(Int) + } } + } // Information about an error provided by the backend in its response. @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -public struct OperationFailureResponseErrorInfo: Codable { - // The error message. - public let message: String - // The path to the field to which this error applies. - public let path: [PathSegment] +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) +public extension OperationFailureResponse.ErrorInfo.PathSegment { + init(from decoder: any Decoder) throws { + let container = try decoder.singleValueContainer() - @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) - public enum PathSegment: Codable, Equatable { - case field(String) - case listIndex(Int) + do { + let field = try container.decode(String.self) + self = .field(field) + } catch { + let index = try container.decode(Int.self) + self = .listIndex(index) + } } -} + func encode(to encoder: any Encoder) throws { + var container = encoder.singleValueContainer() + switch self { + case .field(let fieldVal): + try container.encode(fieldVal) + case .listIndex(let indexVal): + try container.encode(indexVal) + } + } +} diff --git a/Sources/Internal/CodableHelpers.swift b/Sources/Internal/CodableHelpers.swift index ca6506b..0eaea98 100644 --- a/Sources/Internal/CodableHelpers.swift +++ b/Sources/Internal/CodableHelpers.swift @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -40,7 +40,7 @@ class Int64CodableConverter: CodableConverter { } guard let int64Value = Int64(input) else { - throw DataConnectError.appNotConfigured + throw DataConnectInitError.appNotConfigured() } return int64Value } diff --git a/Sources/Internal/CodableTimestamp.swift b/Sources/Internal/CodableTimestamp.swift index 5864bd8..eb6d785 100644 --- a/Sources/Internal/CodableTimestamp.swift +++ b/Sources/Internal/CodableTimestamp.swift @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -55,7 +55,7 @@ extension CodableTimestamp { DataConnectLogger.error( "Timestamp string format \(timestampString) is not supported." ) - throw DataConnectError.invalidTimestampFormat + throw DataConnectCodecError.invalidTimestampFormat() } let buf: Google_Protobuf_Timestamp = diff --git a/Sources/Internal/Codec.swift b/Sources/Internal/Codec.swift index 6478f14..d7940e3 100644 --- a/Sources/Internal/Codec.swift +++ b/Sources/Internal/Codec.swift @@ -35,7 +35,7 @@ class Codec { } // Decode Protos to Codable - func decode(result: Google_Protobuf_Struct, asType: T.Type) throws -> T? { + func decode(result: Google_Protobuf_Struct, asType: T.Type) throws -> T { do { let jsonData = try result.jsonUTF8Data() let jsonDecoder = JSONDecoder() diff --git a/Sources/Internal/GrpcClient.swift b/Sources/Internal/GrpcClient.swift index 6f49166..a93e2f1 100644 --- a/Sources/Internal/GrpcClient.swift +++ b/Sources/Internal/GrpcClient.swift @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -133,7 +133,7 @@ actor GrpcClient: CustomStringConvertible { async throws -> OperationResult { guard let client else { DataConnectLogger.error("When calling executeQuery(), grpc client has not been configured.") - throw DataConnectError.grpcNotConfigured + throw DataConnectInitError.grpcNotConfigured() } let codec = Codec() @@ -151,37 +151,49 @@ actor GrpcClient: CustomStringConvertible { DataConnectLogger .debug("executeQuery() receives response: \(resultsString, privacy: .private).") + //lets decode partial errors. We need these whether we succeed or fail + let errorInfoList = createErrorInfoList(errors: results.errors) - // Not doing error decoding here - guard results.errors.isEmpty else { - throw DataConnectError.operationExecutionFailed( - messages: createErrorJson(errors: results.errors), - response: OperationFailureResponseImpl( - jsonData: resultsString, - errorInfoList: [] - ) - ) - } + // check if decode succeeds + do { + let decodedResults = try codec.decode(result: results.data, asType: resultType) - if let decodedResults = try codec.decode(result: results.data, asType: resultType) { - return OperationResult(data: decodedResults) - } else { - // In future, set this as error in OperationResult - DataConnectLogger - .debug("executeQuery() response: \(resultsString, privacy: .private) decode failed.") - throw DataConnectError.operationExecutionFailed( - messages: "decode failed", - response: OperationFailureResponseImpl( - jsonData: resultsString, - errorInfoList: [] + // even though decode succeeded, we may still have received partial errors + if !errorInfoList.isEmpty { + let failureResponse = OperationFailureResponse( + rawJsonData: resultsString, errors: errorInfoList, + data: decodedResults ) - ) + throw DataConnectOperationError.executionFailed( + response: failureResponse + ) + } else { + return OperationResult(data: decodedResults) + } + + } catch { + // we failed to decode + if !errorInfoList.isEmpty { + let failureResponse = OperationFailureResponse( + rawJsonData: resultsString, + errors: errorInfoList, + data: nil + ) + throw DataConnectOperationError + .executionFailed( + cause: error, + response: failureResponse + ) + } else { + throw DataConnectCodecError.decodingFailed(cause: error) + } } } catch { + // we failed at executing the call DataConnectLogger.error( "executeQuery(): \(requestString, privacy: .private) grpc call FAILED with \(error)." ) - throw error + throw DataConnectOperationError.executionFailed(cause: error) } } @@ -193,7 +205,7 @@ actor GrpcClient: CustomStringConvertible { guard let client else { DataConnectLogger .error("When calling executeMutation(), grpc client has not been configured.") - throw DataConnectError.grpcNotConfigured + throw DataConnectInitError.grpcNotConfigured() } let codec = Codec() @@ -212,28 +224,42 @@ actor GrpcClient: CustomStringConvertible { DataConnectLogger .debug("executeMutation() receives response: \(resultsString, privacy: .private).") - guard results.errors.isEmpty else { - throw DataConnectError.operationExecutionFailed( - messages: createErrorJson(errors: results.errors), - response: OperationFailureResponseImpl( - jsonData: resultsString, - errorInfoList: [] - ) - ) - } + //lets decode partial errors. We need these whether we succeed or fail + var errorInfoList = createErrorInfoList(errors: results.errors) - if let decodedResults = try codec.decode(result: results.data, asType: resultType) { - return OperationResult(data: decodedResults) - } else { - DataConnectLogger - .debug("executeMutation() response: \(resultsString, privacy: .private) decode failed.") - throw DataConnectError.operationExecutionFailed( - messages: "decode failed", - response: OperationFailureResponseImpl( - jsonData: resultsString, - errorInfoList: [] + // check if decode succeeds + do { + let decodedResults = try codec.decode(result: results.data, asType: resultType) + + // even though decode succeeded, we may still have received partial errors + if !errorInfoList.isEmpty { + let failureResponse = OperationFailureResponse( + rawJsonData: resultsString, errors: errorInfoList, + data: decodedResults ) - ) + throw DataConnectOperationError.executionFailed( + response: failureResponse + ) + } else { + return OperationResult(data: decodedResults) + } + + } catch { + // we failed to decode + if !errorInfoList.isEmpty { + let failureResponse = OperationFailureResponse( + rawJsonData: resultsString, + errors: errorInfoList, + data: nil + ) + throw DataConnectOperationError + .executionFailed( + cause: error, + response: failureResponse + ) + } else { + throw DataConnectCodecError.decodingFailed(cause: error) + } } } catch { DataConnectLogger.error( @@ -259,6 +285,24 @@ actor GrpcClient: CustomStringConvertible { } } + private func createErrorInfoList(errors: [FirebaseDataConnectGraphqlError]) -> [OperationFailureResponse.ErrorInfo] { + let errorList = errors.compactMap { errorProto in + do { + let errorJsonData = try errorProto.jsonUTF8Data() + let jsonDecoder = JSONDecoder() + let errorInfo = try jsonDecoder.decode( + OperationFailureResponse.ErrorInfo.self, + from: errorJsonData + ) + return errorInfo + } catch { + DataConnectLogger.error("Error decoding GraphQLError \(error)") + return nil + } + } + return errorList + } + func createCallOptions() async -> CallOptions { var headers = HPACKHeaders() diff --git a/Sources/QueryRef.swift b/Sources/QueryRef.swift index afd38a4..e68b285 100644 --- a/Sources/QueryRef.swift +++ b/Sources/QueryRef.swift @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -71,12 +71,12 @@ struct QueryRequest: OperationRequest, Hashable, Eq @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public protocol QueryRef: OperationRef { // This call starts query execution and publishes data - func subscribe() async throws -> AnyPublisher, Never> + func subscribe() async throws -> AnyPublisher, Never> } @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) actor GenericQueryRef: QueryRef { - private let resultsPublisher = PassthroughSubject, + private let resultsPublisher = PassthroughSubject, Never>() private let request: QueryRequest @@ -90,7 +90,7 @@ actor GenericQueryRef AnyPublisher, Never> { + public func subscribe() -> AnyPublisher, Never> { Task { do { _ = try await reloadResults() @@ -196,7 +196,7 @@ public class QueryRefObservableObject< /// Use this function ONLY if you plan to use the Query Ref outside of SwiftUI context - (UIKit, /// background updates,...) public func subscribe() async throws - -> AnyPublisher, Never> { + -> AnyPublisher, Never> { return await baseRef.subscribe() } } @@ -272,7 +272,7 @@ public class QueryRefObservation< /// Use this function ONLY if you plan to use the Query Ref outside of SwiftUI context - (UIKit, /// background updates,...) public func subscribe() async throws - -> AnyPublisher, Never> { + -> AnyPublisher, Never> { return await baseRef.subscribe() } } diff --git a/Sources/Scalars/LocalDate.swift b/Sources/Scalars/LocalDate.swift index 4356319..7da47cd 100644 --- a/Sources/Scalars/LocalDate.swift +++ b/Sources/Scalars/LocalDate.swift @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -36,7 +36,7 @@ public struct LocalDate: Codable, Comparable, CustomStringConvertible, Equatable dateComponents.calendar = calendar guard dateComponents.isValidDate, let date = dateComponents.date else { - throw DataConnectError.invalidLocalDateFormat + throw DataConnectCodecError.invalidLocalDateFormat() } self.date = date @@ -70,7 +70,7 @@ public struct LocalDate: Codable, Comparable, CustomStringConvertible, Equatable private func convert(dateString: String) throws -> Date { guard let date = dateFormatter.date(from: dateString) else { - throw DataConnectError.invalidLocalDateFormat + throw DataConnectCodecError.invalidLocalDateFormat() } return date } diff --git a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkClient.swift b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkClient.swift index c49c571..28a8321 100644 --- a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkClient.swift +++ b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkClient.swift @@ -38,6 +38,7 @@ public class KitchenSinkConnector { self.createLocalDateMutation = CreateLocalDateMutation(dataConnect: dataConnect) self.createAnyValueTypeMutation = CreateAnyValueTypeMutation(dataConnect: dataConnect) self.insertMultiplePeopleMutation = InsertMultiplePeopleMutation(dataConnect: dataConnect) + self.deleteNonExistentPeopleMutation = DeleteNonExistentPeopleMutation(dataConnect: dataConnect) self.getStandardScalarQuery = GetStandardScalarQuery(dataConnect: dataConnect) self.getScalarBoundaryQuery = GetScalarBoundaryQuery(dataConnect: dataConnect) self.getLargeNumQuery = GetLargeNumQuery(dataConnect: dataConnect) @@ -59,6 +60,7 @@ public let createLargeNumMutation: CreateLargeNumMutation public let createLocalDateMutation: CreateLocalDateMutation public let createAnyValueTypeMutation: CreateAnyValueTypeMutation public let insertMultiplePeopleMutation: InsertMultiplePeopleMutation +public let deleteNonExistentPeopleMutation: DeleteNonExistentPeopleMutation public let getStandardScalarQuery: GetStandardScalarQuery public let getScalarBoundaryQuery: GetScalarBoundaryQuery public let getLargeNumQuery: GetLargeNumQuery diff --git a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkOperations.swift b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkOperations.swift index d46042c..3d8699e 100644 --- a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkOperations.swift +++ b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkOperations.swift @@ -1158,6 +1158,119 @@ name2: String +public class DeleteNonExistentPeopleMutation{ + + let dataConnect: DataConnect + + init(dataConnect: DataConnect) { + self.dataConnect = dataConnect + } + + public static let OperationName = "DeleteNonExistentPeople" + + public typealias Ref = MutationRef + + public struct Variables: OperationVariable { + + + public var +id: UUID + + + + + + public init ( + +id: UUID + + + ) { + self.id = id + + + + } + + public static func == (lhs: Variables, rhs: Variables) -> Bool { + + return lhs.id == rhs.id + + } + + +public func hash(into hasher: inout Hasher) { + + hasher.combine(id) + +} + + enum CodingKeys: String, CodingKey { + + case id + + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + + try codecHelper.encode(id, forKey: .id, container: &container) + + + } + + } + + public struct Data: Decodable, Sendable { + + + +public var +person1: PersonKey? + + + + +public var +person2: PersonKey? + + } + + public func ref( + +id: UUID + + ) -> MutationRef { + var variables = DeleteNonExistentPeopleMutation.Variables(id:id) + + + let ref = dataConnect.mutation(name: "DeleteNonExistentPeople", variables: variables, resultsDataType:DeleteNonExistentPeopleMutation.Data.self) + return ref as MutationRef + } + + @MainActor + public func execute( + +id: UUID + + ) async throws -> OperationResult { + var variables = DeleteNonExistentPeopleMutation.Variables(id:id) + + + let ref = dataConnect.mutation(name: "DeleteNonExistentPeople", variables: variables, resultsDataType:DeleteNonExistentPeopleMutation.Data.self) + + return try await ref.execute() + + } +} + + + + + + public class GetStandardScalarQuery{ let dataConnect: DataConnect diff --git a/Tests/Integration/IntegrationTestBase.swift b/Tests/Integration/IntegrationTestBase.swift index ff18989..86f18a0 100644 --- a/Tests/Integration/IntegrationTestBase.swift +++ b/Tests/Integration/IntegrationTestBase.swift @@ -40,6 +40,7 @@ class IntegrationTestBase: XCTestCase { if defaultApp == nil { FirebaseApp.configure(options: options) defaultApp = FirebaseApp.app() + FirebaseConfiguration.shared.setLoggerLevel(.debug) } DataConnect.kitchenSinkConnector.useEmulator(port: 3628) } diff --git a/Tests/Integration/PartialErrorsDemo.swift b/Tests/Integration/PartialErrorsDemo.swift deleted file mode 100644 index d0bcd14..0000000 --- a/Tests/Integration/PartialErrorsDemo.swift +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import XCTest - -import FirebaseCore -@testable import FirebaseDataConnect - -@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -func demo(id: UUID, connector: KitchenSinkConnector) async throws - -> InsertMultiplePeopleMutation.Data { - - do { - return try await connector.insertMultiplePeopleMutation.execute( - id: id, name1: "name1", name2: "name2").data - } catch let dcError { - guard let dcError = dcError as? DataConnectError else { - throw dcError - } - - let response = switch dcError { - case .operationExecutionFailed(_, let response): response - default: throw dcError - } - - let foo1Path = [OperationFailureResponseErrorInfo.PathSegment.field("foo1")] - if let error = response.errorInfoList.first(where: { $0.path == foo1Path }) { - print("Inserting 1st entry with ID \(id) failed: \(error.message)") - } else { - print("Inserting 1st entry with ID \(id) succeeded") - } - - let foo2Path = [OperationFailureResponseErrorInfo.PathSegment.field("foo2")] - if let error = response.errorInfoList.first(where: { $0.path == foo2Path }) { - print("Inserting 2nd entry with ID \(id) failed: \(error.message)") - } else { - print("Inserting 2nd entry with ID \(id) succeeded") - } - - if let decodedData = response.decodedData(asType: InsertMultiplePeopleMutation.Data.self) { - print("Even though there was an error, decoding the data was successful:") - print("person1=\(decodedData.person1) person2=\(decodedData.person2)") - return decodedData - } - - throw dcError - } -} - diff --git a/Tests/Integration/PartialErrorsTest.swift b/Tests/Integration/PartialErrorsTest.swift new file mode 100644 index 0000000..e06feb1 --- /dev/null +++ b/Tests/Integration/PartialErrorsTest.swift @@ -0,0 +1,88 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import XCTest + +import FirebaseCore +@testable import FirebaseDataConnect + +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) +final class PartialErrorTests: IntegrationTestBase { + + override func setUp(completion: @escaping ((any Error)?) -> Void) { + Task { + do { + try await ProjectConfigurator.shared.configureProject() + completion(nil) + } catch { + completion(error) + } + } + } + + // Tests for insertion of duplicate primary keys. + // Second insert should fail + // Decode should fail so there isn't any partially encoded data + @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + func testDuplicatePrimaryKeys() async throws { + + let id = UUID() + + do { + let results = try await DataConnect.kitchenSinkConnector.insertMultiplePeopleMutation.execute( + id: id, name1: "name1", name2: "name2").data + print("results \(results)") + } catch let dcError as DataConnectOperationError { + + guard let response = dcError.response else { + XCTAssertFalse(false, "No response received from partial error") + throw dcError + } + + let foo1Path = [OperationFailureResponse.ErrorInfo.PathSegment.field("person2")] + let error = response.errors.first(where: { $0.path == foo1Path }) + XCTAssertNotNil(error) + + } catch { + XCTFail("Did not throw OperationError \(error)") + } + } + + // Test for partially decoded data + // Second delete fails but first succeeds and returns data + // We test for existence and equality of first key. + @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + func testPartiallyDecodedData() async throws { + let id = UUID() + do { + _ = try await DataConnect.kitchenSinkConnector.deleteNonExistentPeopleMutation.execute(id: id) + } catch let dcError as DataConnectOperationError { + + guard let response = dcError.response else { + XCTAssertFalse(false, "No response received from partial error") + throw dcError + } + + if let data = response.data( + asType: DeleteNonExistentPeopleMutation.Data.self + ) { + XCTAssertNil(data.person2) + XCTAssertTrue(data.person1?.id == id) + } else { + XCTFail("Partial Data is nil. We should have got back partially decoded data") + } + } + } + +} diff --git a/Tests/Integration/Resources/fdc-kitchensink/dataconnect/default/mutations.gql b/Tests/Integration/Resources/fdc-kitchensink/dataconnect/default/mutations.gql index 82a34de..4a9229f 100644 --- a/Tests/Integration/Resources/fdc-kitchensink/dataconnect/default/mutations.gql +++ b/Tests/Integration/Resources/fdc-kitchensink/dataconnect/default/mutations.gql @@ -66,8 +66,15 @@ mutation createAnyValueType($id: UUID!, $props: Any!) @auth(level: PUBLIC) { # Notice how both "inserts" use the same ID; this means that one of them # will necessarily fail because you can't have two rows with the same ID. -mutation InsertMultiplePeople($id: UUID!, $name1: String!, $name2: String!) { +mutation InsertMultiplePeople($id: UUID!, $name1: String!, $name2: String!) @auth(level: PUBLIC) { person1: person_insert(data: { id: $id, name: $name1 }) - person2: person_insert(data: { id: $id, name: $name2 }) + person2: person_insert(data: { id: $id, name: $name2 }) @check(expr: "false") } +# ID for second person does not exist. +# so first one will succeed but second should fail +mutation DeleteNonExistentPeople($id: UUID!) @auth(level: PUBLIC) { + person1_insert: person_insert(data: { id: $id, name: "name1" }) + person1: person_delete(id: $id) + person2: person_delete(id: "11A7649B-8FF5-485B-AFBF-2EA5F28894DF") +} From e29553c2716545cb0a580c655cbebaa2259618af Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Fri, 21 Mar 2025 16:41:18 -0700 Subject: [PATCH 11/28] Style Fixes --- Sources/DataConnectError.swift | 51 +- Sources/Internal/GrpcClient.swift | 7 +- .../Sources/KitchenSinkClient.swift | 86 +- .../KitchenSink/Sources/KitchenSinkKeys.swift | 322 +-- .../Sources/KitchenSinkOperations.swift | 2387 +++++++---------- Tests/Integration/PartialErrorsTest.swift | 12 +- 6 files changed, 1093 insertions(+), 1772 deletions(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index 3a2e6e2..a44aa9f 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -37,7 +37,6 @@ public extension DataConnectError { /// Type erased DataConnectError @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public struct AnyDataConnectError: DataConnectError { - private let dataConnectError: DataConnectError init(dataConnectError: E) { @@ -72,20 +71,17 @@ public extension DataConnectDomainError { } } - /// Error code within an error domain @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -public protocol DataConnectErrorCode: CustomStringConvertible, Equatable, Sendable, CaseIterable { } +public protocol DataConnectErrorCode: CustomStringConvertible, Equatable, Sendable, CaseIterable {} // MARK: Data Connect Initialization Errors /// Error initializing Data Connect public struct DataConnectInitError: DataConnectDomainError { - public struct Code: DataConnectErrorCode { private let code: String - private init(_ code: String) { self.code = code } - + private init(_ code: String) { self.code = code } public static let appNotConfigured = Code("appNotConfigured") public static let grpcNotConfigured = Code("grpcNotConfigured") @@ -109,11 +105,13 @@ public struct DataConnectInitError: DataConnectDomainError { self.message = message } - static func appNotConfigured(message: String? = nil, cause: Error? = nil) -> DataConnectInitError { + static func appNotConfigured(message: String? = nil, + cause: Error? = nil) -> DataConnectInitError { return DataConnectInitError(code: .appNotConfigured, message: message, cause: cause) } - static func grpcNotConfigured(message: String? = nil, cause: Error? = nil) -> DataConnectInitError { + static func grpcNotConfigured(message: String? = nil, + cause: Error? = nil) -> DataConnectInitError { return DataConnectInitError(code: .grpcNotConfigured, message: message, cause: cause) } } @@ -139,7 +137,7 @@ public struct DataConnectCodecError: DataConnectDomainError { decodingFailed, invalidUUID, invalidTimestampFormat, - invalidLocalDateFormat + invalidLocalDateFormat, ] } @@ -162,25 +160,25 @@ public struct DataConnectCodecError: DataConnectDomainError { return DataConnectCodecError(code: .encodingFailed, message: message, cause: cause) } - static func decodingFailed(message: String? = nil, cause: Error? = nil) -> DataConnectCodecError { - return DataConnectCodecError(code: .decodingFailed, message: message, cause: cause) - } + static func decodingFailed(message: String? = nil, cause: Error? = nil) -> DataConnectCodecError { + return DataConnectCodecError(code: .decodingFailed, message: message, cause: cause) + } static func invalidUUID(message: String? = nil, cause: Error? = nil) -> DataConnectCodecError { return DataConnectCodecError(code: .invalidUUID, message: message, cause: cause) } - static func invalidTimestampFormat(message: String? = nil, cause: Error? = nil) -> DataConnectCodecError { + static func invalidTimestampFormat(message: String? = nil, + cause: Error? = nil) -> DataConnectCodecError { return DataConnectCodecError(code: .invalidTimestampFormat, message: message, cause: cause) } - static func invalidLocalDateFormat(message: String? = nil, cause: Error? = nil) -> DataConnectCodecError { + static func invalidLocalDateFormat(message: String? = nil, + cause: Error? = nil) -> DataConnectCodecError { return DataConnectCodecError(code: .invalidLocalDateFormat, message: message, cause: cause) } - } - // MARK: Operation Execution Error including Partial Errors /// Data Connect Operation Failed @@ -200,17 +198,17 @@ public struct DataConnectOperationError: DataConnectError { self.message = message } - static func executionFailed(message: String? = nil, cause: Error? = nil, response: OperationFailureResponse? = nil) -> DataConnectOperationError { + static func executionFailed(message: String? = nil, cause: Error? = nil, + response: OperationFailureResponse? = nil) + -> DataConnectOperationError { return DataConnectOperationError(message: message, cause: cause, response: response) } - } - // The data and errors sent to us from the backend in its response. // New struct, that contains the data and errors sent to us // from the backend in its response. -public struct OperationFailureResponse : Sendable { +public struct OperationFailureResponse: Sendable { // JSON string whose value is the "data" property provided by the backend in // its response payload; may be `nil` if the "data" property was not provided // in the backend response and/or was `null` in the backend response. @@ -237,11 +235,9 @@ public struct OperationFailureResponse : Sendable { return data as? Data } - internal init( - rawJsonData: String? = nil, - errors: [ErrorInfo], - data: Sendable? - ) { + init(rawJsonData: String? = nil, + errors: [ErrorInfo], + data: Sendable?) { self.rawJsonData = rawJsonData self.errors = errors self.data = data @@ -258,7 +254,6 @@ public struct OperationFailureResponse : Sendable { case listIndex(Int) } } - } // Information about an error provided by the backend in its response. @@ -281,9 +276,9 @@ public extension OperationFailureResponse.ErrorInfo.PathSegment { func encode(to encoder: any Encoder) throws { var container = encoder.singleValueContainer() switch self { - case .field(let fieldVal): + case let .field(fieldVal): try container.encode(fieldVal) - case .listIndex(let indexVal): + case let .listIndex(indexVal): try container.encode(indexVal) } } diff --git a/Sources/Internal/GrpcClient.swift b/Sources/Internal/GrpcClient.swift index a93e2f1..5d252e7 100644 --- a/Sources/Internal/GrpcClient.swift +++ b/Sources/Internal/GrpcClient.swift @@ -151,7 +151,7 @@ actor GrpcClient: CustomStringConvertible { DataConnectLogger .debug("executeQuery() receives response: \(resultsString, privacy: .private).") - //lets decode partial errors. We need these whether we succeed or fail + // lets decode partial errors. We need these whether we succeed or fail let errorInfoList = createErrorInfoList(errors: results.errors) // check if decode succeeds @@ -224,7 +224,7 @@ actor GrpcClient: CustomStringConvertible { DataConnectLogger .debug("executeMutation() receives response: \(resultsString, privacy: .private).") - //lets decode partial errors. We need these whether we succeed or fail + // lets decode partial errors. We need these whether we succeed or fail var errorInfoList = createErrorInfoList(errors: results.errors) // check if decode succeeds @@ -285,7 +285,8 @@ actor GrpcClient: CustomStringConvertible { } } - private func createErrorInfoList(errors: [FirebaseDataConnectGraphqlError]) -> [OperationFailureResponse.ErrorInfo] { + private func createErrorInfoList(errors: [FirebaseDataConnectGraphqlError]) + -> [OperationFailureResponse.ErrorInfo] { let errorList = errors.compactMap { errorProto in do { let errorJsonData = try errorProto.jsonUTF8Data() diff --git a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkClient.swift b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkClient.swift index 28a8321..113f6d1 100644 --- a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkClient.swift +++ b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkClient.swift @@ -4,68 +4,64 @@ import Foundation import FirebaseCore import FirebaseDataConnect - - - - - - - public extension DataConnect { - static let kitchenSinkConnector: KitchenSinkConnector = { - let dc = DataConnect.dataConnect(connectorConfig: KitchenSinkConnector.connectorConfig, callerSDKType: .generated) + let dc = DataConnect.dataConnect( + connectorConfig: KitchenSinkConnector.connectorConfig, + callerSDKType: .generated + ) return KitchenSinkConnector(dataConnect: dc) }() - } public class KitchenSinkConnector { - let dataConnect: DataConnect - public static let connectorConfig = ConnectorConfig(serviceId: "fdc-kitchensink", location: "us-central1", connector: "kitchen-sink") + public static let connectorConfig = ConnectorConfig( + serviceId: "fdc-kitchensink", + location: "us-central1", + connector: "kitchen-sink" + ) init(dataConnect: DataConnect) { self.dataConnect = dataConnect - // init operations - self.createTestIdMutation = CreateTestIdMutation(dataConnect: dataConnect) - self.createTestAutoIdMutation = CreateTestAutoIdMutation(dataConnect: dataConnect) - self.createStandardScalarMutation = CreateStandardScalarMutation(dataConnect: dataConnect) - self.createScalarBoundaryMutation = CreateScalarBoundaryMutation(dataConnect: dataConnect) - self.createLargeNumMutation = CreateLargeNumMutation(dataConnect: dataConnect) - self.createLocalDateMutation = CreateLocalDateMutation(dataConnect: dataConnect) - self.createAnyValueTypeMutation = CreateAnyValueTypeMutation(dataConnect: dataConnect) - self.insertMultiplePeopleMutation = InsertMultiplePeopleMutation(dataConnect: dataConnect) - self.deleteNonExistentPeopleMutation = DeleteNonExistentPeopleMutation(dataConnect: dataConnect) - self.getStandardScalarQuery = GetStandardScalarQuery(dataConnect: dataConnect) - self.getScalarBoundaryQuery = GetScalarBoundaryQuery(dataConnect: dataConnect) - self.getLargeNumQuery = GetLargeNumQuery(dataConnect: dataConnect) - self.getLocalDateTypeQuery = GetLocalDateTypeQuery(dataConnect: dataConnect) - self.getAnyValueTypeQuery = GetAnyValueTypeQuery(dataConnect: dataConnect) - + // init operations + createTestIdMutation = CreateTestIdMutation(dataConnect: dataConnect) + createTestAutoIdMutation = CreateTestAutoIdMutation(dataConnect: dataConnect) + createStandardScalarMutation = CreateStandardScalarMutation(dataConnect: dataConnect) + createScalarBoundaryMutation = CreateScalarBoundaryMutation(dataConnect: dataConnect) + createLargeNumMutation = CreateLargeNumMutation(dataConnect: dataConnect) + createLocalDateMutation = CreateLocalDateMutation(dataConnect: dataConnect) + createAnyValueTypeMutation = CreateAnyValueTypeMutation(dataConnect: dataConnect) + insertMultiplePeopleMutation = InsertMultiplePeopleMutation(dataConnect: dataConnect) + deleteNonExistentPeopleMutation = DeleteNonExistentPeopleMutation(dataConnect: dataConnect) + getStandardScalarQuery = GetStandardScalarQuery(dataConnect: dataConnect) + getScalarBoundaryQuery = GetScalarBoundaryQuery(dataConnect: dataConnect) + getLargeNumQuery = GetLargeNumQuery(dataConnect: dataConnect) + getLocalDateTypeQuery = GetLocalDateTypeQuery(dataConnect: dataConnect) + getAnyValueTypeQuery = GetAnyValueTypeQuery(dataConnect: dataConnect) } - public func useEmulator(host: String = DataConnect.EmulatorDefaults.host, port: Int = DataConnect.EmulatorDefaults.port) { - self.dataConnect.useEmulator(host: host, port: port) + public func useEmulator(host: String = DataConnect.EmulatorDefaults.host, + port: Int = DataConnect.EmulatorDefaults.port) { + dataConnect.useEmulator(host: host, port: port) } // MARK: Operations -public let createTestIdMutation: CreateTestIdMutation -public let createTestAutoIdMutation: CreateTestAutoIdMutation -public let createStandardScalarMutation: CreateStandardScalarMutation -public let createScalarBoundaryMutation: CreateScalarBoundaryMutation -public let createLargeNumMutation: CreateLargeNumMutation -public let createLocalDateMutation: CreateLocalDateMutation -public let createAnyValueTypeMutation: CreateAnyValueTypeMutation -public let insertMultiplePeopleMutation: InsertMultiplePeopleMutation -public let deleteNonExistentPeopleMutation: DeleteNonExistentPeopleMutation -public let getStandardScalarQuery: GetStandardScalarQuery -public let getScalarBoundaryQuery: GetScalarBoundaryQuery -public let getLargeNumQuery: GetLargeNumQuery -public let getLocalDateTypeQuery: GetLocalDateTypeQuery -public let getAnyValueTypeQuery: GetAnyValueTypeQuery - + public let createTestIdMutation: CreateTestIdMutation + public let createTestAutoIdMutation: CreateTestAutoIdMutation + public let createStandardScalarMutation: CreateStandardScalarMutation + public let createScalarBoundaryMutation: CreateScalarBoundaryMutation + public let createLargeNumMutation: CreateLargeNumMutation + public let createLocalDateMutation: CreateLocalDateMutation + public let createAnyValueTypeMutation: CreateAnyValueTypeMutation + public let insertMultiplePeopleMutation: InsertMultiplePeopleMutation + public let deleteNonExistentPeopleMutation: DeleteNonExistentPeopleMutation + public let getStandardScalarQuery: GetStandardScalarQuery + public let getScalarBoundaryQuery: GetScalarBoundaryQuery + public let getLargeNumQuery: GetLargeNumQuery + public let getLocalDateTypeQuery: GetLocalDateTypeQuery + public let getAnyValueTypeQuery: GetAnyValueTypeQuery } diff --git a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkKeys.swift b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkKeys.swift index 064af2a..723c113 100644 --- a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkKeys.swift +++ b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkKeys.swift @@ -2,452 +2,338 @@ import Foundation import FirebaseDataConnect - - public struct AnyValueTypeKey { - public private(set) var id: UUID - enum CodingKeys: String, CodingKey { - - case id - + case id } } -extension AnyValueTypeKey : Codable { +extension AnyValueTypeKey: Codable { public init(from decoder: any Decoder) throws { var container = try decoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) - + id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) } public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - - try codecHelper.encode(id, forKey: .id, container: &container) - - - } + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + try codecHelper.encode(id, forKey: .id, container: &container) + } } -extension AnyValueTypeKey : Equatable { +extension AnyValueTypeKey: Equatable { public static func == (lhs: AnyValueTypeKey, rhs: AnyValueTypeKey) -> Bool { - if lhs.id != rhs.id { return false } - + return true } } -extension AnyValueTypeKey : Hashable { +extension AnyValueTypeKey: Hashable { public func hash(into hasher: inout Hasher) { - - hasher.combine(self.id) - + hasher.combine(id) } } -extension AnyValueTypeKey : Sendable {} - - +extension AnyValueTypeKey: Sendable {} public struct LargeIntTypeKey { - public private(set) var id: UUID - enum CodingKeys: String, CodingKey { - - case id - + case id } } -extension LargeIntTypeKey : Codable { +extension LargeIntTypeKey: Codable { public init(from decoder: any Decoder) throws { var container = try decoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) - + id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) } public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - - try codecHelper.encode(id, forKey: .id, container: &container) - - - } + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + try codecHelper.encode(id, forKey: .id, container: &container) + } } -extension LargeIntTypeKey : Equatable { +extension LargeIntTypeKey: Equatable { public static func == (lhs: LargeIntTypeKey, rhs: LargeIntTypeKey) -> Bool { - if lhs.id != rhs.id { return false } - + return true } } -extension LargeIntTypeKey : Hashable { +extension LargeIntTypeKey: Hashable { public func hash(into hasher: inout Hasher) { - - hasher.combine(self.id) - + hasher.combine(id) } } -extension LargeIntTypeKey : Sendable {} - - +extension LargeIntTypeKey: Sendable {} public struct LocalDateTypeKey { - public private(set) var id: UUID - enum CodingKeys: String, CodingKey { - - case id - + case id } } -extension LocalDateTypeKey : Codable { +extension LocalDateTypeKey: Codable { public init(from decoder: any Decoder) throws { var container = try decoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) - + id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) } public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - - try codecHelper.encode(id, forKey: .id, container: &container) - - - } + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + try codecHelper.encode(id, forKey: .id, container: &container) + } } -extension LocalDateTypeKey : Equatable { +extension LocalDateTypeKey: Equatable { public static func == (lhs: LocalDateTypeKey, rhs: LocalDateTypeKey) -> Bool { - if lhs.id != rhs.id { return false } - + return true } } -extension LocalDateTypeKey : Hashable { +extension LocalDateTypeKey: Hashable { public func hash(into hasher: inout Hasher) { - - hasher.combine(self.id) - + hasher.combine(id) } } -extension LocalDateTypeKey : Sendable {} - - +extension LocalDateTypeKey: Sendable {} public struct PersonKey { - public private(set) var id: UUID - enum CodingKeys: String, CodingKey { - - case id - + case id } } -extension PersonKey : Codable { +extension PersonKey: Codable { public init(from decoder: any Decoder) throws { var container = try decoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) - + id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) } public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - - try codecHelper.encode(id, forKey: .id, container: &container) - - - } + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + try codecHelper.encode(id, forKey: .id, container: &container) + } } -extension PersonKey : Equatable { +extension PersonKey: Equatable { public static func == (lhs: PersonKey, rhs: PersonKey) -> Bool { - if lhs.id != rhs.id { return false } - + return true } } -extension PersonKey : Hashable { +extension PersonKey: Hashable { public func hash(into hasher: inout Hasher) { - - hasher.combine(self.id) - + hasher.combine(id) } } -extension PersonKey : Sendable {} - - +extension PersonKey: Sendable {} public struct ScalarBoundaryKey { - public private(set) var id: UUID - enum CodingKeys: String, CodingKey { - - case id - + case id } } -extension ScalarBoundaryKey : Codable { +extension ScalarBoundaryKey: Codable { public init(from decoder: any Decoder) throws { var container = try decoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) - + id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) } public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - - try codecHelper.encode(id, forKey: .id, container: &container) - - - } + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + try codecHelper.encode(id, forKey: .id, container: &container) + } } -extension ScalarBoundaryKey : Equatable { +extension ScalarBoundaryKey: Equatable { public static func == (lhs: ScalarBoundaryKey, rhs: ScalarBoundaryKey) -> Bool { - if lhs.id != rhs.id { return false } - + return true } } -extension ScalarBoundaryKey : Hashable { +extension ScalarBoundaryKey: Hashable { public func hash(into hasher: inout Hasher) { - - hasher.combine(self.id) - + hasher.combine(id) } } -extension ScalarBoundaryKey : Sendable {} - - +extension ScalarBoundaryKey: Sendable {} public struct StandardScalarsKey { - public private(set) var id: UUID - enum CodingKeys: String, CodingKey { - - case id - + case id } } -extension StandardScalarsKey : Codable { +extension StandardScalarsKey: Codable { public init(from decoder: any Decoder) throws { var container = try decoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) - + id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) } public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - - try codecHelper.encode(id, forKey: .id, container: &container) - - - } + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + try codecHelper.encode(id, forKey: .id, container: &container) + } } -extension StandardScalarsKey : Equatable { +extension StandardScalarsKey: Equatable { public static func == (lhs: StandardScalarsKey, rhs: StandardScalarsKey) -> Bool { - if lhs.id != rhs.id { return false } - + return true } } -extension StandardScalarsKey : Hashable { +extension StandardScalarsKey: Hashable { public func hash(into hasher: inout Hasher) { - - hasher.combine(self.id) - + hasher.combine(id) } } -extension StandardScalarsKey : Sendable {} - - +extension StandardScalarsKey: Sendable {} public struct TestAutoIdKey { - public private(set) var id: UUID - enum CodingKeys: String, CodingKey { - - case id - + case id } } -extension TestAutoIdKey : Codable { +extension TestAutoIdKey: Codable { public init(from decoder: any Decoder) throws { var container = try decoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) - + id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) } public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - - try codecHelper.encode(id, forKey: .id, container: &container) - - - } + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + try codecHelper.encode(id, forKey: .id, container: &container) + } } -extension TestAutoIdKey : Equatable { +extension TestAutoIdKey: Equatable { public static func == (lhs: TestAutoIdKey, rhs: TestAutoIdKey) -> Bool { - if lhs.id != rhs.id { return false } - + return true } } -extension TestAutoIdKey : Hashable { +extension TestAutoIdKey: Hashable { public func hash(into hasher: inout Hasher) { - - hasher.combine(self.id) - + hasher.combine(id) } } -extension TestAutoIdKey : Sendable {} - - +extension TestAutoIdKey: Sendable {} public struct TestIdKey { - public private(set) var id: UUID - enum CodingKeys: String, CodingKey { - - case id - + case id } } -extension TestIdKey : Codable { +extension TestIdKey: Codable { public init(from decoder: any Decoder) throws { var container = try decoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) - + id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) } public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - - try codecHelper.encode(id, forKey: .id, container: &container) - - - } + var container = encoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + try codecHelper.encode(id, forKey: .id, container: &container) + } } -extension TestIdKey : Equatable { +extension TestIdKey: Equatable { public static func == (lhs: TestIdKey, rhs: TestIdKey) -> Bool { - if lhs.id != rhs.id { return false } - + return true } } -extension TestIdKey : Hashable { +extension TestIdKey: Hashable { public func hash(into hasher: inout Hasher) { - - hasher.combine(self.id) - + hasher.combine(id) } } -extension TestIdKey : Sendable {} - - +extension TestIdKey: Sendable {} diff --git a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkOperations.swift b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkOperations.swift index 3d8699e..1743244 100644 --- a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkOperations.swift +++ b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkOperations.swift @@ -3,44 +3,16 @@ import Foundation import FirebaseCore import FirebaseDataConnect - - - - - - - - - - - - - - - - - - - // MARK: Common Enums public enum OrderDirection: String, Codable, Sendable { - case ASC = "ASC" - case DESC = "DESC" - } + case ASC + case DESC +} // End enum definitions - - - - - - - - -public class CreateTestIdMutation{ - +public class CreateTestIdMutation { let dataConnect: DataConnect init(dataConnect: DataConnect) { @@ -49,105 +21,68 @@ public class CreateTestIdMutation{ public static let OperationName = "createTestId" - public typealias Ref = MutationRef + public typealias Ref = MutationRef public struct Variables: OperationVariable { - - - public var -id: UUID - - - - - - public init ( - -id: UUID + public var + id: UUID - - ) { - self.id = id - - - + public init(id: UUID) { + self.id = id } public static func == (lhs: Variables, rhs: Variables) -> Bool { - - return lhs.id == rhs.id - + return lhs.id == rhs.id } - -public func hash(into hasher: inout Hasher) { - - hasher.combine(id) - -} + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + } enum CodingKeys: String, CodingKey { - case id - } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - + try codecHelper.encode(id, forKey: .id, container: &container) - - } - } public struct Data: Decodable, Sendable { - - - -public var -testId_insert: TestIdKey - + public var + testId_insert: TestIdKey } - public func ref( - -id: UUID - - ) -> MutationRef { - var variables = CreateTestIdMutation.Variables(id:id) - + public func ref(id: UUID) + -> MutationRef { + var variables = CreateTestIdMutation.Variables(id: id) - let ref = dataConnect.mutation(name: "createTestId", variables: variables, resultsDataType:CreateTestIdMutation.Data.self) - return ref as MutationRef - } + let ref = dataConnect.mutation( + name: "createTestId", + variables: variables, + resultsDataType: CreateTestIdMutation.Data.self + ) + return ref as MutationRef + } @MainActor - public func execute( - -id: UUID - - ) async throws -> OperationResult { - var variables = CreateTestIdMutation.Variables(id:id) - - - let ref = dataConnect.mutation(name: "createTestId", variables: variables, resultsDataType:CreateTestIdMutation.Data.self) - - return try await ref.execute() - - } -} - - - - + public func execute(id: UUID) async throws -> OperationResult { + var variables = CreateTestIdMutation.Variables(id: id) + let ref = dataConnect.mutation( + name: "createTestId", + variables: variables, + resultsDataType: CreateTestIdMutation.Data.self + ) -public class CreateTestAutoIdMutation{ + return try await ref.execute() + } +} +public class CreateTestAutoIdMutation { let dataConnect: DataConnect init(dataConnect: DataConnect) { @@ -156,54 +91,46 @@ public class CreateTestAutoIdMutation{ public static let OperationName = "createTestAutoId" - public typealias Ref = MutationRef + public typealias Ref = MutationRef< + CreateTestAutoIdMutation.Data, + CreateTestAutoIdMutation.Variables + > - public struct Variables: OperationVariable { - - - - } + public struct Variables: OperationVariable {} public struct Data: Decodable, Sendable { - - - -public var -testAutoId_insert: TestAutoIdKey - + public var + testAutoId_insert: TestAutoIdKey } public func ref( - - ) -> MutationRef { - var variables = CreateTestAutoIdMutation.Variables() - + ) -> MutationRef { + var variables = CreateTestAutoIdMutation.Variables() - let ref = dataConnect.mutation(name: "createTestAutoId", variables: variables, resultsDataType:CreateTestAutoIdMutation.Data.self) - return ref as MutationRef - } + let ref = dataConnect.mutation( + name: "createTestAutoId", + variables: variables, + resultsDataType: CreateTestAutoIdMutation.Data.self + ) + return ref as MutationRef + } @MainActor - public func execute( - - ) async throws -> OperationResult { - var variables = CreateTestAutoIdMutation.Variables() - - - let ref = dataConnect.mutation(name: "createTestAutoId", variables: variables, resultsDataType:CreateTestAutoIdMutation.Data.self) - - return try await ref.execute() - - } -} - - - - - + public func execute( + ) async throws -> OperationResult { + var variables = CreateTestAutoIdMutation.Variables() + + let ref = dataConnect.mutation( + name: "createTestAutoId", + variables: variables, + resultsDataType: CreateTestAutoIdMutation.Data.self + ) -public class CreateStandardScalarMutation{ + return try await ref.execute() + } +} +public class CreateStandardScalarMutation { let dataConnect: DataConnect init(dataConnect: DataConnect) { @@ -212,171 +139,137 @@ public class CreateStandardScalarMutation{ public static let OperationName = "createStandardScalar" - public typealias Ref = MutationRef + public typealias Ref = MutationRef< + CreateStandardScalarMutation.Data, + CreateStandardScalarMutation.Variables + > public struct Variables: OperationVariable { - - - public var -id: UUID - - - - public var -number: Int - - - - public var -text: String - - - - public var -decimal: Double - - - - - - public init ( - -id: UUID -, - -number: Int -, - -text: String -, - -decimal: Double - - - ) { - self.id = id - self.number = number - self.text = text - self.decimal = decimal - - - + public var + id: UUID + + public var + number: Int + + public var + text: String + + public var + decimal: Double + + public init(id: UUID, + + number: Int, + + text: String, + + decimal: Double) { + self.id = id + self.number = number + self.text = text + self.decimal = decimal } public static func == (lhs: Variables, rhs: Variables) -> Bool { - - return lhs.id == rhs.id && - lhs.number == rhs.number && - lhs.text == rhs.text && - lhs.decimal == rhs.decimal - - } - - -public func hash(into hasher: inout Hasher) { - - hasher.combine(id) - - hasher.combine(number) - - hasher.combine(text) - - hasher.combine(decimal) - -} + return lhs.id == rhs.id && + lhs.number == rhs.number && + lhs.text == rhs.text && + lhs.decimal == rhs.decimal + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + + hasher.combine(number) + + hasher.combine(text) + + hasher.combine(decimal) + } enum CodingKeys: String, CodingKey { - case id - + case number - + case text - + case decimal - } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - + try codecHelper.encode(id, forKey: .id, container: &container) - - - + try codecHelper.encode(number, forKey: .number, container: &container) - - - + try codecHelper.encode(text, forKey: .text, container: &container) - - - + try codecHelper.encode(decimal, forKey: .decimal, container: &container) - - } - } public struct Data: Decodable, Sendable { + public var + standardScalars_insert: StandardScalarsKey + } + public func ref(id: UUID, + number: Int, -public var -standardScalars_insert: StandardScalarsKey + text: String, - } + decimal: Double) + -> MutationRef { + var variables = CreateStandardScalarMutation.Variables( + id: id, + number: number, + text: text, + decimal: decimal + ) - public func ref( - -id: UUID -, -number: Int -, -text: String -, -decimal: Double - - ) -> MutationRef { - var variables = CreateStandardScalarMutation.Variables(id:id,number:number,text:text,decimal:decimal) - - - let ref = dataConnect.mutation(name: "createStandardScalar", variables: variables, resultsDataType:CreateStandardScalarMutation.Data.self) - return ref as MutationRef - } + let ref = dataConnect.mutation( + name: "createStandardScalar", + variables: variables, + resultsDataType: CreateStandardScalarMutation.Data.self + ) + return ref as MutationRef< + CreateStandardScalarMutation.Data, + CreateStandardScalarMutation.Variables + > + } @MainActor - public func execute( - -id: UUID -, -number: Int -, -text: String -, -decimal: Double - - ) async throws -> OperationResult { - var variables = CreateStandardScalarMutation.Variables(id:id,number:number,text:text,decimal:decimal) - - - let ref = dataConnect.mutation(name: "createStandardScalar", variables: variables, resultsDataType:CreateStandardScalarMutation.Data.self) - - return try await ref.execute() - - } -} - + public func execute(id: UUID, + number: Int, + text: String, + decimal: Double) async throws + -> OperationResult { + var variables = CreateStandardScalarMutation.Variables( + id: id, + number: number, + text: text, + decimal: decimal + ) + let ref = dataConnect.mutation( + name: "createStandardScalar", + variables: variables, + resultsDataType: CreateStandardScalarMutation.Data.self + ) -public class CreateScalarBoundaryMutation{ + return try await ref.execute() + } +} +public class CreateScalarBoundaryMutation { let dataConnect: DataConnect init(dataConnect: DataConnect) { @@ -385,193 +278,156 @@ public class CreateScalarBoundaryMutation{ public static let OperationName = "createScalarBoundary" - public typealias Ref = MutationRef + public typealias Ref = MutationRef< + CreateScalarBoundaryMutation.Data, + CreateScalarBoundaryMutation.Variables + > public struct Variables: OperationVariable { - - - public var -id: UUID - - - - public var -maxNumber: Int - - - - public var -minNumber: Int - - - - public var -maxDecimal: Double - - - - public var -minDecimal: Double - - - - - - public init ( - -id: UUID -, - -maxNumber: Int -, - -minNumber: Int -, - -maxDecimal: Double -, - -minDecimal: Double - - - ) { - self.id = id - self.maxNumber = maxNumber - self.minNumber = minNumber - self.maxDecimal = maxDecimal - self.minDecimal = minDecimal - - - + public var + id: UUID + + public var + maxNumber: Int + + public var + minNumber: Int + + public var + maxDecimal: Double + + public var + minDecimal: Double + + public init(id: UUID, + + maxNumber: Int, + + minNumber: Int, + + maxDecimal: Double, + + minDecimal: Double) { + self.id = id + self.maxNumber = maxNumber + self.minNumber = minNumber + self.maxDecimal = maxDecimal + self.minDecimal = minDecimal } public static func == (lhs: Variables, rhs: Variables) -> Bool { - - return lhs.id == rhs.id && - lhs.maxNumber == rhs.maxNumber && - lhs.minNumber == rhs.minNumber && - lhs.maxDecimal == rhs.maxDecimal && - lhs.minDecimal == rhs.minDecimal - - } - - -public func hash(into hasher: inout Hasher) { - - hasher.combine(id) - - hasher.combine(maxNumber) - - hasher.combine(minNumber) - - hasher.combine(maxDecimal) - - hasher.combine(minDecimal) - -} + return lhs.id == rhs.id && + lhs.maxNumber == rhs.maxNumber && + lhs.minNumber == rhs.minNumber && + lhs.maxDecimal == rhs.maxDecimal && + lhs.minDecimal == rhs.minDecimal + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + + hasher.combine(maxNumber) + + hasher.combine(minNumber) + + hasher.combine(maxDecimal) + + hasher.combine(minDecimal) + } enum CodingKeys: String, CodingKey { - case id - + case maxNumber - + case minNumber - + case maxDecimal - + case minDecimal - } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - + try codecHelper.encode(id, forKey: .id, container: &container) - - - + try codecHelper.encode(maxNumber, forKey: .maxNumber, container: &container) - - - + try codecHelper.encode(minNumber, forKey: .minNumber, container: &container) - - - + try codecHelper.encode(maxDecimal, forKey: .maxDecimal, container: &container) - - - + try codecHelper.encode(minDecimal, forKey: .minDecimal, container: &container) - - } - } public struct Data: Decodable, Sendable { + public var + scalarBoundary_insert: ScalarBoundaryKey + } + public func ref(id: UUID, + maxNumber: Int, -public var -scalarBoundary_insert: ScalarBoundaryKey + minNumber: Int, - } + maxDecimal: Double, - public func ref( - -id: UUID -, -maxNumber: Int -, -minNumber: Int -, -maxDecimal: Double -, -minDecimal: Double - - ) -> MutationRef { - var variables = CreateScalarBoundaryMutation.Variables(id:id,maxNumber:maxNumber,minNumber:minNumber,maxDecimal:maxDecimal,minDecimal:minDecimal) - - - let ref = dataConnect.mutation(name: "createScalarBoundary", variables: variables, resultsDataType:CreateScalarBoundaryMutation.Data.self) - return ref as MutationRef - } + minDecimal: Double) + -> MutationRef { + var variables = CreateScalarBoundaryMutation.Variables( + id: id, + maxNumber: maxNumber, + minNumber: minNumber, + maxDecimal: maxDecimal, + minDecimal: minDecimal + ) + + let ref = dataConnect.mutation( + name: "createScalarBoundary", + variables: variables, + resultsDataType: CreateScalarBoundaryMutation.Data.self + ) + return ref as MutationRef< + CreateScalarBoundaryMutation.Data, + CreateScalarBoundaryMutation.Variables + > + } @MainActor - public func execute( - -id: UUID -, -maxNumber: Int -, -minNumber: Int -, -maxDecimal: Double -, -minDecimal: Double - - ) async throws -> OperationResult { - var variables = CreateScalarBoundaryMutation.Variables(id:id,maxNumber:maxNumber,minNumber:minNumber,maxDecimal:maxDecimal,minDecimal:minDecimal) - - - let ref = dataConnect.mutation(name: "createScalarBoundary", variables: variables, resultsDataType:CreateScalarBoundaryMutation.Data.self) - - return try await ref.execute() - - } -} + public func execute(id: UUID, + maxNumber: Int, + minNumber: Int, + maxDecimal: Double, + minDecimal: Double) async throws + -> OperationResult { + var variables = CreateScalarBoundaryMutation.Variables( + id: id, + maxNumber: maxNumber, + minNumber: minNumber, + maxDecimal: maxDecimal, + minDecimal: minDecimal + ) + let ref = dataConnect.mutation( + name: "createScalarBoundary", + variables: variables, + resultsDataType: CreateScalarBoundaryMutation.Data.self + ) -public class CreateLargeNumMutation{ + return try await ref.execute() + } +} +public class CreateLargeNumMutation { let dataConnect: DataConnect init(dataConnect: DataConnect) { @@ -580,171 +436,129 @@ public class CreateLargeNumMutation{ public static let OperationName = "createLargeNum" - public typealias Ref = MutationRef + public typealias Ref = MutationRef public struct Variables: OperationVariable { - - - public var -id: UUID - - - - public var -num: Int64 - - - - public var -maxNum: Int64 - - - - public var -minNum: Int64 - - - - - - public init ( - -id: UUID -, - -num: Int64 -, - -maxNum: Int64 -, - -minNum: Int64 - - - ) { - self.id = id - self.num = num - self.maxNum = maxNum - self.minNum = minNum - - - + public var + id: UUID + + public var + num: Int64 + + public var + maxNum: Int64 + + public var + minNum: Int64 + + public init(id: UUID, + + num: Int64, + + maxNum: Int64, + + minNum: Int64) { + self.id = id + self.num = num + self.maxNum = maxNum + self.minNum = minNum } public static func == (lhs: Variables, rhs: Variables) -> Bool { - - return lhs.id == rhs.id && - lhs.num == rhs.num && - lhs.maxNum == rhs.maxNum && - lhs.minNum == rhs.minNum - - } - - -public func hash(into hasher: inout Hasher) { - - hasher.combine(id) - - hasher.combine(num) - - hasher.combine(maxNum) - - hasher.combine(minNum) - -} + return lhs.id == rhs.id && + lhs.num == rhs.num && + lhs.maxNum == rhs.maxNum && + lhs.minNum == rhs.minNum + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + + hasher.combine(num) + + hasher.combine(maxNum) + + hasher.combine(minNum) + } enum CodingKeys: String, CodingKey { - case id - + case num - + case maxNum - + case minNum - } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - + try codecHelper.encode(id, forKey: .id, container: &container) - - - + try codecHelper.encode(num, forKey: .num, container: &container) - - - + try codecHelper.encode(maxNum, forKey: .maxNum, container: &container) - - - + try codecHelper.encode(minNum, forKey: .minNum, container: &container) - - } - } public struct Data: Decodable, Sendable { + public var + largeIntType_insert: LargeIntTypeKey + } + public func ref(id: UUID, + num: Int64, -public var -largeIntType_insert: LargeIntTypeKey + maxNum: Int64, - } + minNum: Int64) + -> MutationRef { + var variables = CreateLargeNumMutation.Variables( + id: id, + num: num, + maxNum: maxNum, + minNum: minNum + ) - public func ref( - -id: UUID -, -num: Int64 -, -maxNum: Int64 -, -minNum: Int64 - - ) -> MutationRef { - var variables = CreateLargeNumMutation.Variables(id:id,num:num,maxNum:maxNum,minNum:minNum) - - - let ref = dataConnect.mutation(name: "createLargeNum", variables: variables, resultsDataType:CreateLargeNumMutation.Data.self) - return ref as MutationRef - } + let ref = dataConnect.mutation( + name: "createLargeNum", + variables: variables, + resultsDataType: CreateLargeNumMutation.Data.self + ) + return ref as MutationRef + } @MainActor - public func execute( - -id: UUID -, -num: Int64 -, -maxNum: Int64 -, -minNum: Int64 - - ) async throws -> OperationResult { - var variables = CreateLargeNumMutation.Variables(id:id,num:num,maxNum:maxNum,minNum:minNum) - - - let ref = dataConnect.mutation(name: "createLargeNum", variables: variables, resultsDataType:CreateLargeNumMutation.Data.self) - - return try await ref.execute() - - } -} - + public func execute(id: UUID, + num: Int64, + maxNum: Int64, + minNum: Int64) async throws -> OperationResult { + var variables = CreateLargeNumMutation.Variables( + id: id, + num: num, + maxNum: maxNum, + minNum: minNum + ) + let ref = dataConnect.mutation( + name: "createLargeNum", + variables: variables, + resultsDataType: CreateLargeNumMutation.Data.self + ) -public class CreateLocalDateMutation{ + return try await ref.execute() + } +} +public class CreateLocalDateMutation { let dataConnect: DataConnect init(dataConnect: DataConnect) { @@ -753,127 +567,90 @@ public class CreateLocalDateMutation{ public static let OperationName = "createLocalDate" - public typealias Ref = MutationRef + public typealias Ref = MutationRef< + CreateLocalDateMutation.Data, + CreateLocalDateMutation.Variables + > public struct Variables: OperationVariable { - - - public var -id: UUID - - - - public var -localDate: LocalDate - + public var + id: UUID - - - - public init ( - -id: UUID -, - -localDate: LocalDate + public var + localDate: LocalDate - - ) { - self.id = id - self.localDate = localDate - + public init(id: UUID, - + localDate: LocalDate) { + self.id = id + self.localDate = localDate } public static func == (lhs: Variables, rhs: Variables) -> Bool { - - return lhs.id == rhs.id && - lhs.localDate == rhs.localDate - - } - - -public func hash(into hasher: inout Hasher) { - - hasher.combine(id) - - hasher.combine(localDate) - -} + return lhs.id == rhs.id && + lhs.localDate == rhs.localDate + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + + hasher.combine(localDate) + } enum CodingKeys: String, CodingKey { - case id - + case localDate - } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - + try codecHelper.encode(id, forKey: .id, container: &container) - - - + try codecHelper.encode(localDate, forKey: .localDate, container: &container) - - } - } public struct Data: Decodable, Sendable { - - - -public var -localDateType_insert: LocalDateTypeKey - + public var + localDateType_insert: LocalDateTypeKey } - public func ref( - -id: UUID -, -localDate: LocalDate + public func ref(id: UUID, - ) -> MutationRef { - var variables = CreateLocalDateMutation.Variables(id:id,localDate:localDate) - + localDate: LocalDate) + -> MutationRef { + var variables = CreateLocalDateMutation.Variables(id: id, localDate: localDate) - let ref = dataConnect.mutation(name: "createLocalDate", variables: variables, resultsDataType:CreateLocalDateMutation.Data.self) - return ref as MutationRef - } + let ref = dataConnect.mutation( + name: "createLocalDate", + variables: variables, + resultsDataType: CreateLocalDateMutation.Data.self + ) + return ref as MutationRef + } @MainActor - public func execute( - -id: UUID -, -localDate: LocalDate - - ) async throws -> OperationResult { - var variables = CreateLocalDateMutation.Variables(id:id,localDate:localDate) - - - let ref = dataConnect.mutation(name: "createLocalDate", variables: variables, resultsDataType:CreateLocalDateMutation.Data.self) - - return try await ref.execute() - - } -} - - - + public func execute(id: UUID, + localDate: LocalDate) async throws + -> OperationResult { + var variables = CreateLocalDateMutation.Variables(id: id, localDate: localDate) + let ref = dataConnect.mutation( + name: "createLocalDate", + variables: variables, + resultsDataType: CreateLocalDateMutation.Data.self + ) -public class CreateAnyValueTypeMutation{ + return try await ref.execute() + } +} +public class CreateAnyValueTypeMutation { let dataConnect: DataConnect init(dataConnect: DataConnect) { @@ -882,127 +659,94 @@ public class CreateAnyValueTypeMutation{ public static let OperationName = "createAnyValueType" - public typealias Ref = MutationRef + public typealias Ref = MutationRef< + CreateAnyValueTypeMutation.Data, + CreateAnyValueTypeMutation.Variables + > public struct Variables: OperationVariable { - - - public var -id: UUID - - - - public var -props: AnyValue - + public var + id: UUID - - - - public init ( - -id: UUID -, - -props: AnyValue + public var + props: AnyValue - - ) { - self.id = id - self.props = props - + public init(id: UUID, - + props: AnyValue) { + self.id = id + self.props = props } public static func == (lhs: Variables, rhs: Variables) -> Bool { - - return lhs.id == rhs.id && - lhs.props == rhs.props - - } - - -public func hash(into hasher: inout Hasher) { - - hasher.combine(id) - - hasher.combine(props) - -} + return lhs.id == rhs.id && + lhs.props == rhs.props + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + + hasher.combine(props) + } enum CodingKeys: String, CodingKey { - case id - + case props - } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - + try codecHelper.encode(id, forKey: .id, container: &container) - - - + try codecHelper.encode(props, forKey: .props, container: &container) - - } - } public struct Data: Decodable, Sendable { - - - -public var -anyValueType_insert: AnyValueTypeKey - + public var + anyValueType_insert: AnyValueTypeKey } - public func ref( - -id: UUID -, -props: AnyValue + public func ref(id: UUID, - ) -> MutationRef { - var variables = CreateAnyValueTypeMutation.Variables(id:id,props:props) - + props: AnyValue) -> MutationRef< + CreateAnyValueTypeMutation.Data, + CreateAnyValueTypeMutation.Variables + > { + var variables = CreateAnyValueTypeMutation.Variables(id: id, props: props) - let ref = dataConnect.mutation(name: "createAnyValueType", variables: variables, resultsDataType:CreateAnyValueTypeMutation.Data.self) - return ref as MutationRef - } + let ref = dataConnect.mutation( + name: "createAnyValueType", + variables: variables, + resultsDataType: CreateAnyValueTypeMutation.Data.self + ) + return ref as MutationRef< + CreateAnyValueTypeMutation.Data, + CreateAnyValueTypeMutation.Variables + > + } @MainActor - public func execute( - -id: UUID -, -props: AnyValue - - ) async throws -> OperationResult { - var variables = CreateAnyValueTypeMutation.Variables(id:id,props:props) - - - let ref = dataConnect.mutation(name: "createAnyValueType", variables: variables, resultsDataType:CreateAnyValueTypeMutation.Data.self) - - return try await ref.execute() - - } -} - - - + public func execute(id: UUID, + props: AnyValue) async throws + -> OperationResult { + var variables = CreateAnyValueTypeMutation.Variables(id: id, props: props) + let ref = dataConnect.mutation( + name: "createAnyValueType", + variables: variables, + resultsDataType: CreateAnyValueTypeMutation.Data.self + ) -public class InsertMultiplePeopleMutation{ + return try await ref.execute() + } +} +public class InsertMultiplePeopleMutation { let dataConnect: DataConnect init(dataConnect: DataConnect) { @@ -1011,155 +755,113 @@ public class InsertMultiplePeopleMutation{ public static let OperationName = "InsertMultiplePeople" - public typealias Ref = MutationRef + public typealias Ref = MutationRef< + InsertMultiplePeopleMutation.Data, + InsertMultiplePeopleMutation.Variables + > public struct Variables: OperationVariable { - - - public var -id: UUID - - - - public var -name1: String - - - - public var -name2: String - - - - - - public init ( - -id: UUID -, - -name1: String -, - -name2: String - - - ) { - self.id = id - self.name1 = name1 - self.name2 = name2 - - - + public var + id: UUID + + public var + name1: String + + public var + name2: String + + public init(id: UUID, + + name1: String, + + name2: String) { + self.id = id + self.name1 = name1 + self.name2 = name2 } public static func == (lhs: Variables, rhs: Variables) -> Bool { - - return lhs.id == rhs.id && - lhs.name1 == rhs.name1 && - lhs.name2 == rhs.name2 - - } - - -public func hash(into hasher: inout Hasher) { - - hasher.combine(id) - - hasher.combine(name1) - - hasher.combine(name2) - -} + return lhs.id == rhs.id && + lhs.name1 == rhs.name1 && + lhs.name2 == rhs.name2 + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + + hasher.combine(name1) + + hasher.combine(name2) + } enum CodingKeys: String, CodingKey { - case id - + case name1 - + case name2 - } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - + try codecHelper.encode(id, forKey: .id, container: &container) - - - + try codecHelper.encode(name1, forKey: .name1, container: &container) - - - + try codecHelper.encode(name2, forKey: .name2, container: &container) - - } - } public struct Data: Decodable, Sendable { + public var + person1: PersonKey + public var + person2: PersonKey + } + public func ref(id: UUID, -public var -person1: PersonKey - - - + name1: String, -public var -person2: PersonKey + name2: String) + -> MutationRef { + var variables = InsertMultiplePeopleMutation.Variables(id: id, name1: name1, name2: name2) + let ref = dataConnect.mutation( + name: "InsertMultiplePeople", + variables: variables, + resultsDataType: InsertMultiplePeopleMutation.Data.self + ) + return ref as MutationRef< + InsertMultiplePeopleMutation.Data, + InsertMultiplePeopleMutation.Variables + > } - public func ref( - -id: UUID -, -name1: String -, -name2: String - - ) -> MutationRef { - var variables = InsertMultiplePeopleMutation.Variables(id:id,name1:name1,name2:name2) - - - let ref = dataConnect.mutation(name: "InsertMultiplePeople", variables: variables, resultsDataType:InsertMultiplePeopleMutation.Data.self) - return ref as MutationRef - } - @MainActor - public func execute( - -id: UUID -, -name1: String -, -name2: String - - ) async throws -> OperationResult { - var variables = InsertMultiplePeopleMutation.Variables(id:id,name1:name1,name2:name2) - - - let ref = dataConnect.mutation(name: "InsertMultiplePeople", variables: variables, resultsDataType:InsertMultiplePeopleMutation.Data.self) - - return try await ref.execute() - - } -} - - + public func execute(id: UUID, + name1: String, + name2: String) async throws + -> OperationResult { + var variables = InsertMultiplePeopleMutation.Variables(id: id, name1: name1, name2: name2) + let ref = dataConnect.mutation( + name: "InsertMultiplePeople", + variables: variables, + resultsDataType: InsertMultiplePeopleMutation.Data.self + ) -public class DeleteNonExistentPeopleMutation{ + return try await ref.execute() + } +} +public class DeleteNonExistentPeopleMutation { let dataConnect: DataConnect init(dataConnect: DataConnect) { @@ -1168,111 +870,79 @@ public class DeleteNonExistentPeopleMutation{ public static let OperationName = "DeleteNonExistentPeople" - public typealias Ref = MutationRef + public typealias Ref = MutationRef< + DeleteNonExistentPeopleMutation.Data, + DeleteNonExistentPeopleMutation.Variables + > public struct Variables: OperationVariable { - - - public var -id: UUID - - - - - - public init ( - -id: UUID - - - ) { - self.id = id - + public var + id: UUID - + public init(id: UUID) { + self.id = id } public static func == (lhs: Variables, rhs: Variables) -> Bool { - - return lhs.id == rhs.id - + return lhs.id == rhs.id } - -public func hash(into hasher: inout Hasher) { - - hasher.combine(id) - -} + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + } enum CodingKeys: String, CodingKey { - case id - } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - + try codecHelper.encode(id, forKey: .id, container: &container) - - } - } public struct Data: Decodable, Sendable { + public var + person1: PersonKey? - - -public var -person1: PersonKey? - - - - -public var -person2: PersonKey? - + public var + person2: PersonKey? } - public func ref( - -id: UUID - - ) -> MutationRef { - var variables = DeleteNonExistentPeopleMutation.Variables(id:id) - + public func ref(id: UUID) + -> MutationRef { + var variables = DeleteNonExistentPeopleMutation.Variables(id: id) - let ref = dataConnect.mutation(name: "DeleteNonExistentPeople", variables: variables, resultsDataType:DeleteNonExistentPeopleMutation.Data.self) - return ref as MutationRef - } + let ref = dataConnect.mutation( + name: "DeleteNonExistentPeople", + variables: variables, + resultsDataType: DeleteNonExistentPeopleMutation.Data.self + ) + return ref as MutationRef< + DeleteNonExistentPeopleMutation.Data, + DeleteNonExistentPeopleMutation.Variables + > + } @MainActor - public func execute( - -id: UUID - - ) async throws -> OperationResult { - var variables = DeleteNonExistentPeopleMutation.Variables(id:id) - - - let ref = dataConnect.mutation(name: "DeleteNonExistentPeople", variables: variables, resultsDataType:DeleteNonExistentPeopleMutation.Data.self) - - return try await ref.execute() - - } -} - - - - - + public func execute(id: UUID) async throws + -> OperationResult { + var variables = DeleteNonExistentPeopleMutation.Variables(id: id) + + let ref = dataConnect.mutation( + name: "DeleteNonExistentPeople", + variables: variables, + resultsDataType: DeleteNonExistentPeopleMutation.Data.self + ) -public class GetStandardScalarQuery{ + return try await ref.execute() + } +} +public class GetStandardScalarQuery { let dataConnect: DataConnect init(dataConnect: DataConnect) { @@ -1281,188 +951,132 @@ public class GetStandardScalarQuery{ public static let OperationName = "GetStandardScalar" - public typealias Ref = QueryRefObservableObject + public typealias Ref = QueryRefObservableObject< + GetStandardScalarQuery.Data, + GetStandardScalarQuery.Variables + > public struct Variables: OperationVariable { - - - public var -id: UUID - - - - - - public init ( - -id: UUID - - - ) { - self.id = id - + public var + id: UUID - + public init(id: UUID) { + self.id = id } public static func == (lhs: Variables, rhs: Variables) -> Bool { - - return lhs.id == rhs.id - + return lhs.id == rhs.id } - -public func hash(into hasher: inout Hasher) { - - hasher.combine(id) - -} + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + } enum CodingKeys: String, CodingKey { - case id - } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - + try codecHelper.encode(id, forKey: .id, container: &container) - - } - } public struct Data: Decodable, Sendable { + public struct StandardScalars: Decodable, Sendable, Hashable, Equatable, Identifiable { + public var + id: UUID + public var + number: Int + public var + text: String + public var + decimal: Double -public struct StandardScalars: Decodable, Sendable ,Hashable, Equatable, Identifiable { - - + public var standardScalarsKey: StandardScalarsKey { + return StandardScalarsKey( + id: id + ) + } -public var -id: UUID + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + } + public static func == (lhs: StandardScalars, rhs: StandardScalars) -> Bool { + return lhs.id == rhs.id + } + enum CodingKeys: String, CodingKey { + case id -public var -number: Int + case number + case text + case decimal + } -public var -text: String + public init(from decoder: any Decoder) throws { + var container = try decoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) + number = try codecHelper.decode(Int.self, forKey: .number, container: &container) -public var -decimal: Double + text = try codecHelper.decode(String.self, forKey: .text, container: &container) + decimal = try codecHelper.decode(Double.self, forKey: .decimal, container: &container) + } + } - - public var standardScalarsKey: StandardScalarsKey { - return StandardScalarsKey( - - id: id - ) + public var + standardScalars: StandardScalars? } - -public func hash(into hasher: inout Hasher) { - - hasher.combine(id) - -} -public static func == (lhs: StandardScalars, rhs: StandardScalars) -> Bool { - - return lhs.id == rhs.id - - } - - - - - enum CodingKeys: String, CodingKey { - - case id - - case number - - case text - - case decimal - - } - - public init(from decoder: any Decoder) throws { - var container = try decoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - - - self.id = try codecHelper.decode(UUID.self, forKey: .id, container: &container) - - - - self.number = try codecHelper.decode(Int.self, forKey: .number, container: &container) - - - - self.text = try codecHelper.decode(String.self, forKey: .text, container: &container) - - - - self.decimal = try codecHelper.decode(Double.self, forKey: .decimal, container: &container) - - - } -} -public var -standardScalars: StandardScalars? + public func ref(id: UUID) + -> QueryRefObservableObject { + var variables = GetStandardScalarQuery.Variables(id: id) + let ref = dataConnect.query( + name: "GetStandardScalar", + variables: variables, + resultsDataType: GetStandardScalarQuery.Data.self, + publisher: .observableObject + ) + return ref as! QueryRefObservableObject< + GetStandardScalarQuery.Data, + GetStandardScalarQuery.Variables + > } - public func ref( - -id: UUID - - ) -> QueryRefObservableObject { - var variables = GetStandardScalarQuery.Variables(id:id) - - - let ref = dataConnect.query(name: "GetStandardScalar", variables: variables, resultsDataType:GetStandardScalarQuery.Data.self, publisher: .observableObject) - return ref as! QueryRefObservableObject - } - @MainActor - public func execute( - -id: UUID - - ) async throws -> OperationResult { - var variables = GetStandardScalarQuery.Variables(id:id) - - - let ref = dataConnect.query(name: "GetStandardScalar", variables: variables, resultsDataType:GetStandardScalarQuery.Data.self, publisher: .observableObject) - - let refCast = ref as! QueryRefObservableObject - return try await refCast.execute() - - } -} - - - - - + public func execute(id: UUID) async throws -> OperationResult { + var variables = GetStandardScalarQuery.Variables(id: id) + + let ref = dataConnect.query( + name: "GetStandardScalar", + variables: variables, + resultsDataType: GetStandardScalarQuery.Data.self, + publisher: .observableObject + ) -public class GetScalarBoundaryQuery{ + let refCast = ref as! QueryRefObservableObject< + GetStandardScalarQuery.Data, + GetStandardScalarQuery.Variables + > + return try await refCast.execute() + } +} +public class GetScalarBoundaryQuery { let dataConnect: DataConnect init(dataConnect: DataConnect) { @@ -1471,168 +1085,118 @@ public class GetScalarBoundaryQuery{ public static let OperationName = "GetScalarBoundary" - public typealias Ref = QueryRefObservableObject + public typealias Ref = QueryRefObservableObject< + GetScalarBoundaryQuery.Data, + GetScalarBoundaryQuery.Variables + > public struct Variables: OperationVariable { - - - public var -id: UUID - - - - - - public init ( - -id: UUID + public var + id: UUID - - ) { - self.id = id - - - + public init(id: UUID) { + self.id = id } public static func == (lhs: Variables, rhs: Variables) -> Bool { - - return lhs.id == rhs.id - + return lhs.id == rhs.id } - -public func hash(into hasher: inout Hasher) { - - hasher.combine(id) - -} + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + } enum CodingKeys: String, CodingKey { - case id - } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - + try codecHelper.encode(id, forKey: .id, container: &container) - - } - } public struct Data: Decodable, Sendable { + public struct ScalarBoundary: Decodable, Sendable { + public var + maxNumber: Int + public var + minNumber: Int + public var + maxDecimal: Double + public var + minDecimal: Double -public struct ScalarBoundary: Decodable, Sendable { - - + enum CodingKeys: String, CodingKey { + case maxNumber -public var -maxNumber: Int + case minNumber + case maxDecimal + case minDecimal + } -public var -minNumber: Int + public init(from decoder: any Decoder) throws { + var container = try decoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + maxNumber = try codecHelper.decode(Int.self, forKey: .maxNumber, container: &container) + minNumber = try codecHelper.decode(Int.self, forKey: .minNumber, container: &container) -public var -maxDecimal: Double + maxDecimal = try codecHelper.decode(Double.self, forKey: .maxDecimal, container: &container) + minDecimal = try codecHelper.decode(Double.self, forKey: .minDecimal, container: &container) + } + } - -public var -minDecimal: Double - - - - - - enum CodingKeys: String, CodingKey { - - case maxNumber - - case minNumber - - case maxDecimal - - case minDecimal - + public var + scalarBoundary: ScalarBoundary? } - public init(from decoder: any Decoder) throws { - var container = try decoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - - - self.maxNumber = try codecHelper.decode(Int.self, forKey: .maxNumber, container: &container) - - - - self.minNumber = try codecHelper.decode(Int.self, forKey: .minNumber, container: &container) - - - - self.maxDecimal = try codecHelper.decode(Double.self, forKey: .maxDecimal, container: &container) - - - - self.minDecimal = try codecHelper.decode(Double.self, forKey: .minDecimal, container: &container) - - - } -} -public var -scalarBoundary: ScalarBoundary? + public func ref(id: UUID) + -> QueryRefObservableObject { + var variables = GetScalarBoundaryQuery.Variables(id: id) + let ref = dataConnect.query( + name: "GetScalarBoundary", + variables: variables, + resultsDataType: GetScalarBoundaryQuery.Data.self, + publisher: .observableObject + ) + return ref as! QueryRefObservableObject< + GetScalarBoundaryQuery.Data, + GetScalarBoundaryQuery.Variables + > } - public func ref( - -id: UUID - - ) -> QueryRefObservableObject { - var variables = GetScalarBoundaryQuery.Variables(id:id) - - - let ref = dataConnect.query(name: "GetScalarBoundary", variables: variables, resultsDataType:GetScalarBoundaryQuery.Data.self, publisher: .observableObject) - return ref as! QueryRefObservableObject - } - @MainActor - public func execute( - -id: UUID - - ) async throws -> OperationResult { - var variables = GetScalarBoundaryQuery.Variables(id:id) - - - let ref = dataConnect.query(name: "GetScalarBoundary", variables: variables, resultsDataType:GetScalarBoundaryQuery.Data.self, publisher: .observableObject) - - let refCast = ref as! QueryRefObservableObject - return try await refCast.execute() - - } -} - - - - - + public func execute(id: UUID) async throws -> OperationResult { + var variables = GetScalarBoundaryQuery.Variables(id: id) + + let ref = dataConnect.query( + name: "GetScalarBoundary", + variables: variables, + resultsDataType: GetScalarBoundaryQuery.Data.self, + publisher: .observableObject + ) -public class GetLargeNumQuery{ + let refCast = ref as! QueryRefObservableObject< + GetScalarBoundaryQuery.Data, + GetScalarBoundaryQuery.Variables + > + return try await refCast.execute() + } +} +public class GetLargeNumQuery { let dataConnect: DataConnect init(dataConnect: DataConnect) { @@ -1641,157 +1205,106 @@ public class GetLargeNumQuery{ public static let OperationName = "GetLargeNum" - public typealias Ref = QueryRefObservableObject + public typealias Ref = QueryRefObservableObject public struct Variables: OperationVariable { - - - public var -id: UUID - - - - - - public init ( - -id: UUID + public var + id: UUID - - ) { - self.id = id - - - + public init(id: UUID) { + self.id = id } public static func == (lhs: Variables, rhs: Variables) -> Bool { - - return lhs.id == rhs.id - + return lhs.id == rhs.id } - -public func hash(into hasher: inout Hasher) { - - hasher.combine(id) - -} + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + } enum CodingKeys: String, CodingKey { - case id - } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - + try codecHelper.encode(id, forKey: .id, container: &container) - - } - } public struct Data: Decodable, Sendable { + public struct LargeIntType: Decodable, Sendable { + public var + num: Int64 + public var + maxNum: Int64 + public var + minNum: Int64 + enum CodingKeys: String, CodingKey { + case num -public struct LargeIntType: Decodable, Sendable { - - - -public var -num: Int64 - - + case maxNum -public var -maxNum: Int64 + case minNum + } + public init(from decoder: any Decoder) throws { + var container = try decoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + num = try codecHelper.decode(Int64.self, forKey: .num, container: &container) -public var -minNum: Int64 + maxNum = try codecHelper.decode(Int64.self, forKey: .maxNum, container: &container) + minNum = try codecHelper.decode(Int64.self, forKey: .minNum, container: &container) + } + } - - - - enum CodingKeys: String, CodingKey { - - case num - - case maxNum - - case minNum - - } - - public init(from decoder: any Decoder) throws { - var container = try decoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - - - self.num = try codecHelper.decode(Int64.self, forKey: .num, container: &container) - - - - self.maxNum = try codecHelper.decode(Int64.self, forKey: .maxNum, container: &container) - - - - self.minNum = try codecHelper.decode(Int64.self, forKey: .minNum, container: &container) - - + public var + largeIntType: LargeIntType? } -} -public var -largeIntType: LargeIntType? + public func ref(id: UUID) -> QueryRefObservableObject< + GetLargeNumQuery.Data, + GetLargeNumQuery.Variables + > { + var variables = GetLargeNumQuery.Variables(id: id) + + let ref = dataConnect.query( + name: "GetLargeNum", + variables: variables, + resultsDataType: GetLargeNumQuery.Data.self, + publisher: .observableObject + ) + return ref as! QueryRefObservableObject } - public func ref( - -id: UUID - - ) -> QueryRefObservableObject { - var variables = GetLargeNumQuery.Variables(id:id) - - - let ref = dataConnect.query(name: "GetLargeNum", variables: variables, resultsDataType:GetLargeNumQuery.Data.self, publisher: .observableObject) - return ref as! QueryRefObservableObject - } - @MainActor - public func execute( - -id: UUID - - ) async throws -> OperationResult { - var variables = GetLargeNumQuery.Variables(id:id) - - - let ref = dataConnect.query(name: "GetLargeNum", variables: variables, resultsDataType:GetLargeNumQuery.Data.self, publisher: .observableObject) - - let refCast = ref as! QueryRefObservableObject - return try await refCast.execute() - - } -} - - - - - + public func execute(id: UUID) async throws -> OperationResult { + var variables = GetLargeNumQuery.Variables(id: id) + + let ref = dataConnect.query( + name: "GetLargeNum", + variables: variables, + resultsDataType: GetLargeNumQuery.Data.self, + publisher: .observableObject + ) -public class GetLocalDateTypeQuery{ + let refCast = ref as! QueryRefObservableObject< + GetLargeNumQuery.Data, + GetLargeNumQuery.Variables + > + return try await refCast.execute() + } +} +public class GetLocalDateTypeQuery { let dataConnect: DataConnect init(dataConnect: DataConnect) { @@ -1800,135 +1313,102 @@ public class GetLocalDateTypeQuery{ public static let OperationName = "GetLocalDateType" - public typealias Ref = QueryRefObservableObject + public typealias Ref = QueryRefObservableObject< + GetLocalDateTypeQuery.Data, + GetLocalDateTypeQuery.Variables + > public struct Variables: OperationVariable { - - - public var -id: UUID - + public var + id: UUID - - - - public init ( - -id: UUID - - - ) { - self.id = id - - - + public init(id: UUID) { + self.id = id } public static func == (lhs: Variables, rhs: Variables) -> Bool { - - return lhs.id == rhs.id - + return lhs.id == rhs.id } - -public func hash(into hasher: inout Hasher) { - - hasher.combine(id) - -} + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + } enum CodingKeys: String, CodingKey { - case id - } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - + try codecHelper.encode(id, forKey: .id, container: &container) - - } - } public struct Data: Decodable, Sendable { + public struct LocalDateType: Decodable, Sendable { + public var + localDate: LocalDate? + + enum CodingKeys: String, CodingKey { + case localDate + } + + public init(from decoder: any Decoder) throws { + var container = try decoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + + localDate = try codecHelper.decode( + LocalDate?.self, + forKey: .localDate, + container: &container + ) + } + } - - - -public struct LocalDateType: Decodable, Sendable { - - - -public var -localDate: LocalDate? - - - - - - enum CodingKeys: String, CodingKey { - - case localDate - - } - - public init(from decoder: any Decoder) throws { - var container = try decoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - - - self.localDate = try codecHelper.decode(LocalDate?.self, forKey: .localDate, container: &container) - - + public var + localDateType: LocalDateType? } -} -public var -localDateType: LocalDateType? + public func ref(id: UUID) -> QueryRefObservableObject< + GetLocalDateTypeQuery.Data, + GetLocalDateTypeQuery.Variables + > { + var variables = GetLocalDateTypeQuery.Variables(id: id) + + let ref = dataConnect.query( + name: "GetLocalDateType", + variables: variables, + resultsDataType: GetLocalDateTypeQuery.Data.self, + publisher: .observableObject + ) + return ref as! QueryRefObservableObject< + GetLocalDateTypeQuery.Data, + GetLocalDateTypeQuery.Variables + > } - public func ref( - -id: UUID - - ) -> QueryRefObservableObject { - var variables = GetLocalDateTypeQuery.Variables(id:id) - - - let ref = dataConnect.query(name: "GetLocalDateType", variables: variables, resultsDataType:GetLocalDateTypeQuery.Data.self, publisher: .observableObject) - return ref as! QueryRefObservableObject - } - @MainActor - public func execute( - -id: UUID - - ) async throws -> OperationResult { - var variables = GetLocalDateTypeQuery.Variables(id:id) - - - let ref = dataConnect.query(name: "GetLocalDateType", variables: variables, resultsDataType:GetLocalDateTypeQuery.Data.self, publisher: .observableObject) - - let refCast = ref as! QueryRefObservableObject - return try await refCast.execute() - - } -} - - - - - + public func execute(id: UUID) async throws -> OperationResult { + var variables = GetLocalDateTypeQuery.Variables(id: id) + + let ref = dataConnect.query( + name: "GetLocalDateType", + variables: variables, + resultsDataType: GetLocalDateTypeQuery.Data.self, + publisher: .observableObject + ) -public class GetAnyValueTypeQuery{ + let refCast = ref as! QueryRefObservableObject< + GetLocalDateTypeQuery.Data, + GetLocalDateTypeQuery.Variables + > + return try await refCast.execute() + } +} +public class GetAnyValueTypeQuery { let dataConnect: DataConnect init(dataConnect: DataConnect) { @@ -1937,126 +1417,93 @@ public class GetAnyValueTypeQuery{ public static let OperationName = "GetAnyValueType" - public typealias Ref = QueryRefObservableObject + public typealias Ref = QueryRefObservableObject< + GetAnyValueTypeQuery.Data, + GetAnyValueTypeQuery.Variables + > public struct Variables: OperationVariable { - - - public var -id: UUID - + public var + id: UUID - - - - public init ( - -id: UUID - - - ) { - self.id = id - - - + public init(id: UUID) { + self.id = id } public static func == (lhs: Variables, rhs: Variables) -> Bool { - - return lhs.id == rhs.id - + return lhs.id == rhs.id } - -public func hash(into hasher: inout Hasher) { - - hasher.combine(id) - -} + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + } enum CodingKeys: String, CodingKey { - case id - } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) let codecHelper = CodecHelper() - - + try codecHelper.encode(id, forKey: .id, container: &container) - - } - } public struct Data: Decodable, Sendable { + public struct AnyValueType: Decodable, Sendable { + public var + props: AnyValue + enum CodingKeys: String, CodingKey { + case props + } + public init(from decoder: any Decoder) throws { + var container = try decoder.container(keyedBy: CodingKeys.self) + let codecHelper = CodecHelper() + props = try codecHelper.decode(AnyValue.self, forKey: .props, container: &container) + } + } -public struct AnyValueType: Decodable, Sendable { - - - -public var -props: AnyValue - - - - - - enum CodingKeys: String, CodingKey { - - case props - - } - - public init(from decoder: any Decoder) throws { - var container = try decoder.container(keyedBy: CodingKeys.self) - let codecHelper = CodecHelper() - - - - self.props = try codecHelper.decode(AnyValue.self, forKey: .props, container: &container) - - + public var + anyValueType: AnyValueType? } -} -public var -anyValueType: AnyValueType? + public func ref(id: UUID) -> QueryRefObservableObject< + GetAnyValueTypeQuery.Data, + GetAnyValueTypeQuery.Variables + > { + var variables = GetAnyValueTypeQuery.Variables(id: id) + + let ref = dataConnect.query( + name: "GetAnyValueType", + variables: variables, + resultsDataType: GetAnyValueTypeQuery.Data.self, + publisher: .observableObject + ) + return ref as! QueryRefObservableObject< + GetAnyValueTypeQuery.Data, + GetAnyValueTypeQuery.Variables + > } - public func ref( - -id: UUID - - ) -> QueryRefObservableObject { - var variables = GetAnyValueTypeQuery.Variables(id:id) - - - let ref = dataConnect.query(name: "GetAnyValueType", variables: variables, resultsDataType:GetAnyValueTypeQuery.Data.self, publisher: .observableObject) - return ref as! QueryRefObservableObject - } - @MainActor - public func execute( - -id: UUID - - ) async throws -> OperationResult { - var variables = GetAnyValueTypeQuery.Variables(id:id) - - - let ref = dataConnect.query(name: "GetAnyValueType", variables: variables, resultsDataType:GetAnyValueTypeQuery.Data.self, publisher: .observableObject) - - let refCast = ref as! QueryRefObservableObject - return try await refCast.execute() - - } -} - + public func execute(id: UUID) async throws -> OperationResult { + var variables = GetAnyValueTypeQuery.Variables(id: id) + + let ref = dataConnect.query( + name: "GetAnyValueType", + variables: variables, + resultsDataType: GetAnyValueTypeQuery.Data.self, + publisher: .observableObject + ) + let refCast = ref as! QueryRefObservableObject< + GetAnyValueTypeQuery.Data, + GetAnyValueTypeQuery.Variables + > + return try await refCast.execute() + } +} diff --git a/Tests/Integration/PartialErrorsTest.swift b/Tests/Integration/PartialErrorsTest.swift index e06feb1..918d0ec 100644 --- a/Tests/Integration/PartialErrorsTest.swift +++ b/Tests/Integration/PartialErrorsTest.swift @@ -19,7 +19,6 @@ import FirebaseCore @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) final class PartialErrorTests: IntegrationTestBase { - override func setUp(completion: @escaping ((any Error)?) -> Void) { Task { do { @@ -36,15 +35,14 @@ final class PartialErrorTests: IntegrationTestBase { // Decode should fail so there isn't any partially encoded data @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) func testDuplicatePrimaryKeys() async throws { - let id = UUID() do { let results = try await DataConnect.kitchenSinkConnector.insertMultiplePeopleMutation.execute( - id: id, name1: "name1", name2: "name2").data + id: id, name1: "name1", name2: "name2" + ).data print("results \(results)") } catch let dcError as DataConnectOperationError { - guard let response = dcError.response else { XCTAssertFalse(false, "No response received from partial error") throw dcError @@ -66,9 +64,8 @@ final class PartialErrorTests: IntegrationTestBase { func testPartiallyDecodedData() async throws { let id = UUID() do { - _ = try await DataConnect.kitchenSinkConnector.deleteNonExistentPeopleMutation.execute(id: id) + _ = try await DataConnect.kitchenSinkConnector.deleteNonExistentPeopleMutation.execute(id: id) } catch let dcError as DataConnectOperationError { - guard let response = dcError.response else { XCTAssertFalse(false, "No response received from partial error") throw dcError @@ -76,7 +73,7 @@ final class PartialErrorTests: IntegrationTestBase { if let data = response.data( asType: DeleteNonExistentPeopleMutation.Data.self - ) { + ) { XCTAssertNil(data.person2) XCTAssertTrue(data.person1?.id == id) } else { @@ -84,5 +81,4 @@ final class PartialErrorTests: IntegrationTestBase { } } } - } From c763b2d71b53b78456b1610b7b969701542310a1 Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Fri, 21 Mar 2025 16:50:50 -0700 Subject: [PATCH 12/28] Remove whitespace from gql file --- .../Resources/fdc-kitchensink/dataconnect/default/mutations.gql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Integration/Resources/fdc-kitchensink/dataconnect/default/mutations.gql b/Tests/Integration/Resources/fdc-kitchensink/dataconnect/default/mutations.gql index 4a9229f..c7ad2d1 100644 --- a/Tests/Integration/Resources/fdc-kitchensink/dataconnect/default/mutations.gql +++ b/Tests/Integration/Resources/fdc-kitchensink/dataconnect/default/mutations.gql @@ -71,7 +71,7 @@ mutation InsertMultiplePeople($id: UUID!, $name1: String!, $name2: String!) @aut person2: person_insert(data: { id: $id, name: $name2 }) @check(expr: "false") } -# ID for second person does not exist. +# ID for second person does not exist. # so first one will succeed but second should fail mutation DeleteNonExistentPeople($id: UUID!) @auth(level: PUBLIC) { person1_insert: person_insert(data: { id: $id, name: "name1" }) From 2a52e5871e1ee86dc0cb531e34b618da774ed748 Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Mon, 24 Mar 2025 07:38:02 -0700 Subject: [PATCH 13/28] Re-add copyright notice to generated code --- .../KitchenSink/Sources/KitchenSinkClient.swift | 13 +++++++++++++ .../Gen/KitchenSink/Sources/KitchenSinkKeys.swift | 14 ++++++++++++++ .../Sources/KitchenSinkOperations.swift | 14 ++++++++++++++ Tests/Integration/PartialErrorsTest.swift | 2 +- .../dataconnect/default/mutations.gql | 2 +- 5 files changed, 43 insertions(+), 2 deletions(-) diff --git a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkClient.swift b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkClient.swift index 113f6d1..75eb013 100644 --- a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkClient.swift +++ b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkClient.swift @@ -1,3 +1,16 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. import Foundation diff --git a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkKeys.swift b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkKeys.swift index 723c113..fa2677d 100644 --- a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkKeys.swift +++ b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkKeys.swift @@ -1,3 +1,17 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + import Foundation import FirebaseDataConnect diff --git a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkOperations.swift b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkOperations.swift index 1743244..bb92f36 100644 --- a/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkOperations.swift +++ b/Tests/Integration/Gen/KitchenSink/Sources/KitchenSinkOperations.swift @@ -1,3 +1,17 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + import Foundation import FirebaseCore diff --git a/Tests/Integration/PartialErrorsTest.swift b/Tests/Integration/PartialErrorsTest.swift index 918d0ec..5dd8011 100644 --- a/Tests/Integration/PartialErrorsTest.swift +++ b/Tests/Integration/PartialErrorsTest.swift @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/Tests/Integration/Resources/fdc-kitchensink/dataconnect/default/mutations.gql b/Tests/Integration/Resources/fdc-kitchensink/dataconnect/default/mutations.gql index c7ad2d1..3cbd5f5 100644 --- a/Tests/Integration/Resources/fdc-kitchensink/dataconnect/default/mutations.gql +++ b/Tests/Integration/Resources/fdc-kitchensink/dataconnect/default/mutations.gql @@ -1,4 +1,4 @@ -# Copyright 2024 Google LLC +# Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. From 255d8ddcea948d009198a55e715efd9521189fb7 Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Mon, 24 Mar 2025 10:20:09 -0700 Subject: [PATCH 14/28] Unnest PathSegment definition --- Sources/DataConnectError.swift | 33 ----------------- Sources/DataConnectPathSegment.swift | 43 +++++++++++++++++++++++ Tests/Integration/PartialErrorsTest.swift | 2 +- 3 files changed, 44 insertions(+), 34 deletions(-) create mode 100644 Sources/DataConnectPathSegment.swift diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index a44aa9f..97cb402 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -248,38 +248,5 @@ public struct OperationFailureResponse: Sendable { public let message: String // The path to the field to which this error applies. public let path: [PathSegment] - - public enum PathSegment: Codable, Equatable, Sendable { - case field(String) - case listIndex(Int) - } - } -} - -// Information about an error provided by the backend in its response. -@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) - -@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -public extension OperationFailureResponse.ErrorInfo.PathSegment { - init(from decoder: any Decoder) throws { - let container = try decoder.singleValueContainer() - - do { - let field = try container.decode(String.self) - self = .field(field) - } catch { - let index = try container.decode(Int.self) - self = .listIndex(index) - } - } - - func encode(to encoder: any Encoder) throws { - var container = encoder.singleValueContainer() - switch self { - case let .field(fieldVal): - try container.encode(fieldVal) - case let .listIndex(indexVal): - try container.encode(indexVal) - } } } diff --git a/Sources/DataConnectPathSegment.swift b/Sources/DataConnectPathSegment.swift new file mode 100644 index 0000000..e536c8f --- /dev/null +++ b/Sources/DataConnectPathSegment.swift @@ -0,0 +1,43 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +public enum PathSegment: Codable, Equatable, Sendable { + case field(String) + case listIndex(Int) +} + +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) +public extension PathSegment { + init(from decoder: any Decoder) throws { + let container = try decoder.singleValueContainer() + + do { + let field = try container.decode(String.self) + self = .field(field) + } catch { + let index = try container.decode(Int.self) + self = .listIndex(index) + } + } + + func encode(to encoder: any Encoder) throws { + var container = encoder.singleValueContainer() + switch self { + case let .field(fieldVal): + try container.encode(fieldVal) + case let .listIndex(indexVal): + try container.encode(indexVal) + } + } +} diff --git a/Tests/Integration/PartialErrorsTest.swift b/Tests/Integration/PartialErrorsTest.swift index 5dd8011..70f7d5c 100644 --- a/Tests/Integration/PartialErrorsTest.swift +++ b/Tests/Integration/PartialErrorsTest.swift @@ -48,7 +48,7 @@ final class PartialErrorTests: IntegrationTestBase { throw dcError } - let foo1Path = [OperationFailureResponse.ErrorInfo.PathSegment.field("person2")] + let foo1Path = [PathSegment.field("person2")] let error = response.errors.first(where: { $0.path == foo1Path }) XCTAssertNotNil(error) From a763f9cec786078324ce2d172eaf95424adb868c Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Mon, 24 Mar 2025 11:28:19 -0700 Subject: [PATCH 15/28] Rename PathSegment to DataConnectPathSegment to match other platforms --- Sources/DataConnectError.swift | 2 +- Sources/DataConnectPathSegment.swift | 4 ++-- Tests/Integration/PartialErrorsTest.swift | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index 97cb402..0478c8f 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -247,6 +247,6 @@ public struct OperationFailureResponse: Sendable { // The error message. public let message: String // The path to the field to which this error applies. - public let path: [PathSegment] + public let path: [DataConnectPathSegment] } } diff --git a/Sources/DataConnectPathSegment.swift b/Sources/DataConnectPathSegment.swift index e536c8f..227cb81 100644 --- a/Sources/DataConnectPathSegment.swift +++ b/Sources/DataConnectPathSegment.swift @@ -12,13 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -public enum PathSegment: Codable, Equatable, Sendable { +public enum DataConnectPathSegment: Codable, Equatable, Sendable { case field(String) case listIndex(Int) } @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -public extension PathSegment { +public extension DataConnectPathSegment { init(from decoder: any Decoder) throws { let container = try decoder.singleValueContainer() diff --git a/Tests/Integration/PartialErrorsTest.swift b/Tests/Integration/PartialErrorsTest.swift index 70f7d5c..1ccc838 100644 --- a/Tests/Integration/PartialErrorsTest.swift +++ b/Tests/Integration/PartialErrorsTest.swift @@ -48,7 +48,7 @@ final class PartialErrorTests: IntegrationTestBase { throw dcError } - let foo1Path = [PathSegment.field("person2")] + let foo1Path = [DataConnectPathSegment.field("person2")] let error = response.errors.first(where: { $0.path == foo1Path }) XCTAssertNotNil(error) From cd2cc5aa4e47f296ec4df848034c41141b5a6ec8 Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Tue, 25 Mar 2025 10:13:30 -0700 Subject: [PATCH 16/28] Cleanup post refactor (removed old `kind` var) --- Sources/DataConnectError.swift | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index 0478c8f..4f4163c 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -183,14 +183,8 @@ public struct DataConnectCodecError: DataConnectDomainError { /// Data Connect Operation Failed public struct DataConnectOperationError: DataConnectError { - public var kind: String { - return "operationError" - } - public var message: String? - public var cause: (any Error)? - public private(set) var response: OperationFailureResponse? = nil private init(message: String? = nil, cause: Error? = nil, response: OperationFailureResponse?) { From 0e717a9828bd9d7d54498ce38e9a3d00c3db8513 Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Tue, 25 Mar 2025 14:49:32 -0700 Subject: [PATCH 17/28] Convert vars to lets --- Sources/DataConnectError.swift | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index 4f4163c..a5de90b 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -95,9 +95,9 @@ public struct DataConnectInitError: DataConnectDomainError { public let code: Code - public private(set) var message: String? + public let message: String? - public private(set) var cause: Error? + public let cause: Error? private init(code: Code, message: String? = nil, cause: Error? = nil) { self.code = code @@ -146,9 +146,9 @@ public struct DataConnectCodecError: DataConnectDomainError { public let code: Code - public var message: String? + public let message: String? - public var cause: (any Error)? + public let cause: (any Error)? private init(code: Code, message: String? = nil, cause: Error? = nil) { self.code = code @@ -183,12 +183,13 @@ public struct DataConnectCodecError: DataConnectDomainError { /// Data Connect Operation Failed public struct DataConnectOperationError: DataConnectError { - public var message: String? - public var cause: (any Error)? - public private(set) var response: OperationFailureResponse? = nil + public let message: String? + public let cause: (any Error)? + public let response: OperationFailureResponse? - private init(message: String? = nil, cause: Error? = nil, response: OperationFailureResponse?) { + private init(message: String? = nil, cause: Error? = nil, response: OperationFailureResponse? = nil) { self.response = response + self.cause = cause self.message = message } @@ -206,12 +207,12 @@ public struct OperationFailureResponse: Sendable { // JSON string whose value is the "data" property provided by the backend in // its response payload; may be `nil` if the "data" property was not provided // in the backend response and/or was `null` in the backend response. - public private(set) var rawJsonData: String? + public let rawJsonData: String? // The list of errors in the "error" property provided by the backend in // its response payload; may be empty if the "errors" property was not // provided in the backend response and/or was an empty list in the backend response. - public private(set) var errors: [ErrorInfo] + public let errors: [ErrorInfo] // (Partially) decoded data private let data: Sendable? From 8ddbe537c05831ba2bcf4114a788f81f450692c5 Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Tue, 25 Mar 2025 16:08:45 -0700 Subject: [PATCH 18/28] Change `cause` to `underlyingError` --- Sources/DataConnectError.swift | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index a5de90b..dad3025 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -20,13 +20,13 @@ import Foundation @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public protocol DataConnectError: Error, CustomDebugStringConvertible, CustomStringConvertible { var message: String? { get } - var cause: Error? { get } + var underlyingError: Error? { get } } @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public extension DataConnectError { var debugDescription: String { - return "{\(Self.self), message: \(message ?? "nil"), cause: \(String(describing: cause))}" + return "{\(Self.self), message: \(message ?? "nil"), cause: \(String(describing: underlyingError))}" } var description: String { @@ -47,8 +47,8 @@ public struct AnyDataConnectError: DataConnectError { return dataConnectError.message } - public var cause: (any Error)? { - return dataConnectError.cause + public var underlyingError: (any Error)? { + return dataConnectError.underlyingError } } @@ -56,14 +56,13 @@ public struct AnyDataConnectError: DataConnectError { /// Represents an error domain which can have more granular error codes public protocol DataConnectDomainError: DataConnectError { associatedtype ErrorCode: DataConnectErrorCode - var code: ErrorCode { get } } @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public extension DataConnectDomainError { var debugDescription: String { - return "{\(Self.self), code: \(code), message: \(message ?? "nil"), cause: \(String(describing: cause))}" + return "{\(Self.self), code: \(code), message: \(message ?? "nil"), cause: \(String(describing: underlyingError))}" } var description: String { @@ -97,11 +96,11 @@ public struct DataConnectInitError: DataConnectDomainError { public let message: String? - public let cause: Error? + public let underlyingError: Error? private init(code: Code, message: String? = nil, cause: Error? = nil) { self.code = code - self.cause = cause + underlyingError = cause self.message = message } @@ -148,12 +147,12 @@ public struct DataConnectCodecError: DataConnectDomainError { public let message: String? - public let cause: (any Error)? + public let underlyingError: (any Error)? private init(code: Code, message: String? = nil, cause: Error? = nil) { self.code = code self.message = message - self.cause = cause + underlyingError = cause } static func encodingFailed(message: String? = nil, cause: Error? = nil) -> DataConnectCodecError { @@ -184,12 +183,13 @@ public struct DataConnectCodecError: DataConnectDomainError { /// Data Connect Operation Failed public struct DataConnectOperationError: DataConnectError { public let message: String? - public let cause: (any Error)? + public let underlyingError: (any Error)? public let response: OperationFailureResponse? - private init(message: String? = nil, cause: Error? = nil, response: OperationFailureResponse? = nil) { + private init(message: String? = nil, cause: Error? = nil, + response: OperationFailureResponse? = nil) { self.response = response - self.cause = cause + underlyingError = cause self.message = message } From 72c1ac1155e736b22a9174e303c5d1407f1bfbbb Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Wed, 26 Mar 2025 07:49:58 -0700 Subject: [PATCH 19/28] Make boxed error accessible --- Sources/DataConnectError.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index dad3025..33ccaf0 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -37,7 +37,7 @@ public extension DataConnectError { /// Type erased DataConnectError @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public struct AnyDataConnectError: DataConnectError { - private let dataConnectError: DataConnectError + public let dataConnectError: DataConnectError init(dataConnectError: E) { self.dataConnectError = dataConnectError From 4d785944d1ab1b28bedb39221573be8362a5331a Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Wed, 26 Mar 2025 11:03:56 -0700 Subject: [PATCH 20/28] Add Unit test to confirm domain error carries through the boxed type --- Tests/Unit/ErrorsTypes.swift | 67 ++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 Tests/Unit/ErrorsTypes.swift diff --git a/Tests/Unit/ErrorsTypes.swift b/Tests/Unit/ErrorsTypes.swift new file mode 100644 index 0000000..dff6624 --- /dev/null +++ b/Tests/Unit/ErrorsTypes.swift @@ -0,0 +1,67 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Foundation +import Combine +import XCTest + +import FirebaseCore +@testable import FirebaseDataConnect + +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) +final class ErrorTypesTests: XCTestCase { + + private var pubCancellable: AnyCancellable? + private let errPublisher = PassthroughSubject, Never>() + + func throwInitError() throws { + throw DataConnectInitError.appNotConfigured() + } + + func testCatchAsGenericTypes() throws { + do { + try throwInitError() + } catch let dcerr as DataConnectError { + XCTAssertTrue(true) + } + } + + func testPublisherErrorType() throws { + + let errExpectation = XCTestExpectation(description: "Expect a Domain Erro") + + pubCancellable = errPublisher.sink( receiveValue: { result in + switch result { + case .success(_): + XCTFail("Unexpectedly got success. We expect a failure with error") + case let .failure(dcerror): + if let initErr = dcerror.dataConnectError as? DataConnectInitError, + initErr.code == .appNotConfigured + { + // got Init domain error + errExpectation.fulfill() + } else { + XCTFail("Did not get DataConnectInitError.appNotConfigured as expected") + } + } + }) + + errPublisher + .send( + .failure(AnyDataConnectError(dataConnectError: DataConnectInitError.appNotConfigured())) + ) + + wait(for: [errExpectation], timeout: 1.0) + } +} From 95fc74e7085919fdd9f7b2b4189adf98f0c24d9d Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Wed, 26 Mar 2025 11:09:21 -0700 Subject: [PATCH 21/28] Style checks --- Tests/Unit/ErrorsTypes.swift | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Tests/Unit/ErrorsTypes.swift b/Tests/Unit/ErrorsTypes.swift index dff6624..9303e2e 100644 --- a/Tests/Unit/ErrorsTypes.swift +++ b/Tests/Unit/ErrorsTypes.swift @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import Foundation import Combine +import Foundation import XCTest import FirebaseCore @@ -21,11 +21,10 @@ import FirebaseCore @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) final class ErrorTypesTests: XCTestCase { - private var pubCancellable: AnyCancellable? private let errPublisher = PassthroughSubject, Never>() - func throwInitError() throws { + func throwInitError() throws { throw DataConnectInitError.appNotConfigured() } @@ -38,17 +37,15 @@ final class ErrorTypesTests: XCTestCase { } func testPublisherErrorType() throws { - let errExpectation = XCTestExpectation(description: "Expect a Domain Erro") - pubCancellable = errPublisher.sink( receiveValue: { result in + pubCancellable = errPublisher.sink(receiveValue: { result in switch result { - case .success(_): + case .success: XCTFail("Unexpectedly got success. We expect a failure with error") case let .failure(dcerror): if let initErr = dcerror.dataConnectError as? DataConnectInitError, - initErr.code == .appNotConfigured - { + initErr.code == .appNotConfigured { // got Init domain error errExpectation.fulfill() } else { From 8bc19e73bfa9c6be4bda94e2f27280e48f2e6c0c Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Wed, 26 Mar 2025 12:22:00 -0700 Subject: [PATCH 22/28] Remove DataConnectError conformance AnyDataConnectError just becomes a container of DataConnectError so it can contain both base and domain errors --- Sources/DataConnectError.swift | 10 +--------- Sources/QueryRef.swift | 4 ++-- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index 33ccaf0..b2a227f 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -36,20 +36,12 @@ public extension DataConnectError { /// Type erased DataConnectError @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) -public struct AnyDataConnectError: DataConnectError { +public struct AnyDataConnectError: Error { public let dataConnectError: DataConnectError init(dataConnectError: E) { self.dataConnectError = dataConnectError } - - public var message: String? { - return dataConnectError.message - } - - public var underlyingError: (any Error)? { - return dataConnectError.underlyingError - } } @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) diff --git a/Sources/QueryRef.swift b/Sources/QueryRef.swift index e68b285..0dd2ca7 100644 --- a/Sources/QueryRef.swift +++ b/Sources/QueryRef.swift @@ -168,7 +168,7 @@ public class QueryRefObservableObject< self.data = resultData self.lastError = nil case let .failure(dcerror): - self.lastError = dcerror + self.lastError = dcerror.dataConnectError } }) } @@ -244,7 +244,7 @@ public class QueryRefObservation< self.data = resultData self.lastError = nil case let .failure(dcerror): - self.lastError = dcerror + self.lastError = dcerror.dataConnectError } }) } From 20d34b1bb65bf6af2f1ba34054c53ff43a3d22a7 Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Wed, 26 Mar 2025 18:06:35 -0700 Subject: [PATCH 23/28] Nick feedback --- Sources/DataConnectError.swift | 61 +++++++++++++++------------- Sources/DataConnectPathSegment.swift | 1 + Sources/Internal/GrpcClient.swift | 24 +++++++++-- 3 files changed, 54 insertions(+), 32 deletions(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index b2a227f..7d51151 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -14,9 +14,9 @@ import Foundation -// MARK: Base Error Definitions +// MARK: - Base Error Definitions -/// Protocol representing an error returned by the DataConnect service +/// A type representing an error returned by the DataConnect service @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public protocol DataConnectError: Error, CustomDebugStringConvertible, CustomStringConvertible { var message: String? { get } @@ -26,7 +26,7 @@ public protocol DataConnectError: Error, CustomDebugStringConvertible, CustomStr @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public extension DataConnectError { var debugDescription: String { - return "{\(Self.self), message: \(message ?? "nil"), cause: \(String(describing: underlyingError))}" + return "{\(Self.self), message: \(message ?? "nil"), underlyingError: \(String(describing: underlyingError))}" } var description: String { @@ -34,9 +34,10 @@ public extension DataConnectError { } } -/// Type erased DataConnectError +/// A structure representing a type-erased ``DataConnectError``. @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public struct AnyDataConnectError: Error { + /// Contained ``DataConnectError`` public let dataConnectError: DataConnectError init(dataConnectError: E) { @@ -44,8 +45,8 @@ public struct AnyDataConnectError: Error { } } -@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) /// Represents an error domain which can have more granular error codes +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public protocol DataConnectDomainError: DataConnectError { associatedtype ErrorCode: DataConnectErrorCode var code: ErrorCode { get } @@ -54,7 +55,7 @@ public protocol DataConnectDomainError: DataConnectError { @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public extension DataConnectDomainError { var debugDescription: String { - return "{\(Self.self), code: \(code), message: \(message ?? "nil"), cause: \(String(describing: underlyingError))}" + return "{\(Self.self), code: \(code), message: \(message ?? "nil"), underlyingError: \(String(describing: underlyingError))}" } var description: String { @@ -66,7 +67,7 @@ public extension DataConnectDomainError { @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public protocol DataConnectErrorCode: CustomStringConvertible, Equatable, Sendable, CaseIterable {} -// MARK: Data Connect Initialization Errors +// MARK: - Data Connect Initialization Errors /// Error initializing Data Connect public struct DataConnectInitError: DataConnectDomainError { @@ -107,7 +108,7 @@ public struct DataConnectInitError: DataConnectDomainError { } } -// MARK: Data Codec Errors +// MARK: - Data Codec Errors /// Data Encoding / Decoding Error public struct DataConnectCodecError: DataConnectDomainError { @@ -170,9 +171,11 @@ public struct DataConnectCodecError: DataConnectDomainError { } } -// MARK: Operation Execution Error including Partial Errors +// MARK: - Operation Execution Error including Partial Errors /// Data Connect Operation Failed +/// When available, the ``response`` will contain more error information and any partially decoded +/// result public struct DataConnectOperationError: DataConnectError { public let message: String? public let underlyingError: (any Error)? @@ -192,32 +195,32 @@ public struct DataConnectOperationError: DataConnectError { } } -// The data and errors sent to us from the backend in its response. -// New struct, that contains the data and errors sent to us -// from the backend in its response. +/// Contains the data and errors sent to us from the backend in its response. +/// The ``OperationFailureResponse`` if present, is available as part of the +/// ``DataConnectOperationError`` public struct OperationFailureResponse: Sendable { - // JSON string whose value is the "data" property provided by the backend in - // its response payload; may be `nil` if the "data" property was not provided - // in the backend response and/or was `null` in the backend response. + /// JSON string whose value is the "data" property provided by the backend in + /// its response payload; may be `nil` if the "data" property was not provided + /// in the backend response and/or was `null` in the backend response. public let rawJsonData: String? - // The list of errors in the "error" property provided by the backend in - // its response payload; may be empty if the "errors" property was not - // provided in the backend response and/or was an empty list in the backend response. + /// The list of errors in the "error" property provided by the backend in + /// its response payload; may be empty if the "errors" property was not + /// provided in the backend response and/or was an empty list in the backend response. public let errors: [ErrorInfo] // (Partially) decoded data private let data: Sendable? - // Returns `jsonData` string decoded into the given type, if decoding was - // successful when the operation was executed. Returns `nil` if `jsonData` - // is `nil`, if `jsonData` was _not_ able to be decoded when the operation - // was executed, or if the given type is _not_ equal to the `Data` type that - // was used when the operation was executed. - // - // This function does _not_ do the decoding itself, but simply returns - // the decoded data, if any, that was decoded at the time of the - // operation's execution. + /// Returns ``rawJsonData`` string decoded into the given type, if decoding was + /// successful when the operation was executed. Returns `nil` if `rawJsonData` + /// is `nil`, if ``rawJsonData`` was _not_ able to be decoded when the operation + /// was executed, or if the given type is _not_ equal to the `Data` type that + /// was used when the operation was executed. + /// + /// This function does _not_ do the decoding itself, but simply returns + /// the decoded data, if any, that was decoded at the time of the + /// operation's execution. func data(asType: Data.Type = Data.self) -> Data? { return data as? Data } @@ -231,9 +234,9 @@ public struct OperationFailureResponse: Sendable { } public struct ErrorInfo: Codable, Sendable { - // The error message. + /// The error message (if available) public let message: String - // The path to the field to which this error applies. + /// The path to the field to which this error applies. public let path: [DataConnectPathSegment] } } diff --git a/Sources/DataConnectPathSegment.swift b/Sources/DataConnectPathSegment.swift index 227cb81..1da35bc 100644 --- a/Sources/DataConnectPathSegment.swift +++ b/Sources/DataConnectPathSegment.swift @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public enum DataConnectPathSegment: Codable, Equatable, Sendable { case field(String) case listIndex(Int) diff --git a/Sources/Internal/GrpcClient.swift b/Sources/Internal/GrpcClient.swift index 5d252e7..bb15645 100644 --- a/Sources/Internal/GrpcClient.swift +++ b/Sources/Internal/GrpcClient.swift @@ -154,7 +154,13 @@ actor GrpcClient: CustomStringConvertible { // lets decode partial errors. We need these whether we succeed or fail let errorInfoList = createErrorInfoList(errors: results.errors) - // check if decode succeeds + /* + - if decode succeeds, errorList isEmpty = return data + - if decode succeeds, errorList notEmpty = throw OperationError with decodedData + - if decode fails, + - if errorList notEmpty -> throw OperationError with no decodedData + else -> throw decodeFailed with the inner error. + */ do { let decodedResults = try codec.decode(result: results.data, asType: resultType) @@ -171,6 +177,9 @@ actor GrpcClient: CustomStringConvertible { return OperationResult(data: decodedResults) } + } catch let operationErr as DataConnectOperationError { + // simply rethrow to avoid wrapping error + throw operationErr } catch { // we failed to decode if !errorInfoList.isEmpty { @@ -225,9 +234,15 @@ actor GrpcClient: CustomStringConvertible { .debug("executeMutation() receives response: \(resultsString, privacy: .private).") // lets decode partial errors. We need these whether we succeed or fail - var errorInfoList = createErrorInfoList(errors: results.errors) + let errorInfoList = createErrorInfoList(errors: results.errors) - // check if decode succeeds + /* + - if decode succeeds, errorList isEmpty = return data + - if decode succeeds, errorList notEmpty = throw OperationError with decodedData + - if decode fails, + - if errorList notEmpty -> throw OperationError with no decodedData + else -> throw decodeFailed with the inner error. + */ do { let decodedResults = try codec.decode(result: results.data, asType: resultType) @@ -244,6 +259,9 @@ actor GrpcClient: CustomStringConvertible { return OperationResult(data: decodedResults) } + } catch let operationErr as DataConnectOperationError { + // simply rethrow to avoid wrapping error + throw operationErr } catch { // we failed to decode if !errorInfoList.isEmpty { From 92c1aec105aaae4178a26b9a67d00da7f3cf2c07 Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Wed, 26 Mar 2025 18:13:00 -0700 Subject: [PATCH 24/28] fix copyright year --- Tests/Unit/ErrorsTypes.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Unit/ErrorsTypes.swift b/Tests/Unit/ErrorsTypes.swift index 9303e2e..f964c83 100644 --- a/Tests/Unit/ErrorsTypes.swift +++ b/Tests/Unit/ErrorsTypes.swift @@ -1,4 +1,4 @@ -// Copyright 2024 Google LLC +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. From 0fc0b6328395d449bfd0245c44cee3e89326a144 Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Wed, 26 Mar 2025 18:16:22 -0700 Subject: [PATCH 25/28] Comment feedback fix --- Sources/DataConnectError.swift | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index 7d51151..b0dd092 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -173,9 +173,18 @@ public struct DataConnectCodecError: DataConnectDomainError { // MARK: - Operation Execution Error including Partial Errors -/// Data Connect Operation Failed +/// An error that occurs during the execution of a Data Connect operation. +/// +/// This error can arise due to various reasons, such as network issues, server-side errors, +/// or problems with the operation itself. It may include an optional underlying error, +/// a message describing the failure, and an optional response from the failed operation. +/// /// When available, the ``response`` will contain more error information and any partially decoded /// result +/// +/// - SeeAlso: `DataConnectError` for the base error type. +/// + public struct DataConnectOperationError: DataConnectError { public let message: String? public let underlyingError: (any Error)? From 1c41f41611e7e719851fdea3efcce75f5d184105 Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Wed, 26 Mar 2025 18:22:27 -0700 Subject: [PATCH 26/28] Documentation fixes. --- Sources/DataConnectError.swift | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index b0dd092..cb0ba43 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -17,6 +17,8 @@ import Foundation // MARK: - Base Error Definitions /// A type representing an error returned by the DataConnect service +/// +/// - SeeAlso: ``DataConnectError`` for the base error type. @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public protocol DataConnectError: Error, CustomDebugStringConvertible, CustomStringConvertible { var message: String? { get } @@ -69,7 +71,13 @@ public protocol DataConnectErrorCode: CustomStringConvertible, Equatable, Sendab // MARK: - Data Connect Initialization Errors -/// Error initializing Data Connect +/// An error that occurs during the initialization of the Data Connect service. +/// +/// This error can arise due to various reasons, such as missing configurations or +/// issues with the underlying gRPC setup. It provides specific error codes +/// to pinpoint the cause of the initialization failure. +/// +/// - SeeAlso: ``DataConnectDomainError`` for the base error type. public struct DataConnectInitError: DataConnectDomainError { public struct Code: DataConnectErrorCode { private let code: String @@ -110,7 +118,13 @@ public struct DataConnectInitError: DataConnectDomainError { // MARK: - Data Codec Errors -/// Data Encoding / Decoding Error +/// An error that occurs during the encoding or decoding of data within the Data Connect service. +/// +/// This error can arise due to various reasons, such as invalid data formats, +/// incorrect UUIDs, or issues with timestamp/date formats. It provides specific error codes +/// to pinpoint the cause of the encoding/decoding failure. +/// +/// - SeeAlso: ``DataConnectDomainError`` for the base error type. public struct DataConnectCodecError: DataConnectDomainError { public struct Code: DataConnectErrorCode { private let code: String @@ -230,7 +244,7 @@ public struct OperationFailureResponse: Sendable { /// This function does _not_ do the decoding itself, but simply returns /// the decoded data, if any, that was decoded at the time of the /// operation's execution. - func data(asType: Data.Type = Data.self) -> Data? { + public func data(asType: Data.Type = Data.self) -> Data? { return data as? Data } From 0aafe10f5ceac361e8fe1dbae1c7da0e572566e3 Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Wed, 26 Mar 2025 21:44:36 -0700 Subject: [PATCH 27/28] More documentation fixes --- Sources/DataConnectError.swift | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index cb0ba43..fceeed2 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -65,7 +65,7 @@ public extension DataConnectDomainError { } } -/// Error code within an error domain +/// A type that represents an error code within an error domain. @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public protocol DataConnectErrorCode: CustomStringConvertible, Equatable, Sendable, CaseIterable {} @@ -235,15 +235,13 @@ public struct OperationFailureResponse: Sendable { // (Partially) decoded data private let data: Sendable? - /// Returns ``rawJsonData`` string decoded into the given type, if decoding was - /// successful when the operation was executed. Returns `nil` if `rawJsonData` - /// is `nil`, if ``rawJsonData`` was _not_ able to be decoded when the operation - /// was executed, or if the given type is _not_ equal to the `Data` type that - /// was used when the operation was executed. + /// Returns `rawJsonData` string decoded into the given type, if decoding was + /// successful when the operation was executed. /// - /// This function does _not_ do the decoding itself, but simply returns - /// the decoded data, if any, that was decoded at the time of the - /// operation's execution. + /// - Parameter asType: The type to decode the `rawJsonData` into (defaults to the inferred + /// generic parameter). + /// - Returns: The decoded data of type `Data` (generic parameter), if decoding to the + /// generic parameter was successful when the operation was executed, `nil` otherwise. public func data(asType: Data.Type = Data.self) -> Data? { return data as? Data } From c294d70bc4de796c89f035586378dc21a3cb8b39 Mon Sep 17 00:00:00 2001 From: Aashish Patil Date: Wed, 26 Mar 2025 21:49:15 -0700 Subject: [PATCH 28/28] Yet more doc fixes --- Sources/DataConnectError.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index fceeed2..9607fa8 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -47,7 +47,8 @@ public struct AnyDataConnectError: Error { } } -/// Represents an error domain which can have more granular error codes +/// A type that represents an error domain with granular error codes. +/// - SeeAlso: ``DataConnectError`` for the base error type. @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public protocol DataConnectDomainError: DataConnectError { associatedtype ErrorCode: DataConnectErrorCode