Skip to content

Commit

Permalink
feat: decoder support on fragment definition (mhallin#80)
Browse files Browse the repository at this point in the history
* adds decoder support to fragments
* deletes newline
* fixes builds
  • Loading branch information
mbirkegaard authored Feb 18, 2020
1 parent 18cbfa0 commit 77d8c45
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 25 deletions.
60 changes: 53 additions & 7 deletions src/base/result_decoder.re
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,45 @@ let rec unify_document_schema = (config, document) => {
...rest,
] => [
{
open Result;

let with_decoder =
switch (fg_directives |> find_directive("bsDecoder")) {
| None => Ok(None)
| Some({item: {d_arguments, _}, span}) =>
switch (find_argument("fn", d_arguments)) {
| None =>
Error(
make_error(
error_marker,
config.map_loc,
span,
"bsDecoder must be given 'fn' argument",
),
)
| Some((_, {item: Iv_string(fn_name), span})) =>
Ok(
Some(
structure =>
Res_custom_decoder(
config.map_loc(span),
fn_name,
structure,
),
),
)
| Some((_, {span, _})) =>
Error(
make_error(
error_marker,
config.map_loc,
span,
"The 'fn' argument must be a string",
),
)
}
};

let is_record = has_directive("bsRecord", fg_directives);
switch (Schema.lookup_type(config.schema, fg_type_condition.item)) {
| None =>
Expand All @@ -601,13 +640,20 @@ let rec unify_document_schema = (config, document) => {
Some(fg_selection_set),
);

Mod_fragment(
fg_name.item,
[],
error_marker.has_error,
fg,
structure,
);
switch (with_decoder) {
| Error(err) => Mod_fragment(fg_name.item, [], true, fg, err)
| Ok(decoder) =>
Mod_fragment(
fg_name.item,
[],
error_marker.has_error,
fg,
switch (decoder) {
| Some(decoder) => decoder(structure)
| None => structure
},
)
};
};
},
...unify_document_schema(config, rest),
Expand Down
53 changes: 39 additions & 14 deletions tests_bucklescript/__tests__/fragmentDefinition.re
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
type record = {
nullableOfNullable: option(array(option(string))),
nullableOfNonNullable: option(array(string)),
};

let concat = ({nullableOfNullable, nullableOfNonNullable}) => {
let x =
nullableOfNullable
->Belt.Option.getWithDefault([||])
->Belt.Array.keepMap(x => x);
let y = nullableOfNonNullable->Belt.Option.getWithDefault([||]);

Belt.Array.concat(x, y);
};

module Fragments = [%graphql
{|
fragment listFragment on Lists {
nullableOfNullable
nullableOfNonNullable
}

fragment concatFragment on Lists @bsRecord @bsDecoder(fn: "concat") {
nullableOfNullable
nullableOfNonNullable
}
|}
];

Expand All @@ -18,6 +38,10 @@ module MyQuery = [%graphql
...Fragments.ListFragment @bsField(name: "frag1")
...Fragments.ListFragment @bsField(name: "frag2")
}

l3: lists {
...Fragments.ConcatFragment
}
}
|}
];
Expand All @@ -26,34 +50,35 @@ open Jest;
open Expect;

describe("Fragment definition", () => {
let expectedObject = {
"nullableOfNullable": Some([|Some("a"), None, Some("b")|]),
"nullableOfNonNullable": None,
};

test("Decodes the fragment", () =>
{|
{
"l1": {"nullableOfNullable": ["a", null, "b"]},
"l2": {"nullableOfNullable": ["a", null, "b"]}
"l2": {"nullableOfNullable": ["a", null, "b"]},
"l3": {
"nullableOfNullable": ["a", null, "b", null, "c"],
"nullableOfNonNullable": ["d", "e"]
}
}|}
|> Js.Json.parseExn
|> MyQuery.parse
|> expect
|> toEqual({
"l1": {
"nullableOfNullable": Some([|Some("a"), None, Some("b")|]),
"nullableOfNonNullable": None,
},
"l1": expectedObject,
"l2": {
"frag1": {
"nullableOfNullable": Some([|Some("a"), None, Some("b")|]),
"nullableOfNonNullable": None,
},
"frag2": {
"nullableOfNullable": Some([|Some("a"), None, Some("b")|]),
"nullableOfNonNullable": None,
},
"frag1": expectedObject,
"frag2": expectedObject,
},
"l3": [|"a", "b", "c", "d", "e"|],
})
);

test("Removes @bsField from query output", () =>
MyQuery.query |> Js.String.includes("@bsField") |> expect |> toBe(false)
);
});
});
8 changes: 7 additions & 1 deletion tests_bucklescript/__tests__/fragmentDefinition.rei
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
type record = {
nullableOfNullable: option(array(option(string))),
nullableOfNonNullable: option(array(string)),
};

