graphql 2.0.22 → 2.0.24
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/graphql/backtrace.rb +0 -4
- data/lib/graphql/dataloader/source.rb +3 -4
- data/lib/graphql/execution/interpreter/runtime.rb +17 -31
- data/lib/graphql/introspection/entry_points.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +4 -1
- data/lib/graphql/language/printer.rb +28 -14
- data/lib/graphql/query/null_context.rb +5 -18
- data/lib/graphql/query/validation_pipeline.rb +2 -1
- data/lib/graphql/query.rb +21 -6
- data/lib/graphql/schema/addition.rb +32 -12
- data/lib/graphql/schema/always_visible.rb +10 -0
- data/lib/graphql/schema/field.rb +21 -10
- data/lib/graphql/schema/introspection_system.rb +1 -1
- data/lib/graphql/schema/member/build_type.rb +10 -2
- data/lib/graphql/schema/object.rb +5 -0
- data/lib/graphql/schema/timeout.rb +1 -1
- data/lib/graphql/schema/warden.rb +29 -2
- data/lib/graphql/schema.rb +25 -10
- data/lib/graphql/tracing/legacy_trace.rb +5 -1
- data/lib/graphql/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c97d63232efb5f7ecdaef0f8102a73ceaa4a4b0a3b06c7ab1f613735efafa59
|
4
|
+
data.tar.gz: aff3df56a3db15d97f457e92fffab33f29440fed5ca84b0515794ad051e5631e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3cf33d0ed4df848c57e459f9ee023b0a6b2814d14ef09d7c304120a595cd62e65f25b05b3f16448c89cfb9479d06e550611c42fa76b3fb92a677c788f31f713e
|
7
|
+
data.tar.gz: 28b8d5e3fb2d6cc0bc3ebbdaf6f6d53dc16b0225bcafcc0fe72d4956afb9ff0fdb1ca929093ad466951dc28a30d893e643c8fb68bff69df374e41e1c43e2980b
|
data/lib/graphql/backtrace.rb
CHANGED
@@ -39,7 +39,7 @@ module GraphQL
|
|
39
39
|
result_for(key)
|
40
40
|
else
|
41
41
|
@pending_keys << key
|
42
|
-
sync
|
42
|
+
sync([key])
|
43
43
|
result_for(key)
|
44
44
|
end
|
45
45
|
end
|
@@ -50,7 +50,7 @@ module GraphQL
|
|
50
50
|
if keys.any? { |k| !@results.key?(k) }
|
51
51
|
pending_keys = keys.select { |k| !@results.key?(k) }
|
52
52
|
@pending_keys.concat(pending_keys)
|
53
|
-
sync
|
53
|
+
sync(pending_keys)
|
54
54
|
end
|
55
55
|
|
56
56
|
keys.map { |k| result_for(k) }
|
@@ -67,8 +67,7 @@ module GraphQL
|
|
67
67
|
# Wait for a batch, if there's anything to batch.
|
68
68
|
# Then run the batch and update the cache.
|
69
69
|
# @return [void]
|
70
|
-
def sync
|
71
|
-
pending_keys = @pending_keys.dup
|
70
|
+
def sync(pending_keys)
|
72
71
|
@dataloader.yield
|
73
72
|
iterations = 0
|
74
73
|
while pending_keys.any? { |k| !@results.key?(k) }
|
@@ -247,15 +247,15 @@ module GraphQL
|
|
247
247
|
st = get_current_runtime_state
|
248
248
|
st.current_object = query.root_value
|
249
249
|
st.current_result = @response
|
250
|
-
|
251
|
-
|
250
|
+
runtime_object = root_type.wrap(query.root_value, context)
|
251
|
+
runtime_object = schema.sync_lazy(runtime_object)
|
252
252
|
|
253
|
-
if
|
253
|
+
if runtime_object.nil?
|
254
254
|
# Root .authorized? returned false.
|
255
255
|
@response = nil
|
256
256
|
else
|
257
|
-
call_method_on_directives(:resolve,
|
258
|
-
gathered_selections = gather_selections(
|
257
|
+
call_method_on_directives(:resolve, runtime_object, root_operation.directives) do # execute query level directives
|
258
|
+
gathered_selections = gather_selections(runtime_object, root_type, root_operation.selections)
|
259
259
|
# This is kind of a hack -- `gathered_selections` is an Array if any of the selections
|
260
260
|
# require isolation during execution (because of runtime directives). In that case,
|
261
261
|
# make a new, isolated result hash for writing the result into. (That isolated response
|
@@ -280,9 +280,9 @@ module GraphQL
|
|
280
280
|
if (directives = selections[:graphql_directives])
|
281
281
|
selections.delete(:graphql_directives)
|
282
282
|
end
|
283
|
-
call_method_on_directives(:resolve,
|
283
|
+
call_method_on_directives(:resolve, runtime_object, directives) do
|
284
284
|
evaluate_selections(
|
285
|
-
|
285
|
+
runtime_object,
|
286
286
|
root_type,
|
287
287
|
root_op_type == "mutation",
|
288
288
|
selections,
|
@@ -343,12 +343,8 @@ module GraphQL
|
|
343
343
|
if node.type
|
344
344
|
type_defn = schema.get_type(node.type.name, context)
|
345
345
|
|
346
|
-
|
347
|
-
|
348
|
-
if t == owner_type
|
349
|
-
gather_selections(owner_object, owner_type, node.selections, selections_to_run, next_selections)
|
350
|
-
break
|
351
|
-
end
|
346
|
+
if query.warden.possible_types(type_defn).include?(owner_type)
|
347
|
+
gather_selections(owner_object, owner_type, node.selections, selections_to_run, next_selections)
|
352
348
|
end
|
353
349
|
else
|
354
350
|
# it's an untyped fragment, definitely continue
|
@@ -357,12 +353,8 @@ module GraphQL
|
|
357
353
|
when GraphQL::Language::Nodes::FragmentSpread
|
358
354
|
fragment_def = query.fragments[node.name]
|
359
355
|
type_defn = query.get_type(fragment_def.type.name)
|
360
|
-
|
361
|
-
|
362
|
-
if t == owner_type
|
363
|
-
gather_selections(owner_object, owner_type, fragment_def.selections, selections_to_run, next_selections)
|
364
|
-
break
|
365
|
-
end
|
356
|
+
if query.warden.possible_types(type_defn).include?(owner_type)
|
357
|
+
gather_selections(owner_object, owner_type, fragment_def.selections, selections_to_run, next_selections)
|
366
358
|
end
|
367
359
|
else
|
368
360
|
raise "Invariant: unexpected selection class: #{node.class}"
|
@@ -446,10 +438,8 @@ module GraphQL
|
|
446
438
|
st.current_result = selections_result
|
447
439
|
st.current_result_name = result_name
|
448
440
|
|
449
|
-
object = owner_object
|
450
|
-
|
451
441
|
if is_introspection
|
452
|
-
|
442
|
+
owner_object = field_defn.owner.wrap(owner_object, context)
|
453
443
|
end
|
454
444
|
|
455
445
|
total_args_count = field_defn.arguments(context).size
|
@@ -457,14 +447,14 @@ module GraphQL
|
|
457
447
|
resolved_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
|
458
448
|
if field_defn.extras.size == 0
|
459
449
|
evaluate_selection_with_resolved_keyword_args(
|
460
|
-
NO_ARGS, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type,
|
450
|
+
NO_ARGS, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type_non_null
|
461
451
|
)
|
462
452
|
else
|
463
|
-
evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type,
|
453
|
+
evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type_non_null)
|
464
454
|
end
|
465
455
|
else
|
466
|
-
@query.arguments_cache.dataload_for(ast_node, field_defn,
|
467
|
-
evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type,
|
456
|
+
@query.arguments_cache.dataload_for(ast_node, field_defn, owner_object) do |resolved_arguments|
|
457
|
+
evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type_non_null)
|
468
458
|
end
|
469
459
|
end
|
470
460
|
end
|
@@ -782,7 +772,7 @@ module GraphQL
|
|
782
772
|
end
|
783
773
|
when "OBJECT"
|
784
774
|
object_proxy = begin
|
785
|
-
|
775
|
+
current_type.wrap(value, context)
|
786
776
|
rescue GraphQL::ExecutionError => err
|
787
777
|
err
|
788
778
|
end
|
@@ -1055,10 +1045,6 @@ module GraphQL
|
|
1055
1045
|
end
|
1056
1046
|
end
|
1057
1047
|
|
1058
|
-
def authorized_new(type, value, context)
|
1059
|
-
type.authorized_new(value, context)
|
1060
|
-
end
|
1061
|
-
|
1062
1048
|
def lazy?(object)
|
1063
1049
|
obj_class = object.class
|
1064
1050
|
is_lazy = @lazy_cache[obj_class]
|
@@ -11,7 +11,7 @@ module GraphQL
|
|
11
11
|
# Apply wrapping manually since this field isn't wrapped by instrumentation
|
12
12
|
schema = @context.query.schema
|
13
13
|
schema_type = schema.introspection_system.types["__Schema"]
|
14
|
-
schema_type.
|
14
|
+
schema_type.wrap(schema, @context)
|
15
15
|
end
|
16
16
|
|
17
17
|
def __type(name:)
|
@@ -36,7 +36,10 @@ module GraphQL
|
|
36
36
|
context: schema_context,
|
37
37
|
)
|
38
38
|
else
|
39
|
-
|
39
|
+
@schema.warden_class.new(
|
40
|
+
schema: @schema,
|
41
|
+
context: schema_context,
|
42
|
+
)
|
40
43
|
end
|
41
44
|
|
42
45
|
schema_context.warden = @warden
|
@@ -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
|
@@ -3,14 +3,6 @@ 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
|
15
7
|
def after_lazy(value)
|
16
8
|
yield(value)
|
@@ -20,21 +12,18 @@ module GraphQL
|
|
20
12
|
class NullSchema < GraphQL::Schema
|
21
13
|
end
|
22
14
|
|
15
|
+
extend Forwardable
|
16
|
+
|
23
17
|
attr_reader :schema, :query, :warden, :dataloader
|
18
|
+
def_delegators GraphQL::EmptyObjects::EMPTY_HASH, :[], :fetch, :dig, :key?
|
24
19
|
|
25
20
|
def initialize
|
26
21
|
@query = NullQuery.new
|
27
22
|
@dataloader = GraphQL::Dataloader::NullDataloader.new
|
28
23
|
@schema = NullSchema
|
29
|
-
@warden = NullWarden.new(
|
30
|
-
GraphQL::Filter.new(silence_deprecation_warning: true),
|
31
|
-
context: self,
|
32
|
-
schema: @schema,
|
33
|
-
)
|
24
|
+
@warden = Schema::Warden::NullWarden.new(context: self, schema: @schema)
|
34
25
|
end
|
35
26
|
|
36
|
-
def [](key); end
|
37
|
-
|
38
27
|
def interpreter?
|
39
28
|
true
|
40
29
|
end
|
@@ -42,13 +31,11 @@ module GraphQL
|
|
42
31
|
class << self
|
43
32
|
extend Forwardable
|
44
33
|
|
45
|
-
def [](key); end
|
46
|
-
|
47
34
|
def instance
|
48
35
|
@instance ||= self.new
|
49
36
|
end
|
50
37
|
|
51
|
-
def_delegators :instance, :query, :warden, :schema, :interpreter?, :dataloader
|
38
|
+
def_delegators :instance, :query, :warden, :schema, :interpreter?, :dataloader, :[], :fetch, :dig, :key?
|
52
39
|
end
|
53
40
|
end
|
54
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,7 +97,7 @@ 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
|
@@ -97,12 +111,13 @@ module GraphQL
|
|
97
111
|
@fragments = nil
|
98
112
|
@operations = nil
|
99
113
|
@validate = validate
|
114
|
+
self.static_validator = static_validator if static_validator
|
100
115
|
context_tracers = (context ? context.fetch(:tracers, []) : [])
|
101
116
|
@tracers = schema.tracers + context_tracers
|
102
117
|
|
103
118
|
# Support `ctx[:backtrace] = true` for wrapping backtraces
|
104
119
|
if context && context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
|
105
|
-
if schema.trace_class <= GraphQL::Tracing::
|
120
|
+
if schema.trace_class <= GraphQL::Tracing::CallLegacyTracers
|
106
121
|
context_tracers += [GraphQL::Backtrace::Tracer]
|
107
122
|
@tracers << GraphQL::Backtrace::Tracer
|
108
123
|
elsif !(current_trace.class <= GraphQL::Backtrace::Trace)
|
@@ -110,8 +125,8 @@ module GraphQL
|
|
110
125
|
end
|
111
126
|
end
|
112
127
|
|
113
|
-
if context_tracers.any? && !(schema.trace_class <= GraphQL::Tracing::
|
114
|
-
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."
|
115
130
|
end
|
116
131
|
|
117
132
|
|
@@ -168,7 +183,7 @@ module GraphQL
|
|
168
183
|
|
169
184
|
# @return [GraphQL::Tracing::Trace]
|
170
185
|
def current_trace
|
171
|
-
@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))
|
172
187
|
end
|
173
188
|
|
174
189
|
def subscription_update?
|
@@ -385,7 +400,7 @@ module GraphQL
|
|
385
400
|
|
386
401
|
def prepare_ast
|
387
402
|
@prepared_ast = true
|
388
|
-
@warden ||=
|
403
|
+
@warden ||= @schema.warden_class.new(@filter, schema: @schema, context: @context)
|
389
404
|
parse_error = nil
|
390
405
|
@document ||= begin
|
391
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,8 +254,9 @@ 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)
|
239
258
|
end
|
259
|
+
path.pop
|
240
260
|
end
|
241
261
|
end
|
242
262
|
end
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -339,7 +339,7 @@ module GraphQL
|
|
339
339
|
self.validates(validates)
|
340
340
|
end
|
341
341
|
|
342
|
-
if
|
342
|
+
if block_given?
|
343
343
|
if definition_block.arity == 1
|
344
344
|
yield self
|
345
345
|
else
|
@@ -810,6 +810,17 @@ ERR
|
|
810
810
|
end
|
811
811
|
end
|
812
812
|
|
813
|
+
class ExtendedState
|
814
|
+
def initialize(args, object)
|
815
|
+
@arguments = args
|
816
|
+
@object = object
|
817
|
+
@memos = nil
|
818
|
+
@added_extras = nil
|
819
|
+
end
|
820
|
+
|
821
|
+
attr_accessor :arguments, :object, :memos, :added_extras
|
822
|
+
end
|
823
|
+
|
813
824
|
# Wrap execution with hooks.
|
814
825
|
# Written iteratively to avoid big stack traces.
|
815
826
|
# @return [Object] Whatever the
|
@@ -820,18 +831,18 @@ ERR
|
|
820
831
|
# This is a hack to get the _last_ value for extended obj and args,
|
821
832
|
# in case one of the extensions doesn't `yield`.
|
822
833
|
# (There's another implementation that uses multiple-return, but I'm wary of the perf cost of the extra arrays)
|
823
|
-
extended =
|
834
|
+
extended = ExtendedState.new(args, obj)
|
824
835
|
value = run_extensions_before_resolve(obj, args, ctx, extended) do |obj, args|
|
825
|
-
if (added_extras = extended
|
836
|
+
if (added_extras = extended.added_extras)
|
826
837
|
args = args.dup
|
827
838
|
added_extras.each { |e| args.delete(e) }
|
828
839
|
end
|
829
840
|
yield(obj, args)
|
830
841
|
end
|
831
842
|
|
832
|
-
extended_obj = extended
|
833
|
-
extended_args = extended
|
834
|
-
memos = extended
|
843
|
+
extended_obj = extended.object
|
844
|
+
extended_args = extended.arguments # rubocop:disable Development/ContextIsPassedCop
|
845
|
+
memos = extended.memos || EMPTY_HASH
|
835
846
|
|
836
847
|
ctx.query.after_lazy(value) do |resolved_value|
|
837
848
|
idx = 0
|
@@ -851,17 +862,17 @@ ERR
|
|
851
862
|
if extension
|
852
863
|
extension.resolve(object: obj, arguments: args, context: ctx) do |extended_obj, extended_args, memo|
|
853
864
|
if memo
|
854
|
-
memos = extended
|
865
|
+
memos = extended.memos ||= {}
|
855
866
|
memos[idx] = memo
|
856
867
|
end
|
857
868
|
|
858
869
|
if (extras = extension.added_extras)
|
859
|
-
ae = extended
|
870
|
+
ae = extended.added_extras ||= []
|
860
871
|
ae.concat(extras)
|
861
872
|
end
|
862
873
|
|
863
|
-
extended
|
864
|
-
extended
|
874
|
+
extended.object = extended_obj
|
875
|
+
extended.arguments = extended_args
|
865
876
|
run_extensions_before_resolve(extended_obj, extended_args, ctx, extended, idx: idx + 1) { |o, a| yield(o, a) }
|
866
877
|
end
|
867
878
|
else
|
@@ -155,7 +155,7 @@ module GraphQL
|
|
155
155
|
if obj.is_a?(GraphQL::Schema::Object)
|
156
156
|
obj = obj.object
|
157
157
|
end
|
158
|
-
wrapped_object = @object_class.
|
158
|
+
wrapped_object = @object_class.wrap(obj, query_ctx)
|
159
159
|
@inner_resolve.call(wrapped_object, args, ctx)
|
160
160
|
end
|
161
161
|
end
|
@@ -109,7 +109,14 @@ module GraphQL
|
|
109
109
|
to_type_name(something.name)
|
110
110
|
end
|
111
111
|
when String
|
112
|
-
something.
|
112
|
+
if something.include?("]") ||
|
113
|
+
something.include?("[") ||
|
114
|
+
something.include?("!") ||
|
115
|
+
something.include?("::")
|
116
|
+
something.gsub(/\]\[\!/, "").split("::").last
|
117
|
+
else
|
118
|
+
something
|
119
|
+
end
|
113
120
|
when GraphQL::Schema::NonNull, GraphQL::Schema::List
|
114
121
|
to_type_name(something.unwrap)
|
115
122
|
else
|
@@ -122,7 +129,8 @@ module GraphQL
|
|
122
129
|
return string unless string.include?("_")
|
123
130
|
camelized = string.split('_').each(&:capitalize!).join
|
124
131
|
camelized[0] = camelized[0].downcase
|
125
|
-
if
|
132
|
+
if string.start_with?("_")
|
133
|
+
match_data = string.match(/\A(_+)/)
|
126
134
|
camelized = "#{match_data[0]}#{camelized}"
|
127
135
|
end
|
128
136
|
camelized
|
@@ -30,6 +30,11 @@ module GraphQL
|
|
30
30
|
# @see authorized_new to make instances
|
31
31
|
protected :new
|
32
32
|
|
33
|
+
# This is called by the runtime to return an object to call methods on.
|
34
|
+
def wrap(object, context)
|
35
|
+
authorized_new(object, context)
|
36
|
+
end
|
37
|
+
|
33
38
|
# Make a new instance of this type _if_ the auth check passes,
|
34
39
|
# otherwise, raise an error.
|
35
40
|
#
|
@@ -90,7 +90,7 @@ module GraphQL
|
|
90
90
|
# The default implementation returns the `max_seconds:` value from installing this plugin.
|
91
91
|
#
|
92
92
|
# @param query [GraphQL::Query] The query that's about to run
|
93
|
-
# @return [
|
93
|
+
# @return [Numeric, false] The number of seconds after which to interrupt query execution and call {#handle_error}, or `false` to bypass the timeout.
|
94
94
|
def max_seconds(query)
|
95
95
|
@max_seconds
|
96
96
|
end
|
@@ -38,8 +38,9 @@ module GraphQL
|
|
38
38
|
# @api private
|
39
39
|
class Warden
|
40
40
|
def self.from_context(context)
|
41
|
-
context.warden
|
42
|
-
rescue
|
41
|
+
context.warden || PassThruWarden
|
42
|
+
rescue NoMethodError
|
43
|
+
# this might be a hash which won't respond to #warden
|
43
44
|
PassThruWarden
|
44
45
|
end
|
45
46
|
|
@@ -87,6 +88,32 @@ module GraphQL
|
|
87
88
|
end
|
88
89
|
end
|
89
90
|
|
91
|
+
class NullWarden
|
92
|
+
def initialize(_filter = nil, context:, schema:)
|
93
|
+
@schema = schema
|
94
|
+
end
|
95
|
+
|
96
|
+
def visible_field?(field_defn, _ctx = nil, owner = nil); true; end
|
97
|
+
def visible_argument?(arg_defn, _ctx = nil); true; end
|
98
|
+
def visible_type?(type_defn, _ctx = nil); true; end
|
99
|
+
def visible_enum_value?(enum_value, _ctx = nil); true; end
|
100
|
+
def visible_type_membership?(type_membership, _ctx = nil); true; end
|
101
|
+
def interface_type_memberships(obj_type, _ctx = nil); obj_type.interface_type_memberships; end
|
102
|
+
def get_type(type_name); @schema.get_type(type_name); end # rubocop:disable Development/ContextIsPassedCop
|
103
|
+
def arguments(argument_owner, ctx = nil); argument_owner.all_argument_definitions; end
|
104
|
+
def enum_values(enum_defn); enum_defn.enum_values; end # rubocop:disable Development/ContextIsPassedCop
|
105
|
+
def get_argument(parent_type, argument_name); parent_type.get_argument(argument_name); end # rubocop:disable Development/ContextIsPassedCop
|
106
|
+
def types; @schema.types; end # rubocop:disable Development/ContextIsPassedCop
|
107
|
+
def root_type_for_operation(op_name); @schema.root_type_for_operation(op_name); end
|
108
|
+
def directives; @schema.directives.values; end
|
109
|
+
def fields(type_defn); type_defn.all_field_definitions; end # rubocop:disable Development/ContextIsPassedCop
|
110
|
+
def get_field(parent_type, field_name); @schema.get_field(parent_type, field_name); end
|
111
|
+
def reachable_type?(type_name); true; end
|
112
|
+
def reachable_types; @schema.types.values; end # rubocop:disable Development/ContextIsPassedCop
|
113
|
+
def possible_types(type_defn); @schema.possible_types(type_defn); end
|
114
|
+
def interfaces(obj_type); obj_type.interfaces; end
|
115
|
+
end
|
116
|
+
|
90
117
|
# @param filter [<#call(member)>] Objects are hidden when `.call(member, ctx)` returns true
|
91
118
|
# @param context [GraphQL::Query::Context]
|
92
119
|
# @param schema [GraphQL::Schema]
|
data/lib/graphql/schema.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "graphql/schema/addition"
|
3
|
+
require "graphql/schema/always_visible"
|
3
4
|
require "graphql/schema/base_64_encoder"
|
4
5
|
require "graphql/schema/find_inherited_value"
|
5
6
|
require "graphql/schema/finder"
|
@@ -157,14 +158,17 @@ module GraphQL
|
|
157
158
|
def trace_class_for(mode)
|
158
159
|
@trace_modes ||= {}
|
159
160
|
@trace_modes[mode] ||= begin
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
161
|
+
if mode == :default_backtrace
|
162
|
+
schema_base_class = trace_class_for(:default)
|
163
|
+
Class.new(schema_base_class) do
|
164
|
+
include(GraphQL::Backtrace::Trace)
|
165
|
+
end
|
166
|
+
elsif superclass.respond_to?(:trace_class_for)
|
167
|
+
superclass_base_class = superclass.trace_class_for(mode)
|
168
|
+
Class.new(superclass_base_class)
|
164
169
|
else
|
165
|
-
GraphQL::Tracing::Trace
|
170
|
+
Class.new(GraphQL::Tracing::Trace)
|
166
171
|
end
|
167
|
-
Class.new(base_class)
|
168
172
|
end
|
169
173
|
end
|
170
174
|
|
@@ -420,6 +424,18 @@ module GraphQL
|
|
420
424
|
@root_types
|
421
425
|
end
|
422
426
|
|
427
|
+
def warden_class
|
428
|
+
if defined?(@warden_class)
|
429
|
+
@warden_class
|
430
|
+
elsif superclass.respond_to?(:warden_class)
|
431
|
+
superclass.warden_class
|
432
|
+
else
|
433
|
+
GraphQL::Schema::Warden
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
attr_writer :warden_class
|
438
|
+
|
423
439
|
# @param type [Module] The type definition whose possible types you want to see
|
424
440
|
# @return [Hash<String, Module>] All possible types, if no `type` is given.
|
425
441
|
# @return [Array<Module>] Possible types for `type`, if it's given.
|
@@ -961,10 +977,8 @@ module GraphQL
|
|
961
977
|
end
|
962
978
|
|
963
979
|
def tracer(new_tracer)
|
964
|
-
if
|
965
|
-
|
966
|
-
else
|
967
|
-
trace_mode(:default, Class.new(GraphQL::Tracing::LegacyTrace))
|
980
|
+
if !(trace_class_for(:default) < GraphQL::Tracing::CallLegacyTracers)
|
981
|
+
trace_with(GraphQL::Tracing::CallLegacyTracers)
|
968
982
|
end
|
969
983
|
|
970
984
|
own_tracers << new_tracer
|
@@ -1036,6 +1050,7 @@ module GraphQL
|
|
1036
1050
|
{
|
1037
1051
|
backtrace: ctx[:backtrace],
|
1038
1052
|
tracers: ctx[:tracers],
|
1053
|
+
trace: ctx[:trace],
|
1039
1054
|
dataloader: ctx[:dataloader],
|
1040
1055
|
}
|
1041
1056
|
else
|
@@ -4,7 +4,7 @@ module GraphQL
|
|
4
4
|
# This trace class calls legacy-style tracer with payload hashes.
|
5
5
|
# New-style `trace_with` modules significantly reduce the overhead of tracing,
|
6
6
|
# but that advantage is lost when legacy-style tracers are also used (since the payload hashes are still constructed).
|
7
|
-
|
7
|
+
module CallLegacyTracers
|
8
8
|
def lex(query_string:)
|
9
9
|
(@multiplex || @query).trace("lex", { query_string: query_string }) { super }
|
10
10
|
end
|
@@ -61,5 +61,9 @@ module GraphQL
|
|
61
61
|
query.trace("resolve_type_lazy", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super }
|
62
62
|
end
|
63
63
|
end
|
64
|
+
|
65
|
+
class LegacyTrace < Trace
|
66
|
+
include CallLegacyTracers
|
67
|
+
end
|
64
68
|
end
|
65
69
|
end
|
data/lib/graphql/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.24
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-06-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-ips
|
@@ -395,6 +395,7 @@ files:
|
|
395
395
|
- lib/graphql/runtime_type_error.rb
|
396
396
|
- lib/graphql/schema.rb
|
397
397
|
- lib/graphql/schema/addition.rb
|
398
|
+
- lib/graphql/schema/always_visible.rb
|
398
399
|
- lib/graphql/schema/argument.rb
|
399
400
|
- lib/graphql/schema/base_64_bp.rb
|
400
401
|
- lib/graphql/schema/base_64_encoder.rb
|
@@ -622,7 +623,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
622
623
|
- !ruby/object:Gem::Version
|
623
624
|
version: '0'
|
624
625
|
requirements: []
|
625
|
-
rubygems_version: 3.
|
626
|
+
rubygems_version: 3.2.33
|
626
627
|
signing_key:
|
627
628
|
specification_version: 4
|
628
629
|
summary: A GraphQL language and runtime for Ruby
|