graphql 1.6.8 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql.rb +5 -0
- data/lib/graphql/analysis/analyze_query.rb +21 -17
- data/lib/graphql/argument.rb +6 -2
- data/lib/graphql/backtrace.rb +50 -0
- data/lib/graphql/backtrace/inspect_result.rb +51 -0
- data/lib/graphql/backtrace/table.rb +120 -0
- data/lib/graphql/backtrace/traced_error.rb +55 -0
- data/lib/graphql/backtrace/tracer.rb +50 -0
- data/lib/graphql/enum_type.rb +1 -10
- data/lib/graphql/execution.rb +1 -2
- data/lib/graphql/execution/execute.rb +98 -89
- data/lib/graphql/execution/flatten.rb +40 -0
- data/lib/graphql/execution/lazy/resolve.rb +7 -7
- data/lib/graphql/execution/multiplex.rb +29 -29
- data/lib/graphql/field.rb +5 -1
- data/lib/graphql/internal_representation/node.rb +16 -0
- data/lib/graphql/invalid_name_error.rb +11 -0
- data/lib/graphql/language/parser.rb +11 -5
- data/lib/graphql/language/parser.y +11 -5
- data/lib/graphql/name_validator.rb +16 -0
- data/lib/graphql/object_type.rb +5 -0
- data/lib/graphql/query.rb +28 -7
- data/lib/graphql/query/context.rb +155 -52
- data/lib/graphql/query/literal_input.rb +36 -9
- data/lib/graphql/query/null_context.rb +7 -1
- data/lib/graphql/query/result.rb +63 -0
- data/lib/graphql/query/serial_execution/field_resolution.rb +3 -4
- data/lib/graphql/query/serial_execution/value_resolution.rb +3 -4
- data/lib/graphql/query/variables.rb +1 -1
- data/lib/graphql/schema.rb +31 -0
- data/lib/graphql/schema/traversal.rb +16 -1
- data/lib/graphql/schema/warden.rb +40 -4
- data/lib/graphql/static_validation/validator.rb +20 -18
- data/lib/graphql/subscriptions.rb +129 -0
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +122 -0
- data/lib/graphql/subscriptions/event.rb +52 -0
- data/lib/graphql/subscriptions/instrumentation.rb +68 -0
- data/lib/graphql/tracing.rb +80 -0
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +31 -0
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -1
- data/spec/graphql/analysis/analyze_query_spec.rb +19 -0
- data/spec/graphql/argument_spec.rb +28 -0
- data/spec/graphql/backtrace_spec.rb +144 -0
- data/spec/graphql/define/assign_argument_spec.rb +12 -0
- data/spec/graphql/enum_type_spec.rb +1 -1
- data/spec/graphql/execution/execute_spec.rb +66 -0
- data/spec/graphql/execution/lazy_spec.rb +4 -3
- data/spec/graphql/language/parser_spec.rb +16 -0
- data/spec/graphql/object_type_spec.rb +14 -0
- data/spec/graphql/query/context_spec.rb +134 -27
- data/spec/graphql/query/result_spec.rb +29 -0
- data/spec/graphql/query/variables_spec.rb +13 -0
- data/spec/graphql/query_spec.rb +22 -0
- data/spec/graphql/schema/build_from_definition_spec.rb +2 -0
- data/spec/graphql/schema/traversal_spec.rb +70 -12
- data/spec/graphql/schema/warden_spec.rb +67 -1
- data/spec/graphql/schema_spec.rb +29 -0
- data/spec/graphql/static_validation/validator_spec.rb +16 -0
- data/spec/graphql/subscriptions_spec.rb +331 -0
- data/spec/graphql/tracing/active_support_notifications_tracing_spec.rb +57 -0
- data/spec/graphql/tracing_spec.rb +47 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/star_wars/schema.rb +39 -0
- metadata +27 -4
- data/lib/graphql/execution/field_result.rb +0 -54
- data/lib/graphql/execution/selection_result.rb +0 -90
data/lib/graphql/enum_type.rb
CHANGED
@@ -141,13 +141,7 @@ module GraphQL
|
|
141
141
|
|
142
142
|
def name=(new_name)
|
143
143
|
# Validate that the name is correct
|
144
|
-
|
145
|
-
raise(
|
146
|
-
GraphQL::EnumType::InvalidEnumNameError,
|
147
|
-
"Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but '#{new_name}' does not"
|
148
|
-
)
|
149
|
-
end
|
150
|
-
|
144
|
+
GraphQL::NameValidator.validate!(new_name)
|
151
145
|
@name = new_name
|
152
146
|
end
|
153
147
|
end
|
@@ -155,9 +149,6 @@ module GraphQL
|
|
155
149
|
class UnresolvedValueError < GraphQL::Error
|
156
150
|
end
|
157
151
|
|
158
|
-
class InvalidEnumNameError < GraphQL::Error
|
159
|
-
end
|
160
|
-
|
161
152
|
private
|
162
153
|
|
163
154
|
# Get the underlying value for this enum value
|
data/lib/graphql/execution.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "graphql/execution/directive_checks"
|
3
3
|
require "graphql/execution/execute"
|
4
|
-
require "graphql/execution/
|
4
|
+
require "graphql/execution/flatten"
|
5
5
|
require "graphql/execution/lazy"
|
6
6
|
require "graphql/execution/multiplex"
|
7
|
-
require "graphql/execution/selection_result"
|
8
7
|
require "graphql/execution/typecast"
|
@@ -13,104 +13,126 @@ module GraphQL
|
|
13
13
|
SKIP = Skip.new
|
14
14
|
|
15
15
|
# @api private
|
16
|
-
|
16
|
+
class PropagateNull
|
17
|
+
end
|
18
|
+
# @api private
|
19
|
+
PROPAGATE_NULL = PropagateNull.new
|
17
20
|
|
18
21
|
def execute(ast_operation, root_type, query)
|
19
|
-
result =
|
20
|
-
|
21
|
-
|
22
|
-
query.irep_selection,
|
23
|
-
query.context,
|
24
|
-
mutation: query.mutation?
|
25
|
-
)
|
26
|
-
|
27
|
-
GraphQL::Execution::Lazy.resolve(result)
|
28
|
-
|
29
|
-
result.to_h
|
22
|
+
result = resolve_root_selection(query)
|
23
|
+
lazy_resolve_root_selection(result, {query: query})
|
24
|
+
GraphQL::Execution::Flatten.call(query.context)
|
30
25
|
end
|
31
26
|
|
32
27
|
# @api private
|
33
28
|
module ExecutionFunctions
|
34
29
|
module_function
|
35
30
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
query_ctx
|
31
|
+
def resolve_root_selection(query)
|
32
|
+
GraphQL::Tracing.trace("execute_query", query: query) do
|
33
|
+
operation = query.selected_operation
|
34
|
+
op_type = operation.operation_type
|
35
|
+
root_type = query.root_type_for_operation(op_type)
|
36
|
+
resolve_selection(
|
37
|
+
query.root_value,
|
38
|
+
root_type,
|
39
|
+
query.context,
|
40
|
+
mutation: query.mutation?
|
47
41
|
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def lazy_resolve_root_selection(result, query: nil, queries: nil)
|
46
|
+
if query.nil? && queries.length == 1
|
47
|
+
query = queries[0]
|
48
|
+
end
|
49
|
+
|
50
|
+
GraphQL::Tracing.trace("execute_query_lazy", {queries: queries, query: query}) do
|
51
|
+
GraphQL::Execution::Lazy.resolve(result)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def resolve_selection(object, current_type, current_ctx, mutation: false )
|
56
|
+
# Assign this _before_ resolving the children
|
57
|
+
# so that when a child propagates null, the selection result is
|
58
|
+
# ready for it.
|
59
|
+
current_ctx.value = {}
|
60
|
+
|
61
|
+
selections_on_type = current_ctx.irep_node.typed_children[current_type]
|
62
|
+
|
63
|
+
selections_on_type.each do |name, child_irep_node|
|
64
|
+
field_ctx = current_ctx.spawn_child(
|
65
|
+
key: name,
|
66
|
+
object: object,
|
67
|
+
irep_node: child_irep_node,
|
68
|
+
)
|
69
|
+
|
70
|
+
field_result = GraphQL::Tracing.trace("execute_field", { context: field_ctx }) do
|
71
|
+
resolve_field(
|
72
|
+
object,
|
73
|
+
field_ctx
|
74
|
+
)
|
75
|
+
end
|
48
76
|
|
49
77
|
if field_result.is_a?(Skip)
|
50
78
|
next
|
51
79
|
end
|
52
80
|
|
53
81
|
if mutation
|
54
|
-
GraphQL::Execution::Lazy.resolve(
|
82
|
+
GraphQL::Execution::Lazy.resolve(field_ctx)
|
55
83
|
end
|
56
84
|
|
57
|
-
selection_result.set(name, field_result)
|
58
85
|
|
59
86
|
# If the last subselection caused a null to propagate to _this_ selection,
|
60
87
|
# then we may as well quit executing fields because they
|
61
88
|
# won't be in the response
|
62
|
-
if
|
89
|
+
if current_ctx.invalid_null?
|
63
90
|
break
|
91
|
+
else
|
92
|
+
current_ctx.value[name] = field_ctx
|
64
93
|
end
|
65
94
|
end
|
66
95
|
|
67
|
-
|
96
|
+
current_ctx.value
|
68
97
|
end
|
69
98
|
|
70
|
-
def resolve_field(
|
71
|
-
query =
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
key: selection.name,
|
76
|
-
selection: selection,
|
77
|
-
)
|
99
|
+
def resolve_field(object, field_ctx)
|
100
|
+
query = field_ctx.query
|
101
|
+
irep_node = field_ctx.irep_node
|
102
|
+
parent_type = irep_node.owner_type
|
103
|
+
field = field_ctx.field
|
78
104
|
|
79
105
|
raw_value = begin
|
80
|
-
arguments = query.arguments_for(
|
81
|
-
|
106
|
+
arguments = query.arguments_for(irep_node, field)
|
107
|
+
field_ctx.schema.middleware.invoke([parent_type, object, field, arguments, field_ctx])
|
82
108
|
rescue GraphQL::ExecutionError => err
|
83
109
|
err
|
84
110
|
end
|
85
111
|
|
86
|
-
|
87
|
-
|
88
|
-
|
112
|
+
# If the returned object is lazy (unfinished),
|
113
|
+
# assign the lazy object to `.value=` so we can resolve it later.
|
114
|
+
# When we resolve it later, reassign it to `.value=` so that
|
115
|
+
# the finished value replaces the unfinished one.
|
116
|
+
#
|
117
|
+
# If the returned object is finished, continue to coerce
|
118
|
+
# and resolve child fields
|
119
|
+
if query.schema.lazy?(raw_value)
|
120
|
+
field_ctx.value = field.prepare_lazy(raw_value, arguments, field_ctx).then { |inner_value|
|
121
|
+
field_ctx.value = continue_resolve_field(inner_value, field_ctx)
|
89
122
|
}
|
90
123
|
elsif raw_value.is_a?(GraphQL::Execution::Lazy)
|
91
124
|
# It came from a connection resolve, assume it was already instrumented
|
92
|
-
raw_value.then { |inner_value|
|
93
|
-
continue_resolve_field(
|
125
|
+
field_ctx.value = raw_value.then { |inner_value|
|
126
|
+
field_ctx.value = continue_resolve_field(inner_value, field_ctx)
|
94
127
|
}
|
95
128
|
else
|
96
|
-
continue_resolve_field(
|
97
|
-
end
|
98
|
-
|
99
|
-
case result
|
100
|
-
when PROPAGATE_NULL, GraphQL::Execution::Lazy, SelectionResult
|
101
|
-
FieldResult.new(
|
102
|
-
owner: owner,
|
103
|
-
type: field.type,
|
104
|
-
value: result,
|
105
|
-
)
|
106
|
-
else
|
107
|
-
result
|
129
|
+
field_ctx.value = continue_resolve_field(raw_value, field_ctx)
|
108
130
|
end
|
109
131
|
end
|
110
132
|
|
111
|
-
def continue_resolve_field(
|
112
|
-
if
|
113
|
-
return
|
133
|
+
def continue_resolve_field(raw_value, field_ctx)
|
134
|
+
if field_ctx.parent.invalid_null?
|
135
|
+
return nil
|
114
136
|
end
|
115
137
|
query = field_ctx.query
|
116
138
|
|
@@ -131,19 +153,18 @@ module GraphQL
|
|
131
153
|
end
|
132
154
|
|
133
155
|
resolve_value(
|
134
|
-
owner,
|
135
|
-
parent_type,
|
136
|
-
field,
|
137
|
-
field.type,
|
138
156
|
raw_value,
|
139
|
-
|
157
|
+
field_ctx.type,
|
140
158
|
field_ctx,
|
141
159
|
)
|
142
160
|
end
|
143
161
|
|
144
|
-
def resolve_value(
|
162
|
+
def resolve_value(value, field_type, field_ctx)
|
163
|
+
field_defn = field_ctx.field
|
164
|
+
|
145
165
|
if value.nil?
|
146
166
|
if field_type.kind.non_null?
|
167
|
+
parent_type = field_ctx.irep_node.owner_type
|
147
168
|
type_error = GraphQL::InvalidNullError.new(parent_type, field_defn, value)
|
148
169
|
field_ctx.schema.type_error(type_error, field_ctx)
|
149
170
|
PROPAGATE_NULL
|
@@ -157,55 +178,46 @@ module GraphQL
|
|
157
178
|
nil
|
158
179
|
end
|
159
180
|
elsif value.is_a?(Skip)
|
160
|
-
value
|
181
|
+
field_ctx.value = value
|
161
182
|
else
|
162
183
|
case field_type.kind
|
163
|
-
when GraphQL::TypeKinds::SCALAR
|
164
|
-
field_type.coerce_result(value, field_ctx)
|
165
|
-
when GraphQL::TypeKinds::ENUM
|
184
|
+
when GraphQL::TypeKinds::SCALAR, GraphQL::TypeKinds::ENUM
|
166
185
|
field_type.coerce_result(value, field_ctx)
|
167
186
|
when GraphQL::TypeKinds::LIST
|
168
187
|
inner_type = field_type.of_type
|
169
188
|
i = 0
|
170
189
|
result = []
|
190
|
+
field_ctx.value = result
|
191
|
+
|
171
192
|
value.each do |inner_value|
|
172
|
-
inner_ctx = field_ctx.
|
193
|
+
inner_ctx = field_ctx.spawn_child(
|
173
194
|
key: i,
|
174
|
-
|
175
|
-
|
176
|
-
field: field_defn,
|
195
|
+
object: inner_value,
|
196
|
+
irep_node: field_ctx.irep_node,
|
177
197
|
)
|
178
198
|
|
179
199
|
inner_result = resolve_value(
|
180
|
-
owner,
|
181
|
-
parent_type,
|
182
|
-
field_defn,
|
183
|
-
inner_type,
|
184
200
|
inner_value,
|
185
|
-
|
201
|
+
inner_type,
|
186
202
|
inner_ctx,
|
187
203
|
)
|
188
204
|
|
189
|
-
|
205
|
+
inner_ctx.value = inner_result
|
206
|
+
result << inner_ctx
|
190
207
|
i += 1
|
191
208
|
end
|
192
209
|
result
|
193
210
|
when GraphQL::TypeKinds::NON_NULL
|
194
|
-
|
211
|
+
inner_type = field_type.of_type
|
195
212
|
resolve_value(
|
196
|
-
owner,
|
197
|
-
parent_type,
|
198
|
-
field_defn,
|
199
|
-
wrapped_type,
|
200
213
|
value,
|
201
|
-
|
214
|
+
inner_type,
|
202
215
|
field_ctx,
|
203
216
|
)
|
204
217
|
when GraphQL::TypeKinds::OBJECT
|
205
218
|
resolve_selection(
|
206
219
|
value,
|
207
220
|
field_type,
|
208
|
-
selection,
|
209
221
|
field_ctx
|
210
222
|
)
|
211
223
|
when GraphQL::TypeKinds::UNION, GraphQL::TypeKinds::INTERFACE
|
@@ -214,17 +226,14 @@ module GraphQL
|
|
214
226
|
possible_types = query.possible_types(field_type)
|
215
227
|
|
216
228
|
if !possible_types.include?(resolved_type)
|
229
|
+
parent_type = field_ctx.irep_node.owner_type
|
217
230
|
type_error = GraphQL::UnresolvedTypeError.new(value, field_defn, parent_type, resolved_type, possible_types)
|
218
231
|
field_ctx.schema.type_error(type_error, field_ctx)
|
219
232
|
PROPAGATE_NULL
|
220
233
|
else
|
221
234
|
resolve_value(
|
222
|
-
owner,
|
223
|
-
parent_type,
|
224
|
-
field_defn,
|
225
|
-
resolved_type,
|
226
235
|
value,
|
227
|
-
|
236
|
+
resolved_type,
|
228
237
|
field_ctx,
|
229
238
|
)
|
230
239
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Execution
|
4
|
+
# Starting from a root context,
|
5
|
+
# create a hash out of the context tree.
|
6
|
+
# @api private
|
7
|
+
module Flatten
|
8
|
+
def self.call(ctx)
|
9
|
+
flatten(ctx)
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
private
|
14
|
+
|
15
|
+
def flatten(obj)
|
16
|
+
case obj
|
17
|
+
when Hash
|
18
|
+
flattened = {}
|
19
|
+
obj.each do |key, val|
|
20
|
+
flattened[key] = flatten(val)
|
21
|
+
end
|
22
|
+
flattened
|
23
|
+
when Array
|
24
|
+
obj.map { |v| flatten(v) }
|
25
|
+
when Query::Context::SharedMethods
|
26
|
+
if obj.invalid_null?
|
27
|
+
nil
|
28
|
+
elsif obj.skipped? && obj.value.empty?
|
29
|
+
nil
|
30
|
+
else
|
31
|
+
flatten(obj.value)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
obj
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -36,10 +36,10 @@ module GraphQL
|
|
36
36
|
Lazy::NullResult
|
37
37
|
else
|
38
38
|
Lazy.new {
|
39
|
-
acc.each_with_index { |
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
acc.each_with_index { |ctx, idx|
|
40
|
+
acc[idx] = GraphQL::Tracing.trace("execute_field_lazy", { context: ctx }) do
|
41
|
+
ctx.value.value
|
42
|
+
end
|
43
43
|
}
|
44
44
|
resolve_in_place(acc)
|
45
45
|
}
|
@@ -52,7 +52,7 @@ module GraphQL
|
|
52
52
|
# @return [void]
|
53
53
|
def self.each_lazy(acc, value)
|
54
54
|
case value
|
55
|
-
when
|
55
|
+
when Hash
|
56
56
|
value.each do |key, field_result|
|
57
57
|
acc = each_lazy(acc, field_result)
|
58
58
|
end
|
@@ -60,12 +60,12 @@ module GraphQL
|
|
60
60
|
value.each do |field_result|
|
61
61
|
acc = each_lazy(acc, field_result)
|
62
62
|
end
|
63
|
-
when
|
63
|
+
when Query::Context::SharedMethods
|
64
64
|
field_value = value.value
|
65
65
|
case field_value
|
66
66
|
when Lazy
|
67
67
|
acc = acc << value
|
68
|
-
when
|
68
|
+
when Enumerable # shortcut for Hash & Array
|
69
69
|
acc = each_lazy(acc, field_value)
|
70
70
|
end
|
71
71
|
end
|
@@ -46,19 +46,21 @@ module GraphQL
|
|
46
46
|
# @param max_complexity [Integer, nil]
|
47
47
|
# @return [Array<Hash>] One result per query
|
48
48
|
def run_queries(schema, queries, context: {}, max_complexity: schema.max_complexity)
|
49
|
-
|
50
|
-
|
51
|
-
if
|
52
|
-
|
49
|
+
multiplex = self.new(schema: schema, queries: queries, context: context)
|
50
|
+
GraphQL::Tracing.trace("execute_multiplex", { multiplex: multiplex }) do
|
51
|
+
if has_custom_strategy?(schema)
|
52
|
+
if queries.length != 1
|
53
|
+
raise ArgumentError, "Multiplexing doesn't support custom execution strategies, run one query at a time instead"
|
54
|
+
else
|
55
|
+
with_instrumentation(multiplex, max_complexity: max_complexity) do
|
56
|
+
[run_one_legacy(schema, queries.first)]
|
57
|
+
end
|
58
|
+
end
|
53
59
|
else
|
54
|
-
with_instrumentation(
|
55
|
-
|
60
|
+
with_instrumentation(multiplex, max_complexity: max_complexity) do
|
61
|
+
run_as_multiplex(queries)
|
56
62
|
end
|
57
63
|
end
|
58
|
-
else
|
59
|
-
with_instrumentation(schema, queries, context: context, max_complexity: max_complexity) do
|
60
|
-
run_as_multiplex(queries)
|
61
|
-
end
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
@@ -71,12 +73,14 @@ module GraphQL
|
|
71
73
|
end
|
72
74
|
|
73
75
|
# Then, work through lazy results in a breadth-first way
|
74
|
-
GraphQL::Execution::
|
76
|
+
GraphQL::Execution::Execute::ExecutionFunctions.lazy_resolve_root_selection(results, { queries: queries })
|
75
77
|
|
76
78
|
# Then, find all errors and assign the result to the query object
|
77
79
|
results.each_with_index.map do |data_result, idx|
|
78
80
|
query = queries[idx]
|
79
81
|
finish_query(data_result, query)
|
82
|
+
# Get the Query::Result, not the Hash
|
83
|
+
query.result
|
80
84
|
end
|
81
85
|
end
|
82
86
|
|
@@ -88,18 +92,10 @@ module GraphQL
|
|
88
92
|
NO_OPERATION
|
89
93
|
else
|
90
94
|
begin
|
91
|
-
|
92
|
-
root_type = query.root_type_for_operation(op_type)
|
93
|
-
GraphQL::Execution::Execute::ExecutionFunctions.resolve_selection(
|
94
|
-
query.root_value,
|
95
|
-
root_type,
|
96
|
-
query.irep_selection,
|
97
|
-
query.context,
|
98
|
-
mutation: query.mutation?
|
99
|
-
)
|
95
|
+
GraphQL::Execution::Execute::ExecutionFunctions.resolve_root_selection(query)
|
100
96
|
rescue GraphQL::ExecutionError => err
|
101
97
|
query.context.errors << err
|
102
|
-
|
98
|
+
NO_OPERATION
|
103
99
|
end
|
104
100
|
end
|
105
101
|
end
|
@@ -109,17 +105,20 @@ module GraphQL
|
|
109
105
|
# @return [Hash] final result of this query, including all values and errors
|
110
106
|
def finish_query(data_result, query)
|
111
107
|
# Assign the result so that it can be accessed in instrumentation
|
112
|
-
query.
|
108
|
+
query.result_values = if data_result.equal?(NO_OPERATION)
|
113
109
|
if !query.valid?
|
114
110
|
{ "errors" => query.static_errors.map(&:to_h) }
|
115
111
|
else
|
116
|
-
|
112
|
+
data_result
|
117
113
|
end
|
118
114
|
else
|
119
|
-
|
120
|
-
|
115
|
+
# Use `context.value` which was assigned during execution
|
116
|
+
result = {
|
117
|
+
"data" => Execution::Flatten.call(query.context)
|
118
|
+
}
|
121
119
|
|
122
|
-
if
|
120
|
+
if query.context.errors.any?
|
121
|
+
error_result = query.context.errors.map(&:to_h)
|
123
122
|
result["errors"] = error_result
|
124
123
|
end
|
125
124
|
|
@@ -129,7 +128,7 @@ module GraphQL
|
|
129
128
|
|
130
129
|
# use the old `query_execution_strategy` etc to run this query
|
131
130
|
def run_one_legacy(schema, query)
|
132
|
-
query.
|
131
|
+
query.result_values = if !query.valid?
|
133
132
|
all_errors = query.validation_errors + query.analysis_errors + query.context.errors
|
134
133
|
if all_errors.any?
|
135
134
|
{ "errors" => all_errors.map(&:to_h) }
|
@@ -150,10 +149,11 @@ module GraphQL
|
|
150
149
|
# Apply multiplex & query instrumentation to `queries`.
|
151
150
|
#
|
152
151
|
# It yields when the queries should be executed, then runs teardown.
|
153
|
-
def with_instrumentation(
|
152
|
+
def with_instrumentation(multiplex, max_complexity:)
|
153
|
+
schema = multiplex.schema
|
154
|
+
queries = multiplex.queries
|
154
155
|
query_instrumenters = schema.instrumenters[:query]
|
155
156
|
multiplex_instrumenters = schema.instrumenters[:multiplex]
|
156
|
-
multiplex = self.new(schema: schema, queries: queries, context: context)
|
157
157
|
|
158
158
|
# First, run multiplex instrumentation, then query instrumentation for each query
|
159
159
|
multiplex_instrumenters.each { |i| i.before_multiplex(multiplex) }
|