@@ -6,6 +6,7 @@ defmodule GraphQL.Execution.Executor do
6
6
# {:ok, %{hello: "world"}}
7
7
"""
8
8
9
+ alias GraphQL.Execution.ExecutionContext
9
10
alias GraphQL.Type.ObjectType
10
11
alias GraphQL.Type.List
11
12
alias GraphQL.Type.Interface
@@ -26,60 +27,19 @@ defmodule GraphQL.Execution.Executor do
26
27
"""
27
28
@ spec execute ( GraphQL.Schema . t , GraphQL.Document . t , map , map , String . t ) :: result_data | { :error , % { errors: list } }
28
29
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 )
30
31
case context . errors do
31
32
[ ] -> execute_operation ( context , context . operation , root_value )
32
33
_ -> { :error , % { errors: Enum . dedup ( context . errors ) } }
33
34
end
34
35
end
35
36
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
-
50
37
@ type operation :: % {
51
38
kind: :OperationDefintion ,
52
39
operation: atom
53
40
}
54
41
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 }
83
43
defp execute_operation ( context , operation , root_value ) do
84
44
type = operation_root_type ( context . schema , operation )
85
45
% { fields: fields } = collect_fields ( context , type , operation . selectionSet )
@@ -118,12 +78,12 @@ defmodule GraphQL.Execution.Executor do
118
78
end
119
79
end
120
80
121
- @ spec execute_fields ( context , atom | Map , any , any ) :: any
81
+ @ spec execute_fields ( ExecutionContext . t , atom | Map , any , any ) :: any
122
82
defp execute_fields ( context , parent_type , source_value , fields ) when is_atom ( parent_type ) do
123
83
execute_fields ( context , apply ( parent_type , :type , [ ] ) , source_value , fields )
124
84
end
125
85
126
- @ spec execute_fields ( context , atom | Map , any , any ) :: any
86
+ @ spec execute_fields ( ExecutionContext . t , atom | Map , any , any ) :: any
127
87
defp execute_fields ( context , parent_type , source_value , fields ) do
128
88
Enum . reduce fields , % { } , fn ( { field_name_ast , field_asts } , results ) ->
129
89
case resolve_field ( context , parent_type , source_value , field_asts ) do
@@ -133,7 +93,7 @@ defmodule GraphQL.Execution.Executor do
133
93
end
134
94
end
135
95
136
- @ spec execute_fields_serially ( context , atom , map , any ) :: any
96
+ @ spec execute_fields_serially ( ExecutionContext . t , atom , map , any ) :: any
137
97
defp execute_fields_serially ( context , parent_type , source_value , fields ) do
138
98
# call execute_fields because no async operations yet
139
99
execute_fields ( context , parent_type , source_value , fields )
@@ -188,7 +148,7 @@ defmodule GraphQL.Execution.Executor do
188
148
189
149
defp complete_value ( _ , _ , _ , _ , nil ) , do: nil
190
150
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
192
152
defp complete_value ( context , % ObjectType { } = return_type , field_asts , _info , result ) do
193
153
sub_field_asts = collect_sub_fields ( context , return_type , field_asts )
194
154
execute_fields ( context , return_type , result , sub_field_asts . fields )
@@ -198,20 +158,20 @@ defmodule GraphQL.Execution.Executor do
198
158
complete_value ( context , % NonNull { ofType: apply ( inner_type , :type , [ ] ) } , field_asts , info , result )
199
159
end
200
160
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
202
162
defp complete_value ( context , % NonNull { ofType: inner_type } , field_asts , info , result ) do
203
163
# TODO: Null Checking
204
164
complete_value ( context , inner_type , field_asts , info , result )
205
165
end
206
166
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
208
168
defp complete_value ( context , % Interface { } = return_type , field_asts , info , result ) do
209
169
runtime_type = AbstractType . get_object_type ( return_type , result , info . schema )
210
170
sub_field_asts = collect_sub_fields ( context , runtime_type , field_asts )
211
171
execute_fields ( context , runtime_type , result , sub_field_asts . fields )
212
172
end
213
173
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
215
175
defp complete_value ( context , % Union { } = return_type , field_asts , info , result ) do
216
176
runtime_type = AbstractType . get_object_type ( return_type , result , info . schema )
217
177
sub_field_asts = collect_sub_fields ( context , runtime_type , field_asts )
@@ -222,7 +182,7 @@ defmodule GraphQL.Execution.Executor do
222
182
complete_value ( context , % List { ofType: apply ( list_type , :type , [ ] ) } , field_asts , info , result )
223
183
end
224
184
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
226
186
defp complete_value ( context , % List { ofType: list_type } , field_asts , info , result ) do
227
187
Enum . map result , fn ( item ) ->
228
188
complete_value_catching_error ( context , list_type , field_asts , info , item )
0 commit comments