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

Commit fb7cae3

Browse files
committed
Extracted ExecutionContext module from Executor
1 parent e1b951e commit fb7cae3

File tree

2 files changed

+62
-51
lines changed

2 files changed

+62
-51
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
2+
defmodule GraphQL.Execution.ExecutionContext do
3+
4+
@type operation :: %{
5+
kind: :OperationDefintion,
6+
operation: atom
7+
}
8+
9+
defstruct [:schema, :fragments, :root_value, :operation, :variable_values, :errors]
10+
@type t :: %__MODULE__{
11+
schema: GraphQL.Schema.t,
12+
fragments: struct,
13+
root_value: Map,
14+
operation: Map,
15+
variable_values: Map,
16+
errors: list(GraphQL.Error.t)
17+
}
18+
19+
@spec new(GraphQL.Schema.t, GraphQL.Document.t, map, map, String.t) :: __MODULE__.t
20+
def new(schema, document, root_value, variable_values, operation_name) do
21+
Enum.reduce document.definitions, %__MODULE__{
22+
schema: schema,
23+
fragments: %{},
24+
root_value: root_value,
25+
operation: nil,
26+
variable_values: variable_values || %{}, # TODO: We need to deeply set keys as strings or atoms. not allow both.
27+
errors: []
28+
}, fn(definition, context) ->
29+
30+
case definition do
31+
%{kind: :OperationDefinition} ->
32+
cond do
33+
!operation_name && context.operation ->
34+
report_error(context, "Must provide operation name if query contains multiple operations.")
35+
!operation_name || definition.name.value === operation_name ->
36+
context = %{context | operation: definition}
37+
%{context | variable_values: GraphQL.Execution.Variables.extract(context) }
38+
true -> context
39+
end
40+
%{kind: :FragmentDefinition} ->
41+
put_in(context.fragments[definition.name.value], definition)
42+
end
43+
end
44+
end
45+
46+
@spec report_error(__MODULE__.t, String.t) :: __MODULE__.t
47+
def report_error(context, msg) do
48+
put_in(context.errors, [%{"message" => msg} | context.errors])
49+
end
50+
end
51+

lib/graphql/execution/executor.ex

Lines changed: 11 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ defmodule GraphQL.Execution.Executor do
66
# {:ok, %{hello: "world"}}
77
"""
88

9+
alias GraphQL.Execution.ExecutionContext
910
alias GraphQL.Type.ObjectType
1011
alias GraphQL.Type.List
1112
alias GraphQL.Type.Interface
@@ -26,60 +27,19 @@ defmodule GraphQL.Execution.Executor do
2627
"""
2728
@spec execute(GraphQL.Schema.t, GraphQL.Document.t, map, map, String.t) :: result_data | {:error, %{errors: list}}
2829
def execute(schema, document, root_value \\ %{}, variable_values \\ %{}, operation_name \\ nil) do
29-
context = build_execution_context(schema, document, root_value, variable_values, operation_name)
30+
context = ExecutionContext.new(schema, document, root_value, variable_values, operation_name)
3031
case context.errors do
3132
[] -> execute_operation(context, context.operation, root_value)
3233
_ -> {:error, %{errors: Enum.dedup(context.errors)}}
3334
end
3435
end
3536

36-
@spec report_error(context, String.t) :: context
37-
defp report_error(context, msg) do
38-
put_in(context.errors, [%{"message" => msg} | context.errors])
39-
end
40-
41-
@type context :: %{
42-
schema: GraphQL.Schema.t,
43-
fragments: struct,
44-
root_value: Map,
45-
operation: Map,
46-
variable_values: Map,
47-
errors: list(GraphQL.Error.t)
48-
}
49-
5037
@type operation :: %{
5138
kind: :OperationDefintion,
5239
operation: atom
5340
}
5441

55-
@spec build_execution_context(GraphQL.Schema.t, GraphQL.Document.t, map, map, String.t) :: context
56-
defp build_execution_context(schema, document, root_value, variable_values, operation_name) do
57-
Enum.reduce document.definitions, %{
58-
schema: schema,
59-
fragments: %{},
60-
root_value: root_value,
61-
operation: nil,
62-
variable_values: variable_values || %{}, # TODO: We need to deeply set keys as strings or atoms. not allow both.
63-
errors: []
64-
}, fn(definition, context) ->
65-
66-
case definition do
67-
%{kind: :OperationDefinition} ->
68-
cond do
69-
!operation_name && context.operation ->
70-
report_error(context, "Must provide operation name if query contains multiple operations.")
71-
!operation_name || definition.name.value === operation_name ->
72-
context = %{context | operation: definition}
73-
%{context | variable_values: GraphQL.Execution.Variables.extract(context) }
74-
true -> context
75-
end
76-
%{kind: :FragmentDefinition} ->
77-
put_in(context.fragments[definition.name.value], definition)
78-
end
79-
end
80-
end
81-
82-
@spec execute_operation(context, operation, map) :: result_data | {:error, String.t}
42+
@spec execute_operation(ExecutionContext.t, operation, map) :: result_data | {:error, String.t}
8343
defp execute_operation(context, operation, root_value) do
8444
type = operation_root_type(context.schema, operation)
8545
%{fields: fields} = collect_fields(context, type, operation.selectionSet)
@@ -118,12 +78,12 @@ defmodule GraphQL.Execution.Executor do
11878
end
11979
end
12080

