diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index c6e299f..b12b49c 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -34,4 +34,7 @@ public enum DataConnectError: Error { /// timestamp components specified to initialize Timestamp are invalid case invalidTimestampFormat + + /// generic operation execution error + case operationExecutionFailed(messages: String?) } diff --git a/Sources/Internal/GrpcClient.swift b/Sources/Internal/GrpcClient.swift index 5f41f24..29b0cd3 100644 --- a/Sources/Internal/GrpcClient.swift +++ b/Sources/Internal/GrpcClient.swift @@ -27,6 +27,7 @@ import SwiftProtobuf @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) typealias FirebaseDataConnectAsyncClient = Google_Firebase_Dataconnect_V1beta_ConnectorServiceAsyncClient +typealias FirebaseDataConnectGraphqlError = Google_Firebase_Dataconnect_V1beta_GraphqlError @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) actor GrpcClient: CustomStringConvertible { @@ -148,7 +149,13 @@ actor GrpcClient: CustomStringConvertible { let resultsString = try results.jsonString() 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)) + } + if let decodedResults = try codec.decode(result: results.data, asType: resultType) { return OperationResult(data: decodedResults) } else { @@ -191,6 +198,12 @@ actor GrpcClient: CustomStringConvertible { let resultsString = try results.jsonString() DataConnectLogger .debug("executeMutation() receives response: \(resultsString, privacy: .private).") + + guard results.errors.isEmpty else { + throw DataConnectError + .operationExecutionFailed(messages: createErrorJson(errors: results.errors)) + } + if let decodedResults = try codec.decode(result: results.data, asType: resultType) { return OperationResult(data: decodedResults) } else { @@ -206,6 +219,22 @@ actor GrpcClient: CustomStringConvertible { } } + private func createErrorJson(errors: [FirebaseDataConnectGraphqlError]) -> String? { + var errorMessages = [String]() + for err in errors { + errorMessages.append(err.message) + } + + do { + let jsonEncoder = JSONEncoder() + let jsonData = try jsonEncoder.encode(errorMessages) + return String(data: jsonData, encoding: .utf8) + } catch { + DataConnectLogger.error("Error encoding partial error list") + return nil + } + } + func createCallOptions() async -> CallOptions { var headers = HPACKHeaders()