Skip to content

Commit 33b7a27

Browse files
Improve handling of potential null values from the JS side. (#213)
1 parent ff492fe commit 33b7a27

File tree

14 files changed

+65
-71
lines changed

14 files changed

+65
-71
lines changed

__tests__/Types_test.re

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ describe("Types", () => {
3232
Types.{
3333
operation: mockOperation,
3434
fetching: true,
35-
data: None,
35+
data: Js.Nullable.undefined,
3636
error: None,
3737
extensions: None,
3838
stale: false,
@@ -51,7 +51,7 @@ describe("Types", () => {
5151
Types.{
5252
operation: mockOperation,
5353
fetching: false,
54-
data: Some(Js.Json.string("Hello")),
54+
data: Js.Nullable.return(Js.Json.string("Hello")),
5555
error: None,
5656
extensions: None,
5757
stale: false,
@@ -98,7 +98,7 @@ describe("Types", () => {
9898
Types.{
9999
operation: mockOperation,
100100
fetching: false,
101-
data: Some(Js.Json.string("Hello")),
101+
data: Js.Nullable.return(Js.Json.string("Hello")),
102102
error: Some(errorJs),
103103
extensions: None,
104104
stale: false,
@@ -148,7 +148,7 @@ describe("Types", () => {
148148
Types.{
149149
operation: mockOperation,
150150
fetching: false,
151-
data: None,
151+
data: Js.Nullable.undefined,
152152
error: Some(errorJs),
153153
extensions: None,
154154
stale: false,
@@ -164,7 +164,7 @@ describe("Types", () => {
164164
Types.{
165165
operation: mockOperation,
166166
fetching: false,
167-
data: None,
167+
data: Js.Nullable.undefined,
168168
error: None,
169169
extensions: None,
170170
stale: false,

src/Client.re

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,15 +190,19 @@ type response('response) =
190190
type clientResponse('response) = {
191191
data: option('response),
192192
error: option(CombinedError.t),
193+
extensions: option(Js.Dict.t(string)),
193194
response: response('response),
195+
stale: option(bool),
194196
};
195197

196198
/**
197199
* A function to convert the JS response from a client.execute*
198200
* methods to typed a Reason record.
199201
*/
200202
let urqlClientResponseToReason = (~response: Types.operationResult, ~parse) => {
201-
let data = response.data->Belt.Option.map(parse);
203+
let {extensions, stale}: Types.operationResult = response;
204+
205+
let data = response.data->Js.Nullable.toOption->Belt.Option.map(parse);
202206
let error =
203207
response.error->Belt.Option.map(CombinedError.combinedErrorToRecord);
204208

@@ -209,7 +213,7 @@ let urqlClientResponseToReason = (~response: Types.operationResult, ~parse) => {
209213
| (None, None) => Empty
210214
};
211215

212-
{data, error, response};
216+
{data, error, extensions, stale, response};
213217
};
214218

215219
/* Execution methods on the client. These allow you to imperatively execute GraphQL

src/Client.rei

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@ type response('response) =
133133
type clientResponse('response) = {
134134
data: option('response),
135135
error: option(CombinedError.t),
136+
extensions: option(Js.Dict.t(string)),
136137
response: response('response),
138+
stale: option(bool),
137139
};
138140

139141
let urqlClientResponseToReason:

src/GraphQLError.re

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ type source = {
1212
locationOffset: sourceLocation,
1313
};
1414

15-
type extension;
16-
1715
type t = {
1816
message: string,
1917
locations: option(array(sourceLocation)),
@@ -22,5 +20,5 @@ type t = {
2220
source: option(source),
2321
positions: option(array(int)),
2422
originalError: option(Js.Exn.t),
25-
extensions: option(Js.Dict.t(extension)),
23+
extensions: option(Js.Json.t),
2624
};

src/GraphQLError.rei

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ type source = {
1212
locationOffset: sourceLocation,
1313
};
1414

15-
type extension;
16-
1715
type t = {
1816
message: string,
1917
locations: option(array(sourceLocation)),
@@ -22,5 +20,5 @@ type t = {
2220
source: option(source),
2321
positions: option(array(int)),
2422
originalError: option(Js.Exn.t),
25-
extensions: option(Js.Dict.t(extension)),
23+
extensions: option(Js.Json.t),
2624
};

src/Types.re

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,9 @@ type operation = {
7070
/* The result of the GraphQL operation. */
7171
type operationResult = {
7272
operation,
73-
data: option(Js.Json.t),
73+
data: Js.Nullable.t(Js.Json.t),
7474
error: option(CombinedError.combinedErrorJs),
75+
extensions: option(Js.Dict.t(string)),
7576
stale: option(bool),
7677
};
7778

@@ -99,22 +100,22 @@ type response('response) =
99100
| Error(CombinedError.t)
100101
| Empty;
101102

102-
type hookResponse('response, 'extensions) = {
103+
type hookResponse('response) = {
103104
operation,
104105
fetching: bool,
105106
data: option('response),
106107
error: option(CombinedError.t),
107108
response: response('response),
108-
extensions: option('extensions),
109+
extensions: option(Js.Json.t),
109110
stale: bool,
110111
};
111112

112-
type hookResponseJs('response, 'extensions) = {
113+
type hookResponseJs('response) = {
113114
operation,
114115
fetching: bool,
115-
data: option('response),
116+
data: Js.Nullable.t('response),
116117
error: option(CombinedError.combinedErrorJs),
117-
extensions: option('extensions),
118+
extensions: option(Js.Json.t),
118119
stale: bool,
119120
};
120121

@@ -123,11 +124,12 @@ type hookResponseJs('response, 'extensions) = {
123124
* JavaScript representation to a typed Reason record.
124125
*/
125126
let urqlResponseToReason = (~response, ~parse) => {
126-
let data = Belt.Option.map(response.data, parse);
127-
let error =
128-
Belt.Option.map(response.error, CombinedError.combinedErrorToRecord);
129127
let {operation, fetching, extensions, stale} = response;
130128

129+
let data = response.data->Js.Nullable.toOption->Belt.Option.map(parse);
130+
let error =
131+
response.error->Belt.Option.map(CombinedError.combinedErrorToRecord);
132+
131133
let response =
132134
switch (fetching, data, error) {
133135
| (true, None, _) => Fetching
@@ -154,5 +156,4 @@ type graphqlDefinition('parseResult, 'composeReturnType, 'hookReturnType) = (
154156
type executionResult = {
155157
errors: option(array(GraphQLError.t)),
156158
data: option(Js.Json.t),
157-
extensions: Js.Json.t,
158159
};

src/Types.rei

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ type operation = {
6060
/* The result of the GraphQL operation. */
6161
type operationResult = {
6262
operation,
63-
data: option(Js.Json.t),
63+
data: Js.Nullable.t(Js.Json.t),
6464
error: option(CombinedError.combinedErrorJs),
65+
extensions: option(Js.Dict.t(string)),
6566
stale: option(bool),
6667
};
6768

@@ -89,31 +90,28 @@ type response('response) =
8990
| Error(CombinedError.t)
9091
| Empty;
9192

92-
type hookResponse('response, 'extensions) = {
93+
type hookResponse('response) = {
9394
operation,
9495
fetching: bool,
9596
data: option('response),
9697
error: option(CombinedError.t),
9798
response: response('response),
98-
extensions: option('extensions),
99+
extensions: option(Js.Json.t),
99100
stale: bool,
100101
};
101102

102-
type hookResponseJs('response, 'extensions) = {
103+
type hookResponseJs('response) = {
103104
operation,
104105
fetching: bool,
105-
data: option('response),
106+
data: Js.Nullable.t('response),
106107
error: option(CombinedError.combinedErrorJs),
107-
extensions: option('extensions),
108+
extensions: option(Js.Json.t),
108109
stale: bool,
109110
};
110111

111112
let urqlResponseToReason:
112-
(
113-
~response: hookResponseJs(Js.Json.t, 'extensions),
114-
~parse: Js.Json.t => 'response
115-
) =>
116-
hookResponse('response, 'extensions);
113+
(~response: hookResponseJs(Js.Json.t), ~parse: Js.Json.t => 'response) =>
114+
hookResponse('response);
117115

118116
type graphqlDefinition('parseResult, 'composeReturnType, 'hookReturnType) = (
119117
// `parse`
@@ -129,5 +127,4 @@ type graphqlDefinition('parseResult, 'composeReturnType, 'hookReturnType) = (
129127
type executionResult = {
130128
errors: option(array(GraphQLError.t)),
131129
data: option(Js.Json.t),
132-
extensions: Js.Json.t,
133130
};

src/hooks/Hooks.re

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ include UseQuery;
33
include UseMutation;
44
include UseSubscription;
55

6-
type hookResponse('ret, 'extensions) =
7-
Types.hookResponse('ret, 'extensions) = {
6+
type hookResponse('ret) =
7+
Types.hookResponse('ret) = {
88
operation: Types.operation,
99
fetching: bool,
1010
data: option('ret),
1111
error: option(CombinedError.t),
1212
response: Types.response('ret),
13-
extensions: option('extensions),
13+
extensions: option(Js.Json.t),
1414
stale: bool,
1515
};

src/hooks/UseMutation.re

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,18 @@ type executeMutation =
1717
) =>
1818
Js.Promise.t(Types.operationResult);
1919

20-
type useMutationResponseJs('extensions) = (
21-
Types.hookResponseJs(Js.Json.t, 'extensions),
20+
type useMutationResponseJs = (
21+
Types.hookResponseJs(Js.Json.t),
2222
executeMutationJs,
2323
);
2424

25-
type useMutationResponse('response, 'extensions) = (
26-
Types.hookResponse('response, 'extensions),
25+
type useMutationResponse('response) = (
26+
Types.hookResponse('response),
2727
executeMutation,
2828
);
2929

3030
[@bs.module "urql"]
31-
external useMutationJs: string => useMutationResponseJs('extensions) =
32-
"useMutation";
31+
external useMutationJs: string => useMutationResponseJs = "useMutation";
3332

3433
/**
3534
* The useMutation hook.

src/hooks/UseMutation.rei

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,13 @@ type executeMutation =
1313
) =>
1414
Js.Promise.t(Types.operationResult);
1515

16-
type useMutationResponse('response, 'extensions) = (
17-
Types.hookResponse('response, 'extensions),
16+
type useMutationResponse('response) = (
17+
Types.hookResponse('response),
1818
executeMutation,
1919
);
2020

2121
let useMutation:
22-
(~request: Types.request('response)) =>
23-
useMutationResponse('response, 'extensions);
22+
(~request: Types.request('response)) => useMutationResponse('response);
2423

2524
let useDynamicMutation:
2625
Types.graphqlDefinition(
@@ -29,7 +28,7 @@ let useDynamicMutation:
2928
'executeMutation,
3029
) =>
3130
(
32-
Types.hookResponse('parse, 'extensions),
31+
Types.hookResponse('parse),
3332
(
3433
~additionalTypenames: array(string)=?,
3534
~fetchOptions: Fetch.requestInit=?,

0 commit comments

Comments
 (0)