90 lines
3.1 KiB
Swift
90 lines
3.1 KiB
Swift
//
|
|
// Copyright Amazon.com Inc. or its affiliates.
|
|
// All Rights Reserved.
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
import Amplify
|
|
import Foundation
|
|
|
|
/// The raw response coming back from the AppSync GraphQL service
|
|
enum AWSAppSyncGraphQLResponse {
|
|
case data(_ graphQLData: [String: JSONValue])
|
|
case errors(_ graphQLErrors: [JSONValue])
|
|
case partial(graphQLData: [String: JSONValue], graphQLErrors: [JSONValue])
|
|
case invalidResponse
|
|
|
|
static func decodeToAWSAppSyncGraphQLResponse(response: Data) throws -> AWSAppSyncGraphQLResponse {
|
|
let jsonObject = try deserializeObject(graphQLResponse: response)
|
|
do {
|
|
let errors = try getAPIErrors(from: jsonObject)
|
|
let data = try getGraphQLData(from: jsonObject)
|
|
switch (data, errors) {
|
|
case (nil, nil):
|
|
return .invalidResponse
|
|
case (.some(let data), .none):
|
|
return .data(data)
|
|
case (.none, .some(let errors)):
|
|
return .errors(errors)
|
|
case (.some(let data), .some(let errors)):
|
|
return .partial(graphQLData: data, graphQLErrors: errors)
|
|
}
|
|
} catch is APIError {
|
|
return .invalidResponse
|
|
} catch {
|
|
throw error
|
|
}
|
|
}
|
|
|
|
private static func deserializeObject(graphQLResponse: Data) throws -> [String: JSONValue] {
|
|
let json: JSONValue
|
|
|
|
do {
|
|
let decoder = JSONDecoder()
|
|
decoder.dateDecodingStrategy = ModelDateFormatting.decodingStrategy
|
|
json = try decoder.decode(JSONValue.self, from: graphQLResponse)
|
|
} catch {
|
|
throw APIError.operationError("Could not decode to JSONValue from the GraphQL Response",
|
|
"Service issue",
|
|
error)
|
|
}
|
|
|
|
guard case .object(let jsonObject) = json else {
|
|
throw APIError.unknown("The GraphQL response is not an object",
|
|
"The AppSync service returned a malformed GraphQL response")
|
|
}
|
|
|
|
return jsonObject
|
|
}
|
|
|
|
private static func getAPIErrors(from jsonObject: [String: JSONValue]) throws -> [JSONValue]? {
|
|
guard let errors = jsonObject["errors"] else {
|
|
return nil
|
|
}
|
|
|
|
guard case .array(let errorArray) = errors else {
|
|
throw APIError.unknown("The GraphQL response containing errors should be an array",
|
|
"The AppSync service returned a malformed GraphQL response")
|
|
}
|
|
|
|
return errorArray
|
|
}
|
|
|
|
private static func getGraphQLData(from jsonObject: [String: JSONValue]) throws -> [String: JSONValue]? {
|
|
guard let data = jsonObject["data"] else {
|
|
return nil
|
|
}
|
|
|
|
switch data {
|
|
case .object(let dataObject):
|
|
return dataObject
|
|
case .null:
|
|
return nil
|
|
default:
|
|
throw APIError.unknown("Failed to get object or null from data.",
|
|
"The AppSync service returned a malformed GraphQL response")
|
|
}
|
|
}
|
|
}
|