graphql 2.0.21 → 2.0.32
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.
- checksums.yaml +4 -4
- data/lib/generators/graphql/mutation_delete_generator.rb +1 -1
- data/lib/generators/graphql/mutation_update_generator.rb +1 -1
- data/lib/generators/graphql/relay.rb +18 -1
- data/lib/graphql/backtrace.rb +0 -4
- data/lib/graphql/dataloader/source.rb +69 -45
- data/lib/graphql/dataloader.rb +4 -4
- data/lib/graphql/execution/interpreter/arguments_cache.rb +31 -30
- data/lib/graphql/execution/interpreter/runtime.rb +122 -101
- data/lib/graphql/execution/interpreter.rb +1 -2
- data/lib/graphql/execution/lookahead.rb +1 -1
- data/lib/graphql/filter.rb +2 -1
- data/lib/graphql/introspection/entry_points.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +16 -9
- data/lib/graphql/language/lexer.rb +89 -57
- data/lib/graphql/language/nodes.rb +3 -0
- data/lib/graphql/language/parser.rb +706 -691
- data/lib/graphql/language/parser.y +1 -0
- data/lib/graphql/language/printer.rb +28 -14
- data/lib/graphql/language/visitor.rb +64 -61
- data/lib/graphql/query/context.rb +16 -7
- data/lib/graphql/query/null_context.rb +8 -18
- data/lib/graphql/query/validation_pipeline.rb +2 -1
- data/lib/graphql/query.rb +37 -12
- data/lib/graphql/schema/addition.rb +38 -12
- data/lib/graphql/schema/always_visible.rb +10 -0
- data/lib/graphql/schema/argument.rb +8 -10
- data/lib/graphql/schema/build_from_definition.rb +8 -7
- data/lib/graphql/schema/directive.rb +1 -1
- data/lib/graphql/schema/enum_value.rb +2 -2
- data/lib/graphql/schema/field/connection_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +26 -15
- data/lib/graphql/schema/input_object.rb +9 -7
- data/lib/graphql/schema/interface.rb +5 -1
- data/lib/graphql/schema/introspection_system.rb +1 -1
- data/lib/graphql/schema/member/build_type.rb +10 -2
- data/lib/graphql/schema/member/has_arguments.rb +9 -7
- data/lib/graphql/schema/member/has_directives.rb +1 -1
- data/lib/graphql/schema/member/has_fields.rb +1 -1
- data/lib/graphql/schema/member/has_interfaces.rb +1 -1
- data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
- data/lib/graphql/schema/object.rb +6 -1
- data/lib/graphql/schema/printer.rb +3 -1
- data/lib/graphql/schema/relay_classic_mutation.rb +1 -1
- data/lib/graphql/schema/resolver.rb +12 -10
- data/lib/graphql/schema/timeout.rb +1 -1
- data/lib/graphql/schema/validator.rb +1 -1
- data/lib/graphql/schema/warden.rb +37 -4
- data/lib/graphql/schema.rb +92 -23
- data/lib/graphql/tracing/appoptics_trace.rb +35 -11
- data/lib/graphql/tracing/appsignal_trace.rb +4 -0
- data/lib/graphql/tracing/data_dog_trace.rb +89 -50
- data/lib/graphql/tracing/data_dog_tracing.rb +7 -21
- data/lib/graphql/tracing/legacy_trace.rb +5 -1
- data/lib/graphql/tracing/notifications_trace.rb +7 -0
- data/lib/graphql/tracing/platform_trace.rb +26 -12
- data/lib/graphql/tracing/prometheus_trace.rb +4 -0
- data/lib/graphql/tracing/scout_trace.rb +3 -0
- data/lib/graphql/tracing/statsd_trace.rb +4 -0
- data/lib/graphql/tracing.rb +1 -0
- data/lib/graphql/types/relay/connection_behaviors.rb +1 -1
- data/lib/graphql/types/relay/edge_behaviors.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -1
- metadata +36 -24
@@ -131,7 +131,7 @@ module GraphQL
|
|
131
131
|
"$#{variable_identifier.name}".dup
|
132
132
|
end
|
133
133
|
|
134
|
-
def print_schema_definition(schema)
|
134
|
+
def print_schema_definition(schema, extension: false)
|
135
135
|
has_conventional_names = (schema.query.nil? || schema.query == 'Query') &&
|
136
136
|
(schema.mutation.nil? || schema.mutation == 'Mutation') &&
|
137
137
|
(schema.subscription.nil? || schema.subscription == 'Subscription')
|
@@ -140,7 +140,7 @@ module GraphQL
|
|
140
140
|
return
|
141
141
|
end
|
142
142
|
|
143
|
-
out = "schema".dup
|
143
|
+
out = extension ? "extend schema".dup : "schema".dup
|
144
144
|
if schema.directives.any?
|
145
145
|
schema.directives.each do |dir|
|
146
146
|
out << "\n "
|
@@ -164,14 +164,14 @@ module GraphQL
|
|
164
164
|
out
|
165
165
|
end
|
166
166
|
|
167
|
-
def print_scalar_type_definition(scalar_type)
|
168
|
-
out = print_description(scalar_type)
|
167
|
+
def print_scalar_type_definition(scalar_type, extension: false)
|
168
|
+
out = extension ? "extend ".dup : print_description(scalar_type)
|
169
169
|
out << "scalar #{scalar_type.name}"
|
170
170
|
out << print_directives(scalar_type.directives)
|
171
171
|
end
|
172
172
|
|
173
|
-
def print_object_type_definition(object_type)
|
174
|
-
out = print_description(object_type)
|
173
|
+
def print_object_type_definition(object_type, extension: false)
|
174
|
+
out = extension ? "extend ".dup : print_description(object_type)
|
175
175
|
out << "type #{object_type.name}"
|
176
176
|
out << print_implements(object_type) unless object_type.interfaces.empty?
|
177
177
|
out << print_directives(object_type.directives)
|
@@ -210,23 +210,23 @@ module GraphQL
|
|
210
210
|
out << print_directives(field.directives)
|
211
211
|
end
|
212
212
|
|
213
|
-
def print_interface_type_definition(interface_type)
|
214
|
-
out = print_description(interface_type)
|
213
|
+
def print_interface_type_definition(interface_type, extension: false)
|
214
|
+
out = extension ? "extend ".dup : print_description(interface_type)
|
215
215
|
out << "interface #{interface_type.name}"
|
216
216
|
out << print_implements(interface_type) if interface_type.interfaces.any?
|
217
217
|
out << print_directives(interface_type.directives)
|
218
218
|
out << print_field_definitions(interface_type.fields)
|
219
219
|
end
|
220
220
|
|
221
|
-
def print_union_type_definition(union_type)
|
222
|
-
out = print_description(union_type)
|
221
|
+
def print_union_type_definition(union_type, extension: false)
|
222
|
+
out = extension ? "extend ".dup : print_description(union_type)
|
223
223
|
out << "union #{union_type.name}"
|
224
224
|
out << print_directives(union_type.directives)
|
225
225
|
out << " = " + union_type.types.map(&:name).join(" | ")
|
226
226
|
end
|
227
227
|
|
228
|
-
def print_enum_type_definition(enum_type)
|
229
|
-
out = print_description(enum_type)
|
228
|
+
def print_enum_type_definition(enum_type, extension: false)
|
229
|
+
out = extension ? "extend ".dup : print_description(enum_type)
|
230
230
|
out << "enum #{enum_type.name}#{print_directives(enum_type.directives)} {\n"
|
231
231
|
enum_type.values.each.with_index do |value, i|
|
232
232
|
out << print_description(value, indent: ' ', first_in_block: i == 0)
|
@@ -241,8 +241,8 @@ module GraphQL
|
|
241
241
|
out << "\n"
|
242
242
|
end
|
243
243
|
|
244
|
-
def print_input_object_type_definition(input_object_type)
|
245
|
-
out = print_description(input_object_type)
|
244
|
+
def print_input_object_type_definition(input_object_type, extension: false)
|
245
|
+
out = extension ? "extend ".dup : print_description(input_object_type)
|
246
246
|
out << "input #{input_object_type.name}"
|
247
247
|
out << print_directives(input_object_type.directives)
|
248
248
|
if !input_object_type.fields.empty?
|
@@ -347,24 +347,38 @@ module GraphQL
|
|
347
347
|
print_variable_identifier(node)
|
348
348
|
when Nodes::SchemaDefinition
|
349
349
|
print_schema_definition(node)
|
350
|
+
when Nodes::SchemaExtension
|
351
|
+
print_schema_definition(node, extension: true)
|
350
352
|
when Nodes::ScalarTypeDefinition
|
351
353
|
print_scalar_type_definition(node)
|
354
|
+
when Nodes::ScalarTypeExtension
|
355
|
+
print_scalar_type_definition(node, extension: true)
|
352
356
|
when Nodes::ObjectTypeDefinition
|
353
357
|
print_object_type_definition(node)
|
358
|
+
when Nodes::ObjectTypeExtension
|
359
|
+
print_object_type_definition(node, extension: true)
|
354
360
|
when Nodes::InputValueDefinition
|
355
361
|
print_input_value_definition(node)
|
356
362
|
when Nodes::FieldDefinition
|
357
363
|
print_field_definition(node)
|
358
364
|
when Nodes::InterfaceTypeDefinition
|
359
365
|
print_interface_type_definition(node)
|
366
|
+
when Nodes::InterfaceTypeExtension
|
367
|
+
print_interface_type_definition(node, extension: true)
|
360
368
|
when Nodes::UnionTypeDefinition
|
361
369
|
print_union_type_definition(node)
|
370
|
+
when Nodes::UnionTypeExtension
|
371
|
+
print_union_type_definition(node, extension: true)
|
362
372
|
when Nodes::EnumTypeDefinition
|
363
373
|
print_enum_type_definition(node)
|
374
|
+
when Nodes::EnumTypeExtension
|
375
|
+
print_enum_type_definition(node, extension: true)
|
364
376
|
when Nodes::EnumValueDefinition
|
365
377
|
print_enum_value_definition(node)
|
366
378
|
when Nodes::InputObjectTypeDefinition
|
367
379
|
print_input_object_type_definition(node)
|
380
|
+
when Nodes::InputObjectTypeExtension
|
381
|
+
print_input_object_type_definition(node, extension: true)
|
368
382
|
when Nodes::DirectiveDefinition
|
369
383
|
print_directive_definition(node)
|
370
384
|
when FalseClass, Float, Integer, NilClass, String, TrueClass, Symbol
|
@@ -76,67 +76,6 @@ module GraphQL
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
-
# We don't use `alias` here because it breaks `super`
|
80
|
-
def self.make_visit_methods(ast_node_class)
|
81
|
-
node_method = ast_node_class.visit_method
|
82
|
-
children_of_type = ast_node_class.children_of_type
|
83
|
-
child_visit_method = :"#{node_method}_children"
|
84
|
-
|
85
|
-
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
86
|
-
# The default implementation for visiting an AST node.
|
87
|
-
# It doesn't _do_ anything, but it continues to visiting the node's children.
|
88
|
-
# To customize this hook, override one of its make_visit_methods (or the base method?)
|
89
|
-
# in your subclasses.
|
90
|
-
#
|
91
|
-
# For compatibility, it calls hook procs, too.
|
92
|
-
# @param node [GraphQL::Language::Nodes::AbstractNode] the node being visited
|
93
|
-
# @param parent [GraphQL::Language::Nodes::AbstractNode, nil] the previously-visited node, or `nil` if this is the root node.
|
94
|
-
# @return [Array, nil] If there were modifications, it returns an array of new nodes, otherwise, it returns `nil`.
|
95
|
-
def #{node_method}(node, parent)
|
96
|
-
if node.equal?(DELETE_NODE)
|
97
|
-
# This might be passed to `super(DELETE_NODE, ...)`
|
98
|
-
# by a user hook, don't want to keep visiting in that case.
|
99
|
-
[node, parent]
|
100
|
-
else
|
101
|
-
# Run hooks if there are any
|
102
|
-
new_node = node
|
103
|
-
no_hooks = !@visitors.key?(node.class)
|
104
|
-
if no_hooks || begin_visit(new_node, parent)
|
105
|
-
#{
|
106
|
-
if method_defined?(child_visit_method)
|
107
|
-
"new_node = #{child_visit_method}(new_node)"
|
108
|
-
elsif children_of_type
|
109
|
-
children_of_type.map do |child_accessor, child_class|
|
110
|
-
"node.#{child_accessor}.each do |child_node|
|
111
|
-
new_child_and_node = #{child_class.visit_method}_with_modifications(child_node, new_node)
|
112
|
-
# Reassign `node` in case the child hook makes a modification
|
113
|
-
if new_child_and_node.is_a?(Array)
|
114
|
-
new_node = new_child_and_node[1]
|
115
|
-
end
|
116
|
-
end"
|
117
|
-
end.join("\n")
|
118
|
-
else
|
119
|
-
""
|
120
|
-
end
|
121
|
-
}
|
122
|
-
end
|
123
|
-
end_visit(new_node, parent) unless no_hooks
|
124
|
-
|
125
|
-
if new_node.equal?(node)
|
126
|
-
[node, parent]
|
127
|
-
else
|
128
|
-
[new_node, parent]
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
def #{node_method}_with_modifications(node, parent)
|
134
|
-
new_node_and_new_parent = #{node_method}(node, parent)
|
135
|
-
apply_modifications(node, parent, new_node_and_new_parent)
|
136
|
-
end
|
137
|
-
RUBY
|
138
|
-
end
|
139
|
-
|
140
79
|
def on_document_children(document_node)
|
141
80
|
new_node = document_node
|
142
81
|
document_node.children.each do |child_node|
|
@@ -237,6 +176,68 @@ module GraphQL
|
|
237
176
|
new_node
|
238
177
|
end
|
239
178
|
|
179
|
+
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
180
|
+
|
181
|
+
def self.make_visit_methods(ast_node_class)
|
182
|
+
node_method = ast_node_class.visit_method
|
183
|
+
children_of_type = ast_node_class.children_of_type
|
184
|
+
child_visit_method = :"#{node_method}_children"
|
185
|
+
|
186
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
187
|
+
# The default implementation for visiting an AST node.
|
188
|
+
# It doesn't _do_ anything, but it continues to visiting the node's children.
|
189
|
+
# To customize this hook, override one of its make_visit_methods (or the base method?)
|
190
|
+
# in your subclasses.
|
191
|
+
#
|
192
|
+
# For compatibility, it calls hook procs, too.
|
193
|
+
# @param node [GraphQL::Language::Nodes::AbstractNode] the node being visited
|
194
|
+
# @param parent [GraphQL::Language::Nodes::AbstractNode, nil] the previously-visited node, or `nil` if this is the root node.
|
195
|
+
# @return [Array, nil] If there were modifications, it returns an array of new nodes, otherwise, it returns `nil`.
|
196
|
+
def #{node_method}(node, parent)
|
197
|
+
if node.equal?(DELETE_NODE)
|
198
|
+
# This might be passed to `super(DELETE_NODE, ...)`
|
199
|
+
# by a user hook, don't want to keep visiting in that case.
|
200
|
+
[node, parent]
|
201
|
+
else
|
202
|
+
# Run hooks if there are any
|
203
|
+
new_node = node
|
204
|
+
no_hooks = !@visitors.key?(node.class)
|
205
|
+
if no_hooks || begin_visit(new_node, parent)
|
206
|
+
#{
|
207
|
+
if method_defined?(child_visit_method)
|
208
|
+
"new_node = #{child_visit_method}(new_node)"
|
209
|
+
elsif children_of_type
|
210
|
+
children_of_type.map do |child_accessor, child_class|
|
211
|
+
"node.#{child_accessor}.each do |child_node|
|
212
|
+
new_child_and_node = #{child_class.visit_method}_with_modifications(child_node, new_node)
|
213
|
+
# Reassign `node` in case the child hook makes a modification
|
214
|
+
if new_child_and_node.is_a?(Array)
|
215
|
+
new_node = new_child_and_node[1]
|
216
|
+
end
|
217
|
+
end"
|
218
|
+
end.join("\n")
|
219
|
+
else
|
220
|
+
""
|
221
|
+
end
|
222
|
+
}
|
223
|
+
end
|
224
|
+
end_visit(new_node, parent) unless no_hooks
|
225
|
+
if new_node.equal?(node)
|
226
|
+
[node, parent]
|
227
|
+
else
|
228
|
+
[new_node, parent]
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
def #{node_method}_with_modifications(node, parent)
|
233
|
+
new_node_and_new_parent = #{node_method}(node, parent)
|
234
|
+
apply_modifications(node, parent, new_node_and_new_parent)
|
235
|
+
end
|
236
|
+
RUBY
|
237
|
+
end
|
238
|
+
|
239
|
+
|
240
|
+
|
240
241
|
[
|
241
242
|
Language::Nodes::Argument,
|
242
243
|
Language::Nodes::Directive,
|
@@ -277,6 +278,8 @@ module GraphQL
|
|
277
278
|
make_visit_methods(ast_node_class)
|
278
279
|
end
|
279
280
|
|
281
|
+
# rubocop:enable Development/NoEvalCop
|
282
|
+
|
280
283
|
private
|
281
284
|
|
282
285
|
def apply_modifications(node, parent, new_node_and_new_parent)
|
@@ -227,7 +227,8 @@ module GraphQL
|
|
227
227
|
current_path
|
228
228
|
else
|
229
229
|
(current_runtime_state = Thread.current[:__graphql_runtime_info]) &&
|
230
|
-
(current_runtime_state
|
230
|
+
(query_runtime_state = current_runtime_state[@query]) &&
|
231
|
+
(query_runtime_state.public_send(key))
|
231
232
|
end
|
232
233
|
else
|
233
234
|
# not found
|
@@ -237,10 +238,12 @@ module GraphQL
|
|
237
238
|
|
238
239
|
def current_path
|
239
240
|
current_runtime_state = Thread.current[:__graphql_runtime_info]
|
240
|
-
|
241
|
-
|
241
|
+
query_runtime_state = current_runtime_state && current_runtime_state[@query]
|
242
|
+
|
243
|
+
path = query_runtime_state &&
|
244
|
+
(result = query_runtime_state.current_result) &&
|
242
245
|
(result.path)
|
243
|
-
if path && (rn =
|
246
|
+
if path && (rn = query_runtime_state.current_result_name)
|
244
247
|
path = path.dup
|
245
248
|
path.push(rn)
|
246
249
|
end
|
@@ -260,7 +263,8 @@ module GraphQL
|
|
260
263
|
def fetch(key, default = UNSPECIFIED_FETCH_DEFAULT)
|
261
264
|
if RUNTIME_METADATA_KEYS.include?(key)
|
262
265
|
(runtime = Thread.current[:__graphql_runtime_info]) &&
|
263
|
-
(runtime
|
266
|
+
(query_runtime_state = runtime[@query]) &&
|
267
|
+
(query_runtime_state.public_send(key))
|
264
268
|
elsif @scoped_context.key?(key)
|
265
269
|
scoped_context[key]
|
266
270
|
elsif @provided_values.key?(key)
|
@@ -277,8 +281,13 @@ module GraphQL
|
|
277
281
|
def dig(key, *other_keys)
|
278
282
|
if RUNTIME_METADATA_KEYS.include?(key)
|
279
283
|
(current_runtime_state = Thread.current[:__graphql_runtime_info]) &&
|
280
|
-
(
|
281
|
-
obj.
|
284
|
+
(query_runtime_state = current_runtime_state[@query]) &&
|
285
|
+
(obj = query_runtime_state.public_send(key)) &&
|
286
|
+
if other_keys.empty?
|
287
|
+
obj
|
288
|
+
else
|
289
|
+
obj.dig(*other_keys)
|
290
|
+
end
|
282
291
|
elsif @scoped_context.key?(key)
|
283
292
|
@scoped_context.dig(key, *other_keys)
|
284
293
|
else
|
@@ -3,35 +3,27 @@ module GraphQL
|
|
3
3
|
class Query
|
4
4
|
# This object can be `ctx` in places where there is no query
|
5
5
|
class NullContext
|
6
|
-
class NullWarden < GraphQL::Schema::Warden
|
7
|
-
def visible_field?(field, ctx); true; end
|
8
|
-
def visible_argument?(arg, ctx); true; end
|
9
|
-
def visible_type?(type, ctx); true; end
|
10
|
-
def visible_enum_value?(ev, ctx); true; end
|
11
|
-
def visible_type_membership?(tm, ctx); true; end
|
12
|
-
end
|
13
|
-
|
14
6
|
class NullQuery
|
7
|
+
def after_lazy(value)
|
8
|
+
yield(value)
|
9
|
+
end
|
15
10
|
end
|
16
11
|
|
17
12
|
class NullSchema < GraphQL::Schema
|
18
13
|
end
|
19
14
|
|
15
|
+
extend Forwardable
|
16
|
+
|
20
17
|
attr_reader :schema, :query, :warden, :dataloader
|
18
|
+
def_delegators GraphQL::EmptyObjects::EMPTY_HASH, :[], :fetch, :dig, :key?
|
21
19
|
|
22
20
|
def initialize
|
23
21
|
@query = NullQuery.new
|
24
22
|
@dataloader = GraphQL::Dataloader::NullDataloader.new
|
25
23
|
@schema = NullSchema
|
26
|
-
@warden = NullWarden.new(
|
27
|
-
GraphQL::Filter.new(silence_deprecation_warning: true),
|
28
|
-
context: self,
|
29
|
-
schema: @schema,
|
30
|
-
)
|
24
|
+
@warden = Schema::Warden::NullWarden.new(context: self, schema: @schema)
|
31
25
|
end
|
32
26
|
|
33
|
-
def [](key); end
|
34
|
-
|
35
27
|
def interpreter?
|
36
28
|
true
|
37
29
|
end
|
@@ -39,13 +31,11 @@ module GraphQL
|
|
39
31
|
class << self
|
40
32
|
extend Forwardable
|
41
33
|
|
42
|
-
def [](key); end
|
43
|
-
|
44
34
|
def instance
|
45
35
|
@instance ||= self.new
|
46
36
|
end
|
47
37
|
|
48
|
-
def_delegators :instance, :query, :warden, :schema, :interpreter?, :dataloader
|
38
|
+
def_delegators :instance, :query, :warden, :schema, :interpreter?, :dataloader, :[], :fetch, :dig, :key?
|
49
39
|
end
|
50
40
|
end
|
51
41
|
end
|
@@ -68,7 +68,8 @@ module GraphQL
|
|
68
68
|
elsif @operation_name_error
|
69
69
|
@validation_errors << @operation_name_error
|
70
70
|
else
|
71
|
-
|
71
|
+
validator = @query.static_validator || @schema.static_validator
|
72
|
+
validation_result = validator.validate(@query, validate: @query.validate, timeout: @schema.validate_timeout, max_errors: @schema.validate_max_errors)
|
72
73
|
@validation_errors.concat(validation_result[:errors])
|
73
74
|
|
74
75
|
if @validation_errors.empty?
|
data/lib/graphql/query.rb
CHANGED
@@ -45,6 +45,20 @@ module GraphQL
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
# @return [GraphQL::StaticValidation::Validator] if present, the query will validate with these rules.
|
49
|
+
attr_reader :static_validator
|
50
|
+
|
51
|
+
# @param new_validate [GraphQL::StaticValidation::Validator] if present, the query will validate with these rules. This can't be reasssigned after validation.
|
52
|
+
def static_validator=(new_validator)
|
53
|
+
if defined?(@validation_pipeline) && @validation_pipeline && @validation_pipeline.has_validated?
|
54
|
+
raise ArgumentError, "Can't reassign Query#static_validator= after validation has run, remove this assignment."
|
55
|
+
elsif !new_validator.is_a?(GraphQL::StaticValidation::Validator)
|
56
|
+
raise ArgumentError, "Expected a `GraphQL::StaticValidation::Validator` instance."
|
57
|
+
else
|
58
|
+
@static_validator = new_validator
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
48
62
|
attr_writer :query_string
|
49
63
|
|
50
64
|
# @return [GraphQL::Language::Nodes::Document]
|
@@ -83,11 +97,13 @@ module GraphQL
|
|
83
97
|
# @param max_complexity [Numeric] the maximum field complexity for this query (falls back to schema-level value)
|
84
98
|
# @param except [<#call(schema_member, context)>] If provided, objects will be hidden from the schema when `.call(schema_member, context)` returns truthy
|
85
99
|
# @param only [<#call(schema_member, context)>] If provided, objects will be hidden from the schema when `.call(schema_member, context)` returns false
|
86
|
-
def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, validate: true, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, except: nil, only: nil, warden: nil)
|
100
|
+
def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, validate: true, static_validator: nil, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, except: nil, only: nil, warden: nil)
|
87
101
|
# Even if `variables: nil` is passed, use an empty hash for simpler logic
|
88
102
|
variables ||= {}
|
89
103
|
@schema = schema
|
90
|
-
|
104
|
+
if only || except
|
105
|
+
merge_filters(except: except, only: only)
|
106
|
+
end
|
91
107
|
@context = schema.context_class.new(query: self, object: root_value, values: context)
|
92
108
|
@warden = warden
|
93
109
|
@subscription_topic = subscription_topic
|
@@ -95,12 +111,13 @@ module GraphQL
|
|
95
111
|
@fragments = nil
|
96
112
|
@operations = nil
|
97
113
|
@validate = validate
|
114
|
+
self.static_validator = static_validator if static_validator
|
98
115
|
context_tracers = (context ? context.fetch(:tracers, []) : [])
|
99
116
|
@tracers = schema.tracers + context_tracers
|
100
117
|
|
101
118
|
# Support `ctx[:backtrace] = true` for wrapping backtraces
|
102
119
|
if context && context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
|
103
|
-
if schema.trace_class <= GraphQL::Tracing::
|
120
|
+
if schema.trace_class <= GraphQL::Tracing::CallLegacyTracers
|
104
121
|
context_tracers += [GraphQL::Backtrace::Tracer]
|
105
122
|
@tracers << GraphQL::Backtrace::Tracer
|
106
123
|
elsif !(current_trace.class <= GraphQL::Backtrace::Trace)
|
@@ -108,8 +125,8 @@ module GraphQL
|
|
108
125
|
end
|
109
126
|
end
|
110
127
|
|
111
|
-
if context_tracers.any? && !(schema.trace_class <= GraphQL::Tracing::
|
112
|
-
raise ArgumentError, "context[:tracers] are not supported without `
|
128
|
+
if context_tracers.any? && !(schema.trace_class <= GraphQL::Tracing::CallLegacyTracers)
|
129
|
+
raise ArgumentError, "context[:tracers] are not supported without `trace_with(GraphQL::Tracing::CallLegacyTracers)` in the schema configuration, please add it."
|
113
130
|
end
|
114
131
|
|
115
132
|
|
@@ -151,11 +168,6 @@ module GraphQL
|
|
151
168
|
|
152
169
|
@result_values = nil
|
153
170
|
@executed = false
|
154
|
-
|
155
|
-
# TODO add a general way to define schema-level filters
|
156
|
-
if @schema.respond_to?(:visible?)
|
157
|
-
merge_filters(only: @schema.method(:visible?))
|
158
|
-
end
|
159
171
|
end
|
160
172
|
|
161
173
|
# If a document was provided to `GraphQL::Schema#execute` instead of the raw query string, we will need to get it from the document
|
@@ -171,7 +183,7 @@ module GraphQL
|
|
171
183
|
|
172
184
|
# @return [GraphQL::Tracing::Trace]
|
173
185
|
def current_trace
|
174
|
-
@current_trace ||= multiplex ? multiplex.current_trace : schema.new_trace(multiplex: multiplex, query: self)
|
186
|
+
@current_trace ||= context[:trace] || (multiplex ? multiplex.current_trace : schema.new_trace(multiplex: multiplex, query: self))
|
175
187
|
end
|
176
188
|
|
177
189
|
def subscription_update?
|
@@ -347,6 +359,7 @@ module GraphQL
|
|
347
359
|
if @prepared_ast
|
348
360
|
raise "Can't add filters after preparing the query"
|
349
361
|
else
|
362
|
+
@filter ||= @schema.default_filter
|
350
363
|
@filter = @filter.merge(only: only, except: except)
|
351
364
|
end
|
352
365
|
nil
|
@@ -361,6 +374,18 @@ module GraphQL
|
|
361
374
|
schema.handle_or_reraise(context, err)
|
362
375
|
end
|
363
376
|
|
377
|
+
def after_lazy(value, &block)
|
378
|
+
if !defined?(@runtime_instance)
|
379
|
+
@runtime_instance = context.namespace(:interpreter_runtime)[:runtime]
|
380
|
+
end
|
381
|
+
|
382
|
+
if @runtime_instance
|
383
|
+
@runtime_instance.minimal_after_lazy(value, &block)
|
384
|
+
else
|
385
|
+
@schema.after_lazy(value, &block)
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
364
389
|
private
|
365
390
|
|
366
391
|
def find_operation(operations, operation_name)
|
@@ -375,7 +400,7 @@ module GraphQL
|
|
375
400
|
|
376
401
|
def prepare_ast
|
377
402
|
@prepared_ast = true
|
378
|
-
@warden ||=
|
403
|
+
@warden ||= @schema.warden_class.new(@filter, schema: @schema, context: @context)
|
379
404
|
parse_error = nil
|
380
405
|
@document ||= begin
|
381
406
|
if query_string
|
@@ -40,14 +40,21 @@ module GraphQL
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def add_directives_from(owner)
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
if (dir_instances = owner.directives).any?
|
44
|
+
dirs = dir_instances.map(&:class)
|
45
|
+
@directives.merge(dirs)
|
46
|
+
add_type_and_traverse(dirs)
|
47
|
+
end
|
46
48
|
end
|
47
49
|
|
48
50
|
def add_type_and_traverse(new_types)
|
49
51
|
late_types = []
|
50
|
-
|
52
|
+
path = []
|
53
|
+
new_types.each do |t|
|
54
|
+
path.push(t.graphql_name)
|
55
|
+
add_type(t, owner: nil, late_types: late_types, path: path)
|
56
|
+
path.pop
|
57
|
+
end
|
51
58
|
missed_late_types = 0
|
52
59
|
while (late_type_vals = late_types.shift)
|
53
60
|
type_owner, lt = late_type_vals
|
@@ -158,7 +165,9 @@ module GraphQL
|
|
158
165
|
type.all_argument_definitions.each do |arg|
|
159
166
|
arg_type = arg.type.unwrap
|
160
167
|
references_to(arg_type, from: arg)
|
161
|
-
|
168
|
+
path.push(arg.graphql_name)
|
169
|
+
add_type(arg_type, owner: arg, late_types: late_types, path: path)
|
170
|
+
path.pop
|
162
171
|
if arg.default_value?
|
163
172
|
@arguments_with_default_values << arg
|
164
173
|
end
|
@@ -179,18 +188,21 @@ module GraphQL
|
|
179
188
|
name = field.graphql_name
|
180
189
|
field_type = field.type.unwrap
|
181
190
|
references_to(field_type, from: field)
|
182
|
-
|
183
|
-
add_type(field_type, owner: field, late_types: late_types, path:
|
191
|
+
path.push(name)
|
192
|
+
add_type(field_type, owner: field, late_types: late_types, path: path)
|
184
193
|
add_directives_from(field)
|
185
194
|
field.all_argument_definitions.each do |arg|
|
186
195
|
add_directives_from(arg)
|
187
196
|
arg_type = arg.type.unwrap
|
188
197
|
references_to(arg_type, from: arg)
|
189
|
-
|
198
|
+
path.push(arg.graphql_name)
|
199
|
+
add_type(arg_type, owner: arg, late_types: late_types, path: path)
|
200
|
+
path.pop
|
190
201
|
if arg.default_value?
|
191
202
|
@arguments_with_default_values << arg
|
192
203
|
end
|
193
204
|
end
|
205
|
+
path.pop
|
194
206
|
end
|
195
207
|
end
|
196
208
|
if type.kind.input_object?
|
@@ -198,7 +210,9 @@ module GraphQL
|
|
198
210
|
add_directives_from(arg)
|
199
211
|
arg_type = arg.type.unwrap
|
200
212
|
references_to(arg_type, from: arg)
|
201
|
-
|
213
|
+
path.push(arg.graphql_name)
|
214
|
+
add_type(arg_type, owner: arg, late_types: late_types, path: path)
|
215
|
+
path.pop
|
202
216
|
if arg.default_value?
|
203
217
|
@arguments_with_default_values << arg
|
204
218
|
end
|
@@ -206,14 +220,18 @@ module GraphQL
|
|
206
220
|
end
|
207
221
|
if type.kind.union?
|
208
222
|
@possible_types[type.graphql_name] = type.all_possible_types
|
223
|
+
path.push("possible_types")
|
209
224
|
type.all_possible_types.each do |t|
|
210
|
-
add_type(t, owner: type, late_types: late_types, path: path
|
225
|
+
add_type(t, owner: type, late_types: late_types, path: path)
|
211
226
|
end
|
227
|
+
path.pop
|
212
228
|
end
|
213
229
|
if type.kind.interface?
|
230
|
+
path.push("orphan_types")
|
214
231
|
type.orphan_types.each do |t|
|
215
|
-
add_type(t, owner: type, late_types: late_types, path: path
|
232
|
+
add_type(t, owner: type, late_types: late_types, path: path)
|
216
233
|
end
|
234
|
+
path.pop
|
217
235
|
end
|
218
236
|
if type.kind.object?
|
219
237
|
possible_types_for_this_name = @possible_types[type.graphql_name] ||= []
|
@@ -221,6 +239,7 @@ module GraphQL
|
|
221
239
|
end
|
222
240
|
|
223
241
|
if type.kind.object? || type.kind.interface?
|
242
|
+
path.push("implements")
|
224
243
|
type.interface_type_memberships.each do |interface_type_membership|
|
225
244
|
case interface_type_membership
|
226
245
|
when Schema::TypeMembership
|
@@ -235,7 +254,14 @@ module GraphQL
|
|
235
254
|
else
|
236
255
|
raise ArgumentError, "Invariant: unexpected type membership for #{type.graphql_name}: #{interface_type_membership.class} (#{interface_type_membership.inspect})"
|
237
256
|
end
|
238
|
-
add_type(interface_type, owner: type, late_types: late_types, path: path
|
257
|
+
add_type(interface_type, owner: type, late_types: late_types, path: path)
|
258
|
+
end
|
259
|
+
path.pop
|
260
|
+
end
|
261
|
+
|
262
|
+
if type.kind.enum?
|
263
|
+
type.all_enum_value_definitions.each do |value_definition|
|
264
|
+
add_directives_from(value_definition)
|
239
265
|
end
|
240
266
|
end
|
241
267
|
end
|