Skip to content

Commit

Permalink
Fix fragment variable issues with required variables (#197)
Browse files Browse the repository at this point in the history
  • Loading branch information
jfrolich authored Sep 2, 2020
1 parent a9fe2da commit 5af7a3a
Show file tree
Hide file tree
Showing 23 changed files with 1,153 additions and 91 deletions.
153 changes: 153 additions & 0 deletions graphql_schema.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@ type AdminUser implements User & Name {
name: String!
}

type WorkspaceUser {
id: String!
firstname: String
lastname: String!
}

type Workspace {
id: String!
title: String!
image: String
description: String
user(id: String!): WorkspaceUser!
}

type AnonymousUser implements User & Anonymous {
id: ID!
anonymousId: Int!
Expand Down
1 change: 1 addition & 0 deletions src/base/graphql_ast.re
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ type operation = {
};

type fragment = {
fg_variable_definitions: option(spanning(variable_definitions)),
fg_name: spanning(string),
fg_type_condition: spanning(string),
fg_directives: list(spanning(directive)),
Expand Down
77 changes: 77 additions & 0 deletions src/base/graphql_parser_document.re
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,81 @@ let parse_operation_definition = parser =>
}
);

// we need to parse the argumentTypes directive, and produce a
// type from a string.
let parse_string_to_type = str => {
switch (str |> Graphql_lexer.make |> Graphql_lexer.consume) {
| Ok(tokens) =>
switch (parse_type(Graphql_parser.make(tokens))) {
| Ok(type_) => Some(type_.item)
| Error(_) => None
}

| Error(_) => None
};
};

let get_fragment_argument_definitions =
(directives: list(Source_pos.spanning(Graphql_ast.directive))) => {
switch (
directives |> List.find(d => {d.item.d_name.item == "argumentDefinitions"})
) {
| {item: {d_arguments: Some(arguments), _}, span} =>
let arguments =
arguments.item
|> List.fold_left(
acc =>
fun
| (
{item: key, span},
{item: Iv_object(values), span: type_span},
) => {
let type_ =
values
|> List.fold_left(
acc =>
fun
| (
{item: "type", _},
{item: Iv_string(type_), _},
) =>
Some(type_)
| _ => acc,
None,
);
switch (type_) {
| Some(type_) =>
switch (parse_string_to_type(type_)) {
| Some(type_) => [
(
{item: key, span},
{
vd_type: {
item: type_,
span: type_span,
},
vd_default_value: None,
},
),
...acc,
]
| None => acc
}
| _ => acc
};
}
| _ => acc,
[],
);
switch (arguments) {
| [] => None
| arguments => Some({span, item: arguments})
};
| _ => None
| exception Not_found => None
};
};

let parse_fragment_definition = parser =>
Result_ext.(
expect(parser, Graphql_lexer.Name("fragment"))
Expand Down Expand Up @@ -472,6 +547,8 @@ let parse_fragment_definition = parser =>
end_pos(selection_set),
{
fg_name: name,
fg_variable_definitions:
get_fragment_argument_definitions(directives),
fg_type_condition: type_cond,
fg_directives: directives,
fg_selection_set: selection_set,
Expand Down
49 changes: 5 additions & 44 deletions src/base/result_decoder.re
Original file line number Diff line number Diff line change
Expand Up @@ -807,43 +807,6 @@ let unify_operation = (error_marker, config) =>
)
};

let getFragmentArgumentDefinitions =
(directives: list(Source_pos.spanning(Graphql_ast.directive))) => {
switch (
directives |> List.find(d => {d.item.d_name.item == "argumentDefinitions"})
) {
| {item: {d_arguments: Some(arguments), _}, _} =>
arguments.item
|> List.fold_left(
acc =>
fun
| (
{item: key, span},
{item: Iv_object(values), span: type_span},
) => {
let type_ =
values
|> List.fold_left(
acc =>
fun
| ({item: "type", _}, {item: Iv_string(type_), _}) =>
Some(type_)
| _ => acc,
None,
);
switch (type_) {
| Some(type_) => [(key, type_, span, type_span), ...acc]
| _ => acc
};
}
| _ => acc,
[],
)
| _ => []
| exception Not_found => []
};
};

type query_config = {
schema: option(string),
records: option(bool),
Expand Down Expand Up @@ -1169,15 +1132,14 @@ let rec unify_document_schema = document => {

let is_record = has_directive(~prepend=true, "Record", fg_directives);

let argumentDefinitions =
getFragmentArgumentDefinitions(fg_directives);
let argumentDefinitions = fg.item.fg_variable_definitions;

(
switch (Schema.lookup_type(config.schema, fg_type_condition.item)) {
| None =>
Def_fragment({
name: fg_name.item,
req_vars: argumentDefinitions,
variable_definitions: argumentDefinitions,
has_error: true,
fragment: fg,
type_name: None,
Expand Down Expand Up @@ -1205,14 +1167,13 @@ let rec unify_document_schema = document => {
Some(fg_selection_set),
);

let argumentDefinitions =
getFragmentArgumentDefinitions(fg_directives);
let argumentDefinitions = fg.item.fg_variable_definitions;

switch (with_decoder) {
| Error(err) =>
Def_fragment({
name: fg_name.item,
req_vars: argumentDefinitions,
variable_definitions: argumentDefinitions,
has_error: true,
fragment: fg,
type_name: existing_record,
Expand All @@ -1221,7 +1182,7 @@ let rec unify_document_schema = document => {
| Ok(decoder) =>
Def_fragment({
name: fg_name.item,
req_vars: argumentDefinitions,
variable_definitions: argumentDefinitions,
has_error: error_marker.has_error,
fragment: fg,
type_name: existing_record,
Expand Down
4 changes: 0 additions & 4 deletions src/base/result_decoder.rei
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
let getFragmentArgumentDefinitions:
list(Source_pos.spanning(Graphql_ast.directive)) =>
list((string, string, Source_pos.span, Source_pos.span));

type query_config = {
schema: option(string),
records: option(bool),
Expand Down
3 changes: 2 additions & 1 deletion src/base/result_structure.re
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ and t =
type definition =
| Def_fragment({
name: string,
req_vars: list((string, string, Source_pos.span, Source_pos.span)),
variable_definitions:
option(Source_pos.spanning(Graphql_ast.variable_definitions)),
has_error: bool,
fragment: Source_pos.spanning(Graphql_ast.fragment),
type_name: option(string), // decodes to a custom type (ppxAs)
Expand Down
3 changes: 2 additions & 1 deletion src/base/result_structure.rei
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ and t =
type definition =
| Def_fragment({
name: string,
req_vars: list((string, string, Source_pos.span, Source_pos.span)),
variable_definitions:
option(Source_pos.spanning(Graphql_ast.variable_definitions)),
has_error: bool,
fragment: Source_pos.spanning(Graphql_ast.fragment),
type_name: option(string), // decodes to a custom type (ppxAs)
Expand Down
Loading

0 comments on commit 5af7a3a

Please sign in to comment.