Skip to content

Commit 973a02f

Browse files
authored
fix(fdc): errors are now properly propagated to the user (#13433)
* Handled errors * Only throw errors if errors is not empty
1 parent 8689a43 commit 973a02f

File tree

4 files changed

+41
-0
lines changed

4 files changed

+41
-0
lines changed

packages/firebase_data_connect/firebase_data_connect/example/dataconnect/connector/mutations.gql

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ mutation addDateAndTimestamp($date: Date!, $timestamp: Timestamp!) @auth(level:
2121
mutation seedMovies @auth(level: PUBLIC) {
2222
the_matrix: movie_insert(
2323
data: {
24+
id: "09d5f835656c467787347668bbb44522"
2425
title: "The Matrix"
2526
releaseYear: 1999
2627
genre: "Sci-Fi"
@@ -70,6 +71,7 @@ mutation thing($title: Any! = "ABC") @auth(level: PUBLIC) {
7071
mutation seedData @auth(level: PUBLIC) {
7172
the_matrix: movie_insert(
7273
data: {
74+
id: "09d5f835656c467787347668bbb44522"
7375
title: "The Matrix"
7476
releaseYear: 1999
7577
genre: "Action"

packages/firebase_data_connect/firebase_data_connect/lib/src/network/grpc_transport.dart

+3
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ class GRPCTransport implements DataConnectTransport {
137137
try {
138138
response = await stub.executeMutation(request,
139139
options: CallOptions(metadata: await getMetadata()));
140+
if (response.errors.isNotEmpty) {
141+
throw Exception(response.errors);
142+
}
140143
return deserializer(jsonEncode(response.data.toProto3Json()));
141144
} on Exception catch (e) {
142145
throw DataConnectError(DataConnectErrorCode.other,

packages/firebase_data_connect/firebase_data_connect/lib/src/network/rest_transport.dart

+8
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,14 @@ class RestTransport implements DataConnectTransport {
112112
? DataConnectErrorCode.unauthorized
113113
: DataConnectErrorCode.other,
114114
"Received a status code of ${r.statusCode} with a message '${message}'");
115+
} else {
116+
Map<String, dynamic> bodyJson =
117+
jsonDecode(r.body) as Map<String, dynamic>;
118+
if (bodyJson.containsKey("errors") &&
119+
(bodyJson['errors'] as List).isNotEmpty) {
120+
throw DataConnectError(
121+
DataConnectErrorCode.other, bodyJson['errors'].toString());
122+
}
115123
}
116124

117125
/// The response we get is in the data field of the response

packages/firebase_data_connect/firebase_data_connect/test/src/network/rest_transport_test.dart

+28
Original file line numberDiff line numberDiff line change
@@ -223,5 +223,33 @@ void main() {
223223
body: anyNamed('body'),
224224
)).called(1);
225225
});
226+
test('invokeOperation should throw an error if the server throws one',
227+
() async {
228+
final mockResponse = http.Response("""
229+
{
230+
"data": {},
231+
"errors": [
232+
{
233+
"message": "SQL query error: pq: duplicate key value violates unique constraint movie_pkey",
234+
"locations": [],
235+
"path": [
236+
"the_matrix"
237+
],
238+
"extensions": null
239+
}
240+
]
241+
}""", 200);
242+
when(mockHttpClient.post(any,
243+
headers: anyNamed('headers'), body: anyNamed('body')))
244+
.thenAnswer((_) async => mockResponse);
245+
246+
final deserializer = (String data) => 'Deserialized Data';
247+
248+
expect(
249+
() => transport.invokeOperation(
250+
'testQuery', deserializer, null, null, 'executeQuery'),
251+
throwsA(isA<DataConnectError>()),
252+
);
253+
});
226254
});
227255
}

0 commit comments

Comments
 (0)