graphql 2.3.3 → 2.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/generators/graphql/install/mutation_root_generator.rb +2 -2
- data/lib/graphql/analysis/ast/query_complexity.rb +1 -1
- data/lib/graphql/dataloader/async_dataloader.rb +1 -0
- data/lib/graphql/dataloader/null_dataloader.rb +1 -1
- data/lib/graphql/dataloader.rb +6 -3
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +7 -4
- data/lib/graphql/execution/interpreter/runtime.rb +52 -63
- data/lib/graphql/execution/interpreter.rb +1 -1
- data/lib/graphql/language/nodes.rb +60 -26
- data/lib/graphql/language/parser.rb +56 -15
- data/lib/graphql/query.rb +2 -2
- data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
- data/lib/graphql/schema/addition.rb +21 -11
- data/lib/graphql/schema/has_single_input_argument.rb +1 -0
- data/lib/graphql/schema/input_object.rb +1 -0
- data/lib/graphql/schema/introspection_system.rb +2 -2
- data/lib/graphql/schema/late_bound_type.rb +4 -0
- data/lib/graphql/schema/list.rb +2 -2
- data/lib/graphql/schema/member/has_arguments.rb +2 -35
- data/lib/graphql/schema/member/has_directives.rb +1 -1
- data/lib/graphql/schema/member/relay_shortcuts.rb +1 -1
- data/lib/graphql/schema/member/type_system_helpers.rb +1 -2
- data/lib/graphql/schema/warden.rb +2 -3
- data/lib/graphql/schema.rb +20 -20
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +1 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +1 -1
- data/lib/graphql/tracing/prometheus_trace.rb +8 -8
- data/lib/graphql/tracing/sentry_trace.rb +10 -10
- data/lib/graphql/type_kinds.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +0 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5f20ae656aec8f5ad77a6edd73103d2f5a25511ae3c9b515c5b0c58ecc91cac
|
4
|
+
data.tar.gz: 6b51f66b0f2188c292b34c61e367de84cb37a7894e536b5b8105a95ec60b9c64
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96bd289b9d880438ed2c7610b3a7008cb793fd4551191fcf084c0f947c3da195e07f07346e0b2c9b88177fdbeed098591508879756d7f5919c53c9576f5548e8
|
7
|
+
data.tar.gz: ce92d82eee23a710b66f3d29bdc29690b2e368f42ddfd60b159708dac0b018024a87bbf6069d8274878e98e0821f223b0cd2fafba41c23afab86dc7faa97328c
|
@@ -9,7 +9,7 @@ module Graphql
|
|
9
9
|
class MutationRootGenerator < Rails::Generators::Base
|
10
10
|
include Core
|
11
11
|
|
12
|
-
desc "Create mutation base type, mutation root
|
12
|
+
desc "Create mutation base type, mutation root type, and adds the latter to the schema"
|
13
13
|
source_root File.expand_path('../templates', __FILE__)
|
14
14
|
|
15
15
|
class_option :schema,
|
@@ -31,4 +31,4 @@ module Graphql
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
34
|
-
end
|
34
|
+
end
|
@@ -8,7 +8,7 @@ module GraphQL
|
|
8
8
|
# simple internal code while adding the option to add Dataloader.
|
9
9
|
class NullDataloader < Dataloader
|
10
10
|
# These are all no-ops because code was
|
11
|
-
# executed
|
11
|
+
# executed synchronously.
|
12
12
|
def run; end
|
13
13
|
def run_isolated; yield; end
|
14
14
|
def yield
|
data/lib/graphql/dataloader.rb
CHANGED
@@ -88,6 +88,11 @@ module GraphQL
|
|
88
88
|
nil
|
89
89
|
end
|
90
90
|
|
91
|
+
# This method is called when Dataloader is finished using a fiber.
|
92
|
+
# Use it to perform any cleanup, such as releasing database connections (if required manually)
|
93
|
+
def cleanup_fiber
|
94
|
+
end
|
95
|
+
|
91
96
|
# Get a Source instance from this dataloader, for calling `.load(...)` or `.request(...)` on.
|
92
97
|
#
|
93
98
|
# @param source_class [Class<GraphQL::Dataloader::Source]
|
@@ -231,9 +236,7 @@ module GraphQL
|
|
231
236
|
Fiber.new(blocking: !@nonblocking) {
|
232
237
|
set_fiber_variables(fiber_vars)
|
233
238
|
yield
|
234
|
-
|
235
|
-
# if the fiber is allowed to terminate normally, control is passed to the main fiber instead.
|
236
|
-
true
|
239
|
+
cleanup_fiber
|
237
240
|
}
|
238
241
|
end
|
239
242
|
|
@@ -5,7 +5,7 @@ module GraphQL
|
|
5
5
|
class Interpreter
|
6
6
|
class Runtime
|
7
7
|
module GraphQLResult
|
8
|
-
def initialize(result_name, result_type, application_value, parent_result, is_non_null_in_parent)
|
8
|
+
def initialize(result_name, result_type, application_value, parent_result, is_non_null_in_parent, selections, is_eager)
|
9
9
|
@graphql_parent = parent_result
|
10
10
|
@graphql_application_value = application_value
|
11
11
|
@graphql_result_type = result_type
|
@@ -16,6 +16,8 @@ module GraphQL
|
|
16
16
|
@graphql_is_non_null_in_parent = is_non_null_in_parent
|
17
17
|
# Jump through some hoops to avoid creating this duplicate storage if at all possible.
|
18
18
|
@graphql_metadata = nil
|
19
|
+
@graphql_selections = selections
|
20
|
+
@graphql_is_eager = is_eager
|
19
21
|
end
|
20
22
|
|
21
23
|
def path
|
@@ -28,14 +30,15 @@ module GraphQL
|
|
28
30
|
end
|
29
31
|
|
30
32
|
attr_accessor :graphql_dead
|
31
|
-
attr_reader :graphql_parent, :graphql_result_name, :graphql_is_non_null_in_parent,
|
33
|
+
attr_reader :graphql_parent, :graphql_result_name, :graphql_is_non_null_in_parent,
|
34
|
+
:graphql_application_value, :graphql_result_type, :graphql_selections, :graphql_is_eager
|
32
35
|
|
33
36
|
# @return [Hash] Plain-Ruby result data (`@graphql_metadata` contains Result wrapper objects)
|
34
37
|
attr_accessor :graphql_result_data
|
35
38
|
end
|
36
39
|
|
37
40
|
class GraphQLResultHash
|
38
|
-
def initialize(_result_name, _result_type, _application_value, _parent_result, _is_non_null_in_parent)
|
41
|
+
def initialize(_result_name, _result_type, _application_value, _parent_result, _is_non_null_in_parent, _selections, _is_eager)
|
39
42
|
super
|
40
43
|
@graphql_result_data = {}
|
41
44
|
end
|
@@ -123,7 +126,7 @@ module GraphQL
|
|
123
126
|
class GraphQLResultArray
|
124
127
|
include GraphQLResult
|
125
128
|
|
126
|
-
def initialize(_result_name, _result_type, _application_value, _parent_result, _is_non_null_in_parent)
|
129
|
+
def initialize(_result_name, _result_type, _application_value, _parent_result, _is_non_null_in_parent, _selections, _is_eager)
|
127
130
|
super
|
128
131
|
@graphql_result_data = []
|
129
132
|
end
|
@@ -65,16 +65,6 @@ module GraphQL
|
|
65
65
|
"#<#{self.class.name} response=#{@response.inspect}>"
|
66
66
|
end
|
67
67
|
|
68
|
-
def tap_or_each(obj_or_array)
|
69
|
-
if obj_or_array.is_a?(Array)
|
70
|
-
obj_or_array.each do |item|
|
71
|
-
yield(item, true)
|
72
|
-
end
|
73
|
-
else
|
74
|
-
yield(obj_or_array, false)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
68
|
# This _begins_ the execution. Some deferred work
|
79
69
|
# might be stored up in lazies.
|
80
70
|
# @return [void]
|
@@ -84,7 +74,8 @@ module GraphQL
|
|
84
74
|
root_type = schema.root_type_for_operation(root_op_type)
|
85
75
|
runtime_object = root_type.wrap(query.root_value, context)
|
86
76
|
runtime_object = schema.sync_lazy(runtime_object)
|
87
|
-
|
77
|
+
is_eager = root_op_type == "mutation"
|
78
|
+
@response = GraphQLResultHash.new(nil, root_type, runtime_object, nil, false, root_operation.selections, is_eager)
|
88
79
|
st = get_current_runtime_state
|
89
80
|
st.current_result = @response
|
90
81
|
|
@@ -93,17 +84,9 @@ module GraphQL
|
|
93
84
|
@response = nil
|
94
85
|
else
|
95
86
|
call_method_on_directives(:resolve, runtime_object, root_operation.directives) do # execute query level directives
|
96
|
-
|
97
|
-
# This is kind of a hack -- `gathered_selections` is an Array if any of the selections
|
98
|
-
# require isolation during execution (because of runtime directives). In that case,
|
99
|
-
# make a new, isolated result hash for writing the result into. (That isolated response
|
100
|
-
# is eventually merged back into the main response)
|
101
|
-
#
|
102
|
-
# Otherwise, `gathered_selections` is a hash of selections which can be
|
103
|
-
# directly evaluated and the results can be written right into the main response hash.
|
104
|
-
tap_or_each(gathered_selections) do |selections, is_selection_array|
|
87
|
+
each_gathered_selections(@response) do |selections, is_selection_array|
|
105
88
|
if is_selection_array
|
106
|
-
selection_response = GraphQLResultHash.new(nil, root_type, runtime_object, nil, false)
|
89
|
+
selection_response = GraphQLResultHash.new(nil, root_type, runtime_object, nil, false, selections, is_eager)
|
107
90
|
final_response = @response
|
108
91
|
else
|
109
92
|
selection_response = @response
|
@@ -112,12 +95,10 @@ module GraphQL
|
|
112
95
|
|
113
96
|
@dataloader.append_job {
|
114
97
|
evaluate_selections(
|
115
|
-
root_op_type == "mutation",
|
116
98
|
selections,
|
117
99
|
selection_response,
|
118
100
|
final_response,
|
119
101
|
nil,
|
120
|
-
nil,
|
121
102
|
)
|
122
103
|
}
|
123
104
|
end
|
@@ -126,8 +107,18 @@ module GraphQL
|
|
126
107
|
nil
|
127
108
|
end
|
128
109
|
|
129
|
-
def
|
110
|
+
def each_gathered_selections(response_hash)
|
111
|
+
gathered_selections = gather_selections(response_hash.graphql_application_value, response_hash.graphql_result_type, response_hash.graphql_selections)
|
112
|
+
if gathered_selections.is_a?(Array)
|
113
|
+
gathered_selections.each do |item|
|
114
|
+
yield(item, true)
|
115
|
+
end
|
116
|
+
else
|
117
|
+
yield(gathered_selections, false)
|
118
|
+
end
|
119
|
+
end
|
130
120
|
|
121
|
+
def gather_selections(owner_object, owner_type, selections, selections_to_run = nil, selections_by_name = {})
|
131
122
|
selections.each do |node|
|
132
123
|
# Skip gathering this if the directive says so
|
133
124
|
if !directives_include?(node, owner_object, owner_type)
|
@@ -139,7 +130,7 @@ module GraphQL
|
|
139
130
|
selections = selections_by_name[response_key]
|
140
131
|
# if there was already a selection of this field,
|
141
132
|
# use an array to hold all selections,
|
142
|
-
#
|
133
|
+
# otherwise, use the single node to represent the selection
|
143
134
|
if selections
|
144
135
|
# This field was already selected at least once,
|
145
136
|
# add this node to the list of selections
|
@@ -172,17 +163,26 @@ module GraphQL
|
|
172
163
|
type_defn = schema.get_type(node.type.name, context)
|
173
164
|
|
174
165
|
if query.warden.possible_types(type_defn).include?(owner_type)
|
175
|
-
gather_selections(owner_object, owner_type, node.selections, selections_to_run, next_selections)
|
166
|
+
result = gather_selections(owner_object, owner_type, node.selections, selections_to_run, next_selections)
|
167
|
+
if !result.equal?(next_selections)
|
168
|
+
selections_to_run = result
|
169
|
+
end
|
176
170
|
end
|
177
171
|
else
|
178
172
|
# it's an untyped fragment, definitely continue
|
179
|
-
gather_selections(owner_object, owner_type, node.selections, selections_to_run, next_selections)
|
173
|
+
result = gather_selections(owner_object, owner_type, node.selections, selections_to_run, next_selections)
|
174
|
+
if !result.equal?(next_selections)
|
175
|
+
selections_to_run = result
|
176
|
+
end
|
180
177
|
end
|
181
178
|
when GraphQL::Language::Nodes::FragmentSpread
|
182
179
|
fragment_def = query.fragments[node.name]
|
183
180
|
type_defn = query.get_type(fragment_def.type.name)
|
184
181
|
if query.warden.possible_types(type_defn).include?(owner_type)
|
185
|
-
gather_selections(owner_object, owner_type, fragment_def.selections, selections_to_run, next_selections)
|
182
|
+
result = gather_selections(owner_object, owner_type, fragment_def.selections, selections_to_run, next_selections)
|
183
|
+
if !result.equal?(next_selections)
|
184
|
+
selections_to_run = result
|
185
|
+
end
|
186
186
|
end
|
187
187
|
else
|
188
188
|
raise "Invariant: unexpected selection class: #{node.class}"
|
@@ -195,7 +195,7 @@ module GraphQL
|
|
195
195
|
NO_ARGS = GraphQL::EmptyObjects::EMPTY_HASH
|
196
196
|
|
197
197
|
# @return [void]
|
198
|
-
def evaluate_selections(
|
198
|
+
def evaluate_selections(gathered_selections, selections_result, target_result, runtime_state) # rubocop:disable Metrics/ParameterLists
|
199
199
|
runtime_state ||= get_current_runtime_state
|
200
200
|
runtime_state.current_result_name = nil
|
201
201
|
runtime_state.current_result = selections_result
|
@@ -210,7 +210,7 @@ module GraphQL
|
|
210
210
|
gathered_selections.each do |result_name, field_ast_nodes_or_ast_node|
|
211
211
|
@dataloader.append_job {
|
212
212
|
evaluate_selection(
|
213
|
-
result_name, field_ast_nodes_or_ast_node,
|
213
|
+
result_name, field_ast_nodes_or_ast_node, selections_result
|
214
214
|
)
|
215
215
|
finished_jobs += 1
|
216
216
|
if target_result && finished_jobs == enqueued_jobs
|
@@ -220,7 +220,7 @@ module GraphQL
|
|
220
220
|
# Field resolution may pause the fiber,
|
221
221
|
# so it wouldn't get to the `Resolve` call that happens below.
|
222
222
|
# So instead trigger a run from this outer context.
|
223
|
-
if
|
223
|
+
if selections_result.graphql_is_eager
|
224
224
|
@dataloader.clear_cache
|
225
225
|
@dataloader.run
|
226
226
|
@dataloader.clear_cache
|
@@ -231,7 +231,7 @@ module GraphQL
|
|
231
231
|
end
|
232
232
|
|
233
233
|
# @return [void]
|
234
|
-
def evaluate_selection(result_name, field_ast_nodes_or_ast_node,
|
234
|
+
def evaluate_selection(result_name, field_ast_nodes_or_ast_node, selections_result) # rubocop:disable Metrics/ParameterLists
|
235
235
|
return if selections_result.graphql_dead
|
236
236
|
# As a performance optimization, the hash key will be a `Node` if
|
237
237
|
# there's only one selection of the field. But if there are multiple
|
@@ -258,28 +258,27 @@ module GraphQL
|
|
258
258
|
owner_object = field_defn.owner.wrap(owner_object, context)
|
259
259
|
end
|
260
260
|
|
261
|
-
return_type = field_defn.type
|
262
261
|
if !field_defn.any_arguments?
|
263
262
|
resolved_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
|
264
263
|
if field_defn.extras.size == 0
|
265
264
|
evaluate_selection_with_resolved_keyword_args(
|
266
|
-
NO_ARGS, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_object,
|
265
|
+
NO_ARGS, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_object, result_name, selections_result, runtime_state
|
267
266
|
)
|
268
267
|
else
|
269
|
-
evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_object,
|
268
|
+
evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_object, result_name, selections_result, runtime_state)
|
270
269
|
end
|
271
270
|
else
|
272
271
|
@query.arguments_cache.dataload_for(ast_node, field_defn, owner_object) do |resolved_arguments|
|
273
272
|
runtime_state = get_current_runtime_state # This might be in a different fiber
|
274
|
-
evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_object,
|
273
|
+
evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_object, result_name, selections_result, runtime_state)
|
275
274
|
end
|
276
275
|
end
|
277
276
|
end
|
278
277
|
|
279
|
-
def evaluate_selection_with_args(arguments, field_defn, ast_node, field_ast_nodes, object,
|
278
|
+
def evaluate_selection_with_args(arguments, field_defn, ast_node, field_ast_nodes, object, result_name, selection_result, runtime_state) # rubocop:disable Metrics/ParameterLists
|
280
279
|
after_lazy(arguments, field: field_defn, ast_node: ast_node, owner_object: object, arguments: arguments, result_name: result_name, result: selection_result, runtime_state: runtime_state) do |resolved_arguments, runtime_state|
|
281
|
-
return_type_non_null = return_type.non_null?
|
282
280
|
if resolved_arguments.is_a?(GraphQL::ExecutionError) || resolved_arguments.is_a?(GraphQL::UnauthorizedError)
|
281
|
+
return_type_non_null = field_defn.type.non_null?
|
283
282
|
continue_value(resolved_arguments, field_defn, return_type_non_null, ast_node, result_name, selection_result)
|
284
283
|
next
|
285
284
|
end
|
@@ -318,7 +317,8 @@ module GraphQL
|
|
318
317
|
# to the keyword args hash _before_ freezing everything.
|
319
318
|
extra_args[:argument_details] = :__arguments_add_self
|
320
319
|
when :parent
|
321
|
-
|
320
|
+
parent_result = selection_result.graphql_parent
|
321
|
+
extra_args[:parent] = parent_result&.graphql_application_value&.object
|
322
322
|
else
|
323
323
|
extra_args[extra] = field_defn.fetch_extra(extra, context)
|
324
324
|
end
|
@@ -329,11 +329,11 @@ module GraphQL
|
|
329
329
|
resolved_arguments.keyword_arguments
|
330
330
|
end
|
331
331
|
|
332
|
-
evaluate_selection_with_resolved_keyword_args(kwarg_arguments, resolved_arguments, field_defn, ast_node, field_ast_nodes, object,
|
332
|
+
evaluate_selection_with_resolved_keyword_args(kwarg_arguments, resolved_arguments, field_defn, ast_node, field_ast_nodes, object, result_name, selection_result, runtime_state)
|
333
333
|
end
|
334
334
|
end
|
335
335
|
|
336
|
-
def evaluate_selection_with_resolved_keyword_args(kwarg_arguments, resolved_arguments, field_defn, ast_node, field_ast_nodes, object,
|
336
|
+
def evaluate_selection_with_resolved_keyword_args(kwarg_arguments, resolved_arguments, field_defn, ast_node, field_ast_nodes, object, result_name, selection_result, runtime_state) # rubocop:disable Metrics/ParameterLists
|
337
337
|
runtime_state.current_field = field_defn
|
338
338
|
runtime_state.current_arguments = resolved_arguments
|
339
339
|
runtime_state.current_result_name = result_name
|
@@ -376,7 +376,8 @@ module GraphQL
|
|
376
376
|
end
|
377
377
|
after_lazy(app_result, field: field_defn, ast_node: ast_node, owner_object: object, arguments: resolved_arguments, result_name: result_name, result: selection_result, runtime_state: runtime_state) do |inner_result, runtime_state|
|
378
378
|
owner_type = selection_result.graphql_result_type
|
379
|
-
|
379
|
+
return_type = field_defn.type
|
380
|
+
continue_value = continue_value(inner_result, field_defn, return_type.non_null?, ast_node, result_name, selection_result)
|
380
381
|
if HALT != continue_value
|
381
382
|
was_scoped = runtime_state.was_authorized_by_scope_items
|
382
383
|
runtime_state.was_authorized_by_scope_items = nil
|
@@ -387,7 +388,7 @@ module GraphQL
|
|
387
388
|
# If this field is a root mutation field, immediately resolve
|
388
389
|
# all of its child fields before moving on to the next root mutation field.
|
389
390
|
# (Subselections of this mutation will still be resolved level-by-level.)
|
390
|
-
if
|
391
|
+
if selection_result.graphql_is_eager
|
391
392
|
Interpreter::Resolve.resolve_all([field_result], @dataloader)
|
392
393
|
end
|
393
394
|
end
|
@@ -599,21 +600,11 @@ module GraphQL
|
|
599
600
|
after_lazy(object_proxy, ast_node: ast_node, field: field, owner_object: owner_object, arguments: arguments, trace: false, result_name: result_name, result: selection_result, runtime_state: runtime_state) do |inner_object, runtime_state|
|
600
601
|
continue_value = continue_value(inner_object, field, is_non_null, ast_node, result_name, selection_result)
|
601
602
|
if HALT != continue_value
|
602
|
-
response_hash = GraphQLResultHash.new(result_name, current_type, continue_value, selection_result, is_non_null)
|
603
|
+
response_hash = GraphQLResultHash.new(result_name, current_type, continue_value, selection_result, is_non_null, next_selections, false)
|
603
604
|
set_result(selection_result, result_name, response_hash, true, is_non_null)
|
604
|
-
|
605
|
-
gathered_selections = gather_selections(continue_value, current_type, next_selections)
|
606
|
-
# There are two possibilities for `gathered_selections`:
|
607
|
-
# 1. All selections of this object should be evaluated together (there are no runtime directives modifying execution).
|
608
|
-
# This case is handled below, and the result can be written right into the main `response_hash` above.
|
609
|
-
# In this case, `gathered_selections` is a hash of selections.
|
610
|
-
# 2. Some selections of this object have runtime directives that may or may not modify execution.
|
611
|
-
# That part of the selection is evaluated in an isolated way, writing into a sub-response object which is
|
612
|
-
# eventually merged into the final response. In this case, `gathered_selections` is an array of things to run in isolation.
|
613
|
-
# (Technically, it's possible that one of those entries _doesn't_ require isolation.)
|
614
|
-
tap_or_each(gathered_selections) do |selections, is_selection_array|
|
605
|
+
each_gathered_selections(response_hash) do |selections, is_selection_array|
|
615
606
|
if is_selection_array
|
616
|
-
this_result = GraphQLResultHash.new(result_name, current_type, continue_value, selection_result, is_non_null)
|
607
|
+
this_result = GraphQLResultHash.new(result_name, current_type, continue_value, selection_result, is_non_null, selections, false)
|
617
608
|
final_result = response_hash
|
618
609
|
else
|
619
610
|
this_result = response_hash
|
@@ -621,11 +612,9 @@ module GraphQL
|
|
621
612
|
end
|
622
613
|
|
623
614
|
evaluate_selections(
|
624
|
-
false,
|
625
615
|
selections,
|
626
616
|
this_result,
|
627
617
|
final_result,
|
628
|
-
owner_object.object,
|
629
618
|
runtime_state,
|
630
619
|
)
|
631
620
|
end
|
@@ -636,7 +625,7 @@ module GraphQL
|
|
636
625
|
# This is true for objects, unions, and interfaces
|
637
626
|
use_dataloader_job = !inner_type.unwrap.kind.input?
|
638
627
|
inner_type_non_null = inner_type.non_null?
|
639
|
-
response_list = GraphQLResultArray.new(result_name, current_type,
|
628
|
+
response_list = GraphQLResultArray.new(result_name, current_type, owner_object, selection_result, is_non_null, next_selections, false)
|
640
629
|
set_result(selection_result, result_name, response_list, true, is_non_null)
|
641
630
|
idx = nil
|
642
631
|
list_value = begin
|
@@ -646,10 +635,10 @@ module GraphQL
|
|
646
635
|
idx += 1
|
647
636
|
if use_dataloader_job
|
648
637
|
@dataloader.append_job do
|
649
|
-
resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list,
|
638
|
+
resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, owner_type, was_scoped, runtime_state)
|
650
639
|
end
|
651
640
|
else
|
652
|
-
resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list,
|
641
|
+
resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, owner_type, was_scoped, runtime_state)
|
653
642
|
end
|
654
643
|
end
|
655
644
|
|
@@ -680,7 +669,7 @@ module GraphQL
|
|
680
669
|
end
|
681
670
|
end
|
682
671
|
|
683
|
-
def resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list,
|
672
|
+
def resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, owner_type, was_scoped, runtime_state) # rubocop:disable Metrics/ParameterLists
|
684
673
|
runtime_state.current_result_name = this_idx
|
685
674
|
runtime_state.current_result = response_list
|
686
675
|
call_method_on_directives(:resolve_each, owner_object, ast_node.directives) do
|
@@ -688,7 +677,7 @@ module GraphQL
|
|
688
677
|
after_lazy(inner_value, ast_node: ast_node, field: field, owner_object: owner_object, arguments: arguments, result_name: this_idx, result: response_list, runtime_state: runtime_state) do |inner_inner_value, runtime_state|
|
689
678
|
continue_value = continue_value(inner_inner_value, field, inner_type_non_null, ast_node, this_idx, response_list)
|
690
679
|
if HALT != continue_value
|
691
|
-
continue_field(continue_value, owner_type, field, inner_type, ast_node,
|
680
|
+
continue_field(continue_value, owner_type, field, inner_type, ast_node, response_list.graphql_selections, false, owner_object, arguments, this_idx, response_list, was_scoped, runtime_state)
|
692
681
|
end
|
693
682
|
end
|
694
683
|
end
|
@@ -20,7 +20,7 @@ module GraphQL
|
|
20
20
|
# @param queries [Array<GraphQL::Query, Hash>]
|
21
21
|
# @param context [Hash]
|
22
22
|
# @param max_complexity [Integer, nil]
|
23
|
-
# @return [Array<
|
23
|
+
# @return [Array<GraphQL::Query::Result>] One result per query
|
24
24
|
def run_all(schema, query_options, context: {}, max_complexity: schema.max_complexity)
|
25
25
|
queries = query_options.map do |opts|
|
26
26
|
case opts
|
@@ -20,6 +20,15 @@ module GraphQL
|
|
20
20
|
@definition_line = definition_line
|
21
21
|
super(**_rest)
|
22
22
|
end
|
23
|
+
|
24
|
+
def marshal_dump
|
25
|
+
super << @definition_line
|
26
|
+
end
|
27
|
+
|
28
|
+
def marshal_load(values)
|
29
|
+
@definition_line = values.pop
|
30
|
+
super
|
31
|
+
end
|
23
32
|
end
|
24
33
|
|
25
34
|
attr_reader :filename
|
@@ -265,6 +274,8 @@ module GraphQL
|
|
265
274
|
]
|
266
275
|
|
267
276
|
def generate_initialize
|
277
|
+
return if method_defined?(:marshal_load, false) # checking for `:initialize` doesn't work right
|
278
|
+
|
268
279
|
scalar_method_names = @scalar_methods
|
269
280
|
# TODO: These probably should be scalar methods, but `types` returns an array
|
270
281
|
[:types, :description].each do |extra_method|
|
@@ -273,18 +284,20 @@ module GraphQL
|
|
273
284
|
end
|
274
285
|
end
|
275
286
|
|
276
|
-
|
287
|
+
children_method_names = @children_methods.keys
|
288
|
+
|
289
|
+
all_method_names = scalar_method_names + children_method_names
|
277
290
|
if all_method_names.include?(:alias)
|
278
291
|
# Rather than complicating this special case,
|
279
292
|
# let it be overridden (in field)
|
280
293
|
return
|
281
294
|
else
|
282
295
|
arguments = scalar_method_names.map { |m| "#{m}: nil"} +
|
283
|
-
|
296
|
+
children_method_names.map { |m| "#{m}: NO_CHILDREN" } +
|
284
297
|
DEFAULT_INITIALIZE_OPTIONS
|
285
298
|
|
286
299
|
assignments = scalar_method_names.map { |m| "@#{m} = #{m}"} +
|
287
|
-
|
300
|
+
children_method_names.map { |m| "@#{m} = #{m}.freeze" }
|
288
301
|
|
289
302
|
if name.end_with?("Definition") && name != "FragmentDefinition"
|
290
303
|
arguments << "definition_pos: nil"
|
@@ -292,7 +305,7 @@ module GraphQL
|
|
292
305
|
end
|
293
306
|
|
294
307
|
keywords = scalar_method_names.map { |m| "#{m}: #{m}"} +
|
295
|
-
|
308
|
+
children_method_names.map { |m| "#{m}: #{m}" }
|
296
309
|
|
297
310
|
module_eval <<-RUBY, __FILE__, __LINE__
|
298
311
|
def initialize(#{arguments.join(", ")})
|
@@ -304,9 +317,21 @@ module GraphQL
|
|
304
317
|
#{assignments.join("\n")}
|
305
318
|
end
|
306
319
|
|
307
|
-
def self.from_a(filename, line, col, #{
|
320
|
+
def self.from_a(filename, line, col, #{all_method_names.join(", ")})
|
308
321
|
self.new(filename: filename, line: line, col: col, #{keywords.join(", ")})
|
309
322
|
end
|
323
|
+
|
324
|
+
def marshal_dump
|
325
|
+
[
|
326
|
+
line, col, # use methods here to force them to be calculated
|
327
|
+
@filename,
|
328
|
+
#{all_method_names.map { |n| "@#{n}," }.join}
|
329
|
+
]
|
330
|
+
end
|
331
|
+
|
332
|
+
def marshal_load(values)
|
333
|
+
@line, @col, @filename #{all_method_names.map { |n| ", @#{n}"}.join} = values
|
334
|
+
end
|
310
335
|
RUBY
|
311
336
|
end
|
312
337
|
end
|
@@ -369,16 +394,6 @@ module GraphQL
|
|
369
394
|
|
370
395
|
# A single selection in a GraphQL query.
|
371
396
|
class Field < AbstractNode
|
372
|
-
scalar_methods :name, :alias
|
373
|
-
children_methods({
|
374
|
-
arguments: GraphQL::Language::Nodes::Argument,
|
375
|
-
selections: GraphQL::Language::Nodes::Field,
|
376
|
-
directives: GraphQL::Language::Nodes::Directive,
|
377
|
-
})
|
378
|
-
|
379
|
-
# @!attribute selections
|
380
|
-
# @return [Array<Nodes::Field>] Selections on this object (or empty array if this is a scalar field)
|
381
|
-
|
382
397
|
def initialize(name: nil, arguments: NONE, directives: NONE, selections: NONE, field_alias: nil, line: nil, col: nil, pos: nil, filename: nil, source: nil)
|
383
398
|
@name = name
|
384
399
|
@arguments = arguments || NONE
|
@@ -397,24 +412,27 @@ module GraphQL
|
|
397
412
|
self.new(filename: filename, line: line, col: col, field_alias: field_alias, name: name, arguments: arguments, directives: directives, selections: selections)
|
398
413
|
end
|
399
414
|
|
400
|
-
|
401
|
-
|
402
|
-
|
415
|
+
def marshal_dump
|
416
|
+
[line, col, @filename, @name, @arguments, @directives, @selections, @alias]
|
417
|
+
end
|
403
418
|
|
404
|
-
|
405
|
-
|
406
|
-
|
419
|
+
def marshal_load(values)
|
420
|
+
@line, @col, @filename, @name, @arguments, @directives, @selections, @alias = values
|
421
|
+
end
|
422
|
+
|
423
|
+
scalar_methods :name, :alias
|
407
424
|
children_methods({
|
425
|
+
arguments: GraphQL::Language::Nodes::Argument,
|
408
426
|
selections: GraphQL::Language::Nodes::Field,
|
409
427
|
directives: GraphQL::Language::Nodes::Directive,
|
410
428
|
})
|
411
429
|
|
412
|
-
|
413
|
-
|
414
|
-
|
430
|
+
# Override this because default is `:fields`
|
431
|
+
self.children_method_name = :selections
|
432
|
+
end
|
415
433
|
|
416
|
-
|
417
|
-
|
434
|
+
# A reusable fragment, defined at document-level.
|
435
|
+
class FragmentDefinition < AbstractNode
|
418
436
|
def initialize(name: nil, type: nil, directives: NONE, selections: NONE, filename: nil, pos: nil, source: nil, line: nil, col: nil)
|
419
437
|
@name = name
|
420
438
|
@type = type
|
@@ -430,6 +448,22 @@ module GraphQL
|
|
430
448
|
def self.from_a(filename, line, col, name, type, directives, selections)
|
431
449
|
self.new(filename: filename, line: line, col: col, name: name, type: type, directives: directives, selections: selections)
|
432
450
|
end
|
451
|
+
|
452
|
+
def marshal_dump
|
453
|
+
[line, col, @filename, @name, @type, @directives, @selections]
|
454
|
+
end
|
455
|
+
|
456
|
+
def marshal_load(values)
|
457
|
+
@line, @col, @filename, @name, @type, @directives, @selections = values
|
458
|
+
end
|
459
|
+
|
460
|
+
scalar_methods :name, :type
|
461
|
+
children_methods({
|
462
|
+
selections: GraphQL::Language::Nodes::Field,
|
463
|
+
directives: GraphQL::Language::Nodes::Directive,
|
464
|
+
})
|
465
|
+
|
466
|
+
self.children_method_name = :definitions
|
433
467
|
end
|
434
468
|
|
435
469
|
# Application of a named fragment in a selection
|