Skip to content
This repository was archived by the owner on Jul 25, 2024. It is now read-only.

Commit 804a9bd

Browse files
author
Josh Price
authored
Merge pull request #96 from graphql-elixir/refactor/executor
Executor refactoring
2 parents 06bea1a + e39d5d8 commit 804a9bd

23 files changed

+560
-401
lines changed

lib/graphql/execution/arguments.ex

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
defmodule GraphQL.Execution.Arguments do
3+
alias GraphQL.Execution.ASTValue
4+
5+
def argument_values(arg_defs, arg_asts, variable_values) do
6+
arg_ast_map = Enum.reduce arg_asts, %{}, fn(arg_ast, result) ->
7+
Map.put(result, String.to_atom(arg_ast.name.value), arg_ast)
8+
end
9+
Enum.reduce(arg_defs, %{}, fn(arg_def, result) ->
10+
{arg_def_name, arg_def_type} = arg_def
11+
value_ast = Map.get(arg_ast_map, arg_def_name)
12+
13+
value = ASTValue.value_from_ast(value_ast, arg_def_type.type, variable_values)
14+
value = if is_nil(value) do
15+
Map.get(arg_def_type, :defaultValue)
16+
else
17+
value
18+
end
19+
if is_nil(value) do
20+
result
21+
else
22+
Map.put(result, arg_def_name, value)
23+
end
24+
end)
25+
end
26+
end

lib/graphql/execution/ast_value.ex

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
2+
defmodule GraphQL.Execution.ASTValue do
3+
alias GraphQL.Type.NonNull
4+
alias GraphQL.Type.List
5+
alias GraphQL.Type.Input
6+
alias GraphQL.Type.NonNull
7+
alias GraphQL.Type.CompositeType
8+
9+
def value_from_ast(value_ast, %NonNull{ofType: inner_type}, variable_values) do
10+
value_from_ast(value_ast, inner_type, variable_values)
11+
end
12+
13+
def value_from_ast(%{value: obj=%{kind: :ObjectValue}}, type=%Input{}, variable_values) do
14+
input_fields = CompositeType.get_fields(type)
15+
field_asts = Enum.reduce(obj.fields, %{}, fn(ast, result) ->
16+
Map.put(result, ast.name.value, ast)
17+
end)
18+
Enum.reduce(Map.keys(input_fields), %{}, fn(field_name, result) ->
19+
field = Map.get(input_fields, field_name)
20+
field_ast = Map.get(field_asts, to_string(field_name)) # this feels... brittle.
21+
inner_result = value_from_ast(field_ast, field.type, variable_values)
22+
case inner_result do
23+
nil -> result
24+
_ -> Map.put(result, field_name, inner_result)
25+
end
26+
end)
27+
end
28+
29+
def value_from_ast(%{value: %{kind: :Variable, name: %{value: value}}}, type, variable_values) do
30+
case Map.get(variable_values, value) do
31+
nil -> nil
32+
variable_value -> GraphQL.Types.parse_value(type, variable_value)
33+
end
34+
end
35+
36+
# if it isn't a variable or object input type, that means it's invalid
37+
# and we shoud return a nil
38+
def value_from_ast(_, %Input{}, _), do: nil
39+
40+
def value_from_ast(%{value: %{kind: :ListValue, values: values_ast}}, type, _) do
41+
GraphQL.Types.parse_value(type, Enum.map(values_ast, fn(value_ast) ->
42+
value_ast.value
43+
end))
44+
end
45+
46+
def value_from_ast(value_ast, %List{ofType: inner_type}, variable_values) do
47+
[value_from_ast(value_ast, inner_type, variable_values)]
48+
end
49+
50+
def value_from_ast(nil, _, _), do: nil # remove once NonNull is actually done..
51+
52+
def value_from_ast(value_ast, type, variable_values) when is_atom(type) do
53+
value_from_ast(value_ast, type.type, variable_values)
54+
end
55+
56+
def value_from_ast(value_ast, type, _) do
57+
GraphQL.Types.parse_literal(type, value_ast.value)
58+
end
59+
end

lib/graphql/execution/completion.ex

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
defprotocol GraphQL.Execution.Completion do
3+
@fallback_to_any true
4+
5+
@spec complete_value(any, ExecutionContext.t, GraphQL.Document.t, map, map) :: {ExecutionContext.t, any}
6+
def complete_value(type, context, field_asts, info, result)
7+
end
8+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
defimpl GraphQL.Execution.Completion, for: Any do
3+
alias GraphQL.Execution.Types
4+
5+
def complete_value(return_type, context, _field_asts, _info, result) do
6+
{context, GraphQL.Types.serialize(Types.unwrap_type(return_type), result)}
7+
end
8+
end
9+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
defimpl GraphQL.Execution.Completion, for: Atom do
2+
alias GraphQL.Execution.Completion
3+
alias GraphQL.Execution.Types
4+
5+
def complete_value(return_type, context, field_asts, info, result) do
6+
Completion.complete_value(Types.unwrap_type(return_type), context, field_asts, info, result)
7+
end
8+
end
9+

lib/graphql/execution/directives.ex

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
defmodule GraphQL.Execution.Directives do
3+
alias GraphQL.Execution.Arguments
4+
5+
def resolve_directive(context, directives, directive_name) do
6+
ast = Enum.find(directives, fn(d) -> d.name.value == Atom.to_string(directive_name) end)
7+
if ast do
8+
directive = apply(GraphQL.Type.Directives, directive_name, [])
9+
%{if: val} = Arguments.argument_values(directive.args, ast.arguments, context.variable_values)
10+
val
11+
else
12+
directive_name == :include
13+
end
14+
end
15+
end

0 commit comments

Comments
 (0)