121-
@spec execute_fields(context, atom | Map, any, any) :: any
81+
@spec execute_fields(ExecutionContext.t, atom | Map, any, any) :: any
12282
defp execute_fields(context, parent_type, source_value, fields) when is_atom(parent_type) do
12383
execute_fields(context, apply(parent_type, :type, []), source_value, fields)
12484
end
12585

126-
@spec execute_fields(context, atom | Map, any, any) :: any
86+
@spec execute_fields(ExecutionContext.t, atom | Map, any, any) :: any
12787
defp execute_fields(context, parent_type, source_value, fields) do
12888
Enum.reduce fields, %{}, fn({field_name_ast, field_asts}, results) ->
12989
case resolve_field(context, parent_type, source_value, field_asts) do
@@ -133,7 +93,7 @@ defmodule GraphQL.Execution.Executor do
13393
end
13494
end
13595

136-
@spec execute_fields_serially(context, atom, map, any) :: any
96+
@spec execute_fields_serially(ExecutionContext.t, atom, map, any) :: any
13797
defp execute_fields_serially(context, parent_type, source_value, fields) do
13898
# call execute_fields because no async operations yet
13999
execute_fields(context, parent_type, source_value, fields)
@@ -188,7 +148,7 @@ defmodule GraphQL.Execution.Executor do
188148

189149
defp complete_value(_, _, _, _, nil), do: nil
190150

191-
@spec complete_value(context, %ObjectType{}, GraphQL.Document.t, any, map) :: map
151+
@spec complete_value(ExecutionContext.t, %ObjectType{}, GraphQL.Document.t, any, map) :: map
192152
defp complete_value(context, %ObjectType{} = return_type, field_asts, _info, result) do
193153
sub_field_asts = collect_sub_fields(context, return_type, field_asts)
194154
execute_fields(context, return_type, result, sub_field_asts.fields)
@@ -198,20 +158,20 @@ defmodule GraphQL.Execution.Executor do
198158
complete_value(context, %NonNull{ofType: apply(inner_type, :type, [])}, field_asts, info, result)
199159
end
200160

201-
@spec complete_value(context, %NonNull{}, GraphQL.Document.t, any, any) :: map
161+
@spec complete_value(ExecutionContext.t, %NonNull{}, GraphQL.Document.t, any, any) :: map
202162
defp complete_value(context, %NonNull{ofType: inner_type}, field_asts, info, result) do
203163
# TODO: Null Checking
204164
complete_value(context, inner_type, field_asts, info, result)
205165
end
206166

207-
@spec complete_value(context, %Interface{}, GraphQL.Document.t, any, any) :: map
167+
@spec complete_value(ExecutionContext.t, %Interface{}, GraphQL.Document.t, any, any) :: map
208168
defp complete_value(context, %Interface{} = return_type, field_asts, info, result) do
209169
runtime_type = AbstractType.get_object_type(return_type, result, info.schema)
210170
sub_field_asts = collect_sub_fields(context, runtime_type, field_asts)
211171
execute_fields(context, runtime_type, result, sub_field_asts.fields)
212172
end
213173

214-
@spec complete_value(context, %Union{}, GraphQL.Document.t, any, any) :: map
174+
@spec complete_value(ExecutionContext.t, %Union{}, GraphQL.Document.t, any, any) :: map
215175
defp complete_value(context, %Union{} = return_type, field_asts, info, result) do
216176
runtime_type = AbstractType.get_object_type(return_type, result, info.schema)
217177
sub_field_asts = collect_sub_fields(context, runtime_type, field_asts)
@@ -222,7 +182,7 @@ defmodule GraphQL.Execution.Executor do
222182
complete_value(context, %List{ofType: apply(list_type, :type, [])}, field_asts, info, result)
223183
end
224184

225-
@spec complete_value(context, %List{}, GraphQL.Document.t, any, any) :: map
185+
@spec complete_value(ExecutionContext.t, %List{}, GraphQL.Document.t, any, any) :: map
226186
defp complete_value(context, %List{ofType: list_type}, field_asts, info, result) do
227187
Enum.map result, fn(item) ->
228188
complete_value_catching_error(context, list_type, field_asts, info, item)

0 commit comments

Comments
 (0)