diff --git a/packages/amplify_datastore/example/ios/unit_tests/GraphQLResponse+DecodeTests.swift b/packages/amplify_datastore/example/ios/unit_tests/GraphQLResponse+DecodeTests.swift index 3c5d1071af..c046b6c341 100644 --- a/packages/amplify_datastore/example/ios/unit_tests/GraphQLResponse+DecodeTests.swift +++ b/packages/amplify_datastore/example/ios/unit_tests/GraphQLResponse+DecodeTests.swift @@ -116,7 +116,7 @@ class GraphQLResponseDecodeTests: XCTestCase { "a": ["b"] ] let expectedJson = "{\"a\":[\"b\"]}" - let result: Result = GraphQLResponse.decodeDataPayload(json, modelName: nil) + let result: Result = GraphQLResponse.decodeDataPayload(json, modelName: "Post") XCTAssertNoThrow(try result.get()) XCTAssertEqual(expectedJson, try result.get()) } @@ -137,7 +137,7 @@ class GraphQLResponseDecodeTests: XCTestCase { "author": "authorId", ], modelName: "Post")) - let result: Result = GraphQLResponse.decodeDataPayload(json, modelName: nil) + let result: Result = GraphQLResponse.decodeDataPayload(json, modelName: "Post") XCTAssertNoThrow(try result.get()) XCTAssertEqual(expectedModel.modelName, try result.get().modelName) XCTAssertEqual(expectedModel.id, try result.get().id) @@ -227,7 +227,11 @@ class GraphQLResponseDecodeTests: XCTestCase { "author": "authorId", ], modelName: "Post")) - let result: Result>, APIError> = .fromAppSyncResponse(json: json, decodePath: "onCreatePost", modelName: nil) + let result: Result>, APIError> = .fromAppSyncResponse( + json: json, + decodePath: "onCreatePost", + modelName: "Post" + ) XCTAssertNoThrow(try result.get()) let mutationSync = try! result.get() XCTAssertNoThrow(try mutationSync.get()) @@ -244,7 +248,11 @@ class GraphQLResponseDecodeTests: XCTestCase { ] ] - let result: Result>, APIError> = .fromAppSyncResponse(json: json, decodePath: "onCreatePost", modelName: nil) + let result: Result>, APIError> = .fromAppSyncResponse( + json: json, + decodePath: "onCreatePost", + modelName: "Post" + ) XCTAssertNoThrow(try result.get()) let mutationSync = try! result.get() XCTAssertThrowsError(try mutationSync.get()) { error in @@ -283,7 +291,11 @@ class GraphQLResponseDecodeTests: XCTestCase { "author": "authorId", ], modelName: "Post")) - let result: Result>, APIError> = .fromAppSyncResponse(json: json, decodePath: "onCreatePost", modelName: nil) + let result: Result>, APIError> = .fromAppSyncResponse( + json: json, + decodePath: "onCreatePost", + modelName: "Post" + ) XCTAssertNoThrow(try result.get()) let mutationSync = try! result.get() XCTAssertThrowsError(try mutationSync.get()) { error in @@ -305,7 +317,11 @@ class GraphQLResponseDecodeTests: XCTestCase { "a": "b" ] - let result: Result>, APIError> = .fromAppSyncResponse(json: json, decodePath: "onCreatePost", modelName: nil) + let result: Result>, APIError> = .fromAppSyncResponse( + json: json, + decodePath: "onCreatePost", + modelName: "Post" + ) XCTAssertThrowsError(try result.get()) { error in if case .unknown(let description, _, _) = (error as! APIError) { XCTAssertEqual("Failed to get data object or errors from GraphQL response", description) @@ -325,7 +341,7 @@ class GraphQLResponseDecodeTests: XCTestCase { ] let jsonString = String(data: try! JSONEncoder().encode(json), encoding: .utf8)! - let response: GraphQLResponse = .fromAppSyncResponse(string: jsonString, decodePath: nil) + let response: GraphQLResponse = .fromAppSyncResponse(string: jsonString, decodePath: nil, modelName: "Post") XCTAssertNoThrow(try response.get()) XCTAssertEqual(json.id?.stringValue, try response.get().identifier) XCTAssertEqual(json.__typename?.stringValue, try response.get().modelName) @@ -334,7 +350,7 @@ class GraphQLResponseDecodeTests: XCTestCase { func testFromAppSyncResponse_withBrokenJsonString_failWithTransformationError() { SchemaData.modelSchemaRegistry.registerModels(registry: ModelRegistry.self) let jsonString = "{" - let response: GraphQLResponse = .fromAppSyncResponse(string: jsonString, decodePath: nil) + let response: GraphQLResponse = .fromAppSyncResponse(string: jsonString, decodePath: nil, modelName: "Post") XCTAssertThrowsError(try response.get()) { error in guard case .transformationError = error as! GraphQLResponseError else { XCTFail("Should failed with transformationError") @@ -358,7 +374,11 @@ class GraphQLResponseDecodeTests: XCTestCase { ] let jsonString = String(data: try! JSONEncoder().encode(payloadJson), encoding: .utf8)! - let response: GraphQLResponse> = .fromAppSyncResponse(string: jsonString, decodePath: "onCreatePost") + let response: GraphQLResponse> = .fromAppSyncResponse( + string: jsonString, + decodePath: "onCreatePost", + modelName: "Post" + ) XCTAssertNoThrow(try response.get()) let mutationSync = try! response.get() XCTAssertEqual(payloadJson.onCreatePost?.id?.stringValue, mutationSync.model.identifier) @@ -368,7 +388,11 @@ class GraphQLResponseDecodeTests: XCTestCase { func testFromAppSyncSubscriptionResponse_withWrongJsonString_failWithTransformationError() { SchemaData.modelSchemaRegistry.registerModels(registry: ModelRegistry.self) let jsonString = "{" - let response: GraphQLResponse> = .fromAppSyncSubscriptionResponse(string: jsonString, decodePath: nil) + let response: GraphQLResponse> = .fromAppSyncSubscriptionResponse( + string: jsonString, + decodePath: nil, + modelName: "Post" + ) XCTAssertThrowsError(try response.get()) { error in guard case .transformationError = error as! GraphQLResponseError> else { XCTFail("Should failed with transformationError") diff --git a/packages/amplify_datastore/ios/Classes/FlutterApiPlugin.swift b/packages/amplify_datastore/ios/Classes/FlutterApiPlugin.swift index b23182c352..0ceb6ffa02 100644 --- a/packages/amplify_datastore/ios/Classes/FlutterApiPlugin.swift +++ b/packages/amplify_datastore/ios/Classes/FlutterApiPlugin.swift @@ -100,12 +100,14 @@ public class FlutterApiPlugin: APICategoryPlugin throw DataStoreError.decodingError("Request payload could not be empty", "") } - let datastoreOptions = request.options?.pluginOptions as? AWSAPIPluginDataStoreOptions - + guard let datastoreOptions = request.options?.pluginOptions as? AWSAPIPluginDataStoreOptions else { + throw DataStoreError.decodingError("Failed to decode the GraphQLRequest due to a missing options field.", "") + } + return GraphQLResponse.fromAppSyncResponse( string: payload, decodePath: request.decodePath, - modelName: datastoreOptions?.modelName + modelName: datastoreOptions.modelName ) } @@ -117,12 +119,14 @@ public class FlutterApiPlugin: APICategoryPlugin throw DataStoreError.decodingError("Request payload could not be empty", "") } - let datastoreOptions = request.options?.pluginOptions as? AWSAPIPluginDataStoreOptions + guard let datastoreOptions = request.options?.pluginOptions as? AWSAPIPluginDataStoreOptions else { + throw DataStoreError.decodingError("Failed to decode the GraphQLRequest due to a missing options field.", "") + } return GraphQLResponse.fromAppSyncSubscriptionResponse( string: payload, decodePath: request.decodePath, - modelName: datastoreOptions?.modelName + modelName: datastoreOptions.modelName ) } diff --git a/packages/amplify_datastore/ios/Classes/api/GraphQLResponse+Decode.swift b/packages/amplify_datastore/ios/Classes/api/GraphQLResponse+Decode.swift index acb977c8e4..630fdd0636 100644 --- a/packages/amplify_datastore/ios/Classes/api/GraphQLResponse+Decode.swift +++ b/packages/amplify_datastore/ios/Classes/api/GraphQLResponse+Decode.swift @@ -22,7 +22,7 @@ extension GraphQLResponse { public static func fromAppSyncResponse( string: String, decodePath: String?, - modelName: String? = nil + modelName: String ) -> GraphQLResponse { guard let data = string.data(using: .utf8) else { return .failure(.transformationError( @@ -44,7 +44,7 @@ extension GraphQLResponse { public static func fromAppSyncSubscriptionResponse( string: String, decodePath: String?, - modelName: String? = nil + modelName: String ) -> GraphQLResponse { guard let data = string.data(using: .utf8) else { return .failure(.transformationError( @@ -98,7 +98,7 @@ extension GraphQLResponse { static func fromAppSyncResponse( json: JSONValue, decodePath: String?, - modelName: String? + modelName: String ) -> Result, APIError> { let data = decodePath != nil ? json.value(at: decodePath!) : json let errors = json.errors?.asArray @@ -147,18 +147,17 @@ extension GraphQLResponse { static func decodeDataPayload( _ dataPayload: JSONValue, - modelName: String? + modelName: String ) -> Result { if R.self == String.self { return encodeDataPayloadToString(dataPayload).map { $0 as! R } } /// This is included to allow multi-platform support. Requests that do not have `__typename` - let dataPayloadWithTypeName = modelName.flatMap { - dataPayload.asObject?.merging( - ["__typename": .string($0)] - ) { a, _ in a } - }.map { JSONValue.object($0) } ?? dataPayload + let dataPayloadWithTypeName = (dataPayload.asObject?.merging( + ["__typename": .string(modelName)], + uniquingKeysWith: { a, _ in a } + )).map { JSONValue.object($0) } ?? dataPayload if R.self == AnyModel.self { return decodeDataPayloadToAnyModel(dataPayloadWithTypeName).map { $0 as! R }