module Fragments: {
module ListFragment: {
type t = {
Expand Down Expand Up @@ -33,6 +38,7 @@ module MyQuery: {
"nullableOfNonNullable": option(array(string)),
},
},
"l3": array(string),
};

let make:
Expand All @@ -52,4 +58,4 @@ module MyQuery: {
"variables": Js.Json.t,
};
let makeVariables: unit => Js.Json.t;
};
};
44 changes: 41 additions & 3 deletions tests_native/fragment_definition.re
Original file line number Diff line number Diff line change
@@ -1,11 +1,38 @@
open Test_shared;

type record = {
nullableOfNullable: option(array(option(string))),
nullableOfNonNullable: option(array(string)),
};

let concat = ({nullableOfNullable, nullableOfNonNullable}) => {
let x = switch (nullableOfNullable) {
| None => [||]
| Some(arr) => arr |> Array.map(v => switch(v) {
| None => [||]
| Some(s) => [|s|]
}) |> Array.to_list |> Array.concat
};

let y = switch (nullableOfNonNullable) {
| None => [||]
| Some(a) => a
};

Array.append(x, y);
};

module Fragments = [%graphql
{|
fragment listFragment on Lists {
nullableOfNullable
nullableOfNonNullable
}

fragment concatFragment on Lists @bsRecord @bsDecoder(fn: "concat") {
nullableOfNullable
nullableOfNonNullable
}
|}
];

Expand All @@ -26,6 +53,10 @@ module MyQuery = [%graphql
...Fragments.ListFragment @bsField(name: "frag1")
...Fragments.ListFragment @bsField(name: "frag2")
}

l3: lists {
...Fragments.ConcatFragment
}
}
|}
];
Expand All @@ -38,6 +69,7 @@ type qt = {
frag1: ft,
frag2: ft,
},
l3: array(string)
};

let print_fragment = (formatter, obj: ft) =>
Expand Down Expand Up @@ -84,7 +116,8 @@ let my_query: module Alcotest.TESTABLE with type t = qt =
let equal = (a, b) =>
fragment_equal(a#l1, b#l1)
&& fragment_equal(a#l2#frag1, b#l2#frag1)
&& fragment_equal(a#l2#frag2, b#l2#frag2);
&& fragment_equal(a#l2#frag2, b#l2#frag2)
&& a#l3 == b#l3;
});

let decodes_the_fragment = () =>
Expand All @@ -96,7 +129,11 @@ let decodes_the_fragment = () =>
{|
{
"l1": {"nullableOfNullable": ["a", null, "b"]},
"l2": {"nullableOfNullable": ["a", null, "b"]}
"l2": {"nullableOfNullable": ["a", null, "b"]},
"l3": {
"nullableOfNullable": ["a", null, "b", null, "c"],
"nullableOfNonNullable": ["d", "e"]
}
}|},
),
),
Expand All @@ -119,7 +156,8 @@ let decodes_the_fragment = () =>
pub nullableOfNullable = Some([|Some("a"), None, Some("b")|]);
pub nullableOfNonNullable = None
}
}
};
pub l3 = [|"a", "b", "c", "d", "e"|]
},
);

Expand Down

0 comments on commit 77d8c45

Please sign in to comment.