77 lines
3.0 KiB
Swift
77 lines
3.0 KiB
Swift
//
|
|
// Copyright Amazon.com Inc. or its affiliates.
|
|
// All Rights Reserved.
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
import Amplify
|
|
import AppSyncRealTimeClient
|
|
import Foundation
|
|
|
|
struct GraphQLErrorDecoder {
|
|
static func decodeErrors(graphQLErrors: [JSONValue]) throws -> [GraphQLError] {
|
|
var responseErrors = [GraphQLError]()
|
|
for error in graphQLErrors {
|
|
do {
|
|
let responseError = try decode(graphQLErrorJSON: error)
|
|
responseErrors.append(responseError)
|
|
} catch let decodingError as DecodingError {
|
|
throw APIError(error: decodingError)
|
|
} catch {
|
|
throw APIError.unknown("""
|
|
Unexpected failure while decoding GraphQL response containing errors:
|
|
\(String(describing: graphQLErrors))
|
|
""", "", error)
|
|
}
|
|
}
|
|
|
|
return responseErrors
|
|
}
|
|
|
|
static func decodeAppSyncErrors(_ appSyncJSON: AppSyncJSONValue) throws -> [GraphQLError] {
|
|
guard case let .array(errors) = appSyncJSON else {
|
|
throw APIError.unknown("Expected 'errors' field not found in \(String(describing: appSyncJSON))", "", nil)
|
|
}
|
|
let convertedValues = errors.map(AppSyncJSONValue.toJSONValue)
|
|
return try decodeErrors(graphQLErrors: convertedValues)
|
|
}
|
|
|
|
static func decode(graphQLErrorJSON: JSONValue) throws -> GraphQLError {
|
|
let serializedJSON = try JSONEncoder().encode(graphQLErrorJSON)
|
|
let decoder = JSONDecoder()
|
|
decoder.dateDecodingStrategy = ModelDateFormatting.decodingStrategy
|
|
let graphQLError = try decoder.decode(GraphQLError.self, from: serializedJSON)
|
|
return mergeExtensions(from: graphQLErrorJSON, graphQLError: graphQLError)
|
|
}
|
|
|
|
/// Merge fields which are not in the generic GraphQL error json over into the `GraphQLError.extensions`
|
|
/// This is the opinionated implementation of the plugin to store service errors which do not conform to the
|
|
/// GraphQL Error spec (https://spec.graphql.org/June2018/#sec-Errors)
|
|
private static func mergeExtensions(from graphQLErrorJSON: JSONValue, graphQLError: GraphQLError) -> GraphQLError {
|
|
var keys = ["message", "locations", "path", "extensions"]
|
|
var mergedExtensions = [String: JSONValue]()
|
|
if let graphQLErrorExtensions = graphQLError.extensions {
|
|
mergedExtensions = graphQLErrorExtensions
|
|
keys += mergedExtensions.keys
|
|
}
|
|
|
|
guard case let .object(graphQLErrorObject) = graphQLErrorJSON else {
|
|
return graphQLError
|
|
}
|
|
|
|
graphQLErrorObject.forEach { key, value in
|
|
if keys.contains(key) {
|
|
return
|
|
}
|
|
|
|
mergedExtensions[key] = value
|
|
}
|
|
|
|
return GraphQLError(message: graphQLError.message,
|
|
locations: graphQLError.locations,
|
|
path: graphQLError.path,
|
|
extensions: mergedExtensions.isEmpty ? nil : mergedExtensions)
|
|
}
|
|
}
|