graphql 2.0.20 → 2.0.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql/backtrace/trace.rb +96 -0
- data/lib/graphql/backtrace.rb +6 -1
- data/lib/graphql/execution/interpreter/arguments.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +2 -3
- data/lib/graphql/execution/interpreter/runtime.rb +200 -161
- data/lib/graphql/execution/interpreter.rb +1 -1
- data/lib/graphql/filter.rb +7 -2
- data/lib/graphql/language/document_from_schema_definition.rb +25 -9
- data/lib/graphql/language/nodes.rb +2 -2
- data/lib/graphql/language/parser.rb +475 -458
- data/lib/graphql/language/parser.y +5 -1
- data/lib/graphql/pagination/connection.rb +5 -5
- data/lib/graphql/query/context.rb +13 -12
- data/lib/graphql/query/null_context.rb +1 -1
- data/lib/graphql/query.rb +9 -5
- data/lib/graphql/schema/argument.rb +7 -9
- data/lib/graphql/schema/build_from_definition.rb +15 -3
- data/lib/graphql/schema/enum_value.rb +2 -5
- data/lib/graphql/schema/field.rb +14 -13
- data/lib/graphql/schema/field_extension.rb +1 -4
- data/lib/graphql/schema/find_inherited_value.rb +2 -7
- data/lib/graphql/schema/member/has_arguments.rb +1 -1
- data/lib/graphql/schema/member/has_directives.rb +4 -6
- data/lib/graphql/schema/member/has_fields.rb +80 -36
- data/lib/graphql/schema/member/has_validators.rb +2 -2
- data/lib/graphql/schema/resolver.rb +4 -4
- data/lib/graphql/schema/validator.rb +1 -1
- data/lib/graphql/schema/warden.rb +3 -1
- data/lib/graphql/schema.rb +40 -11
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +2 -2
- data/lib/graphql/tracing/appsignal_trace.rb +6 -0
- data/lib/graphql/tracing/legacy_trace.rb +65 -0
- data/lib/graphql/tracing/notifications_trace.rb +2 -1
- data/lib/graphql/tracing/platform_trace.rb +21 -19
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +1 -1
- data/lib/graphql/tracing/trace.rb +75 -0
- data/lib/graphql/tracing.rb +3 -123
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +4 -0
- metadata +5 -2
@@ -284,7 +284,11 @@ rule
|
|
284
284
|
| directive_definition
|
285
285
|
|
286
286
|
schema_definition:
|
287
|
-
SCHEMA directives_list_opt
|
287
|
+
SCHEMA directives_list_opt operation_type_definition_list_opt { result = make_node(:SchemaDefinition, position_source: val[0], definition_line: val[0][1], directives: val[1], **val[2]) }
|
288
|
+
|
289
|
+
operation_type_definition_list_opt:
|
290
|
+
/* none */ { result = {} }
|
291
|
+
| LCURLY operation_type_definition_list RCURLY { result = val[1] }
|
288
292
|
|
289
293
|
operation_type_definition_list:
|
290
294
|
operation_type_definition
|
@@ -58,7 +58,7 @@ module GraphQL
|
|
58
58
|
# @param arguments [Hash] The arguments to the field that returned the collection wrapped by this connection
|
59
59
|
# @param max_page_size [Integer, nil] A configured value to cap the result size. Applied as `first` if neither first or last are given and no `default_page_size` is set.
|
60
60
|
# @param default_page_size [Integer, nil] A configured value to determine the result size when neither first or last are given.
|
61
|
-
def initialize(items, parent: nil, field: nil, context: nil, first: nil, after: nil, max_page_size:
|
61
|
+
def initialize(items, parent: nil, field: nil, context: nil, first: nil, after: nil, max_page_size: NOT_CONFIGURED, default_page_size: NOT_CONFIGURED, last: nil, before: nil, edge_class: nil, arguments: nil)
|
62
62
|
@items = items
|
63
63
|
@parent = parent
|
64
64
|
@context = context
|
@@ -71,14 +71,14 @@ module GraphQL
|
|
71
71
|
@edge_class = edge_class || self.class::Edge
|
72
72
|
# This is only true if the object was _initialized_ with an override
|
73
73
|
# or if one is assigned later.
|
74
|
-
@has_max_page_size_override = max_page_size !=
|
75
|
-
@max_page_size = if max_page_size ==
|
74
|
+
@has_max_page_size_override = max_page_size != NOT_CONFIGURED
|
75
|
+
@max_page_size = if max_page_size == NOT_CONFIGURED
|
76
76
|
nil
|
77
77
|
else
|
78
78
|
max_page_size
|
79
79
|
end
|
80
|
-
@has_default_page_size_override = default_page_size !=
|
81
|
-
@default_page_size = if default_page_size ==
|
80
|
+
@has_default_page_size_override = default_page_size != NOT_CONFIGURED
|
81
|
+
@default_page_size = if default_page_size == NOT_CONFIGURED
|
82
82
|
nil
|
83
83
|
else
|
84
84
|
default_page_size
|
@@ -91,8 +91,8 @@ module GraphQL
|
|
91
91
|
end
|
92
92
|
|
93
93
|
class ScopedContext
|
94
|
-
NO_PATH =
|
95
|
-
NO_CONTEXT =
|
94
|
+
NO_PATH = GraphQL::EmptyObjects::EMPTY_ARRAY
|
95
|
+
NO_CONTEXT = GraphQL::EmptyObjects::EMPTY_HASH
|
96
96
|
|
97
97
|
def initialize(query_context)
|
98
98
|
@query_context = query_context
|
@@ -226,8 +226,8 @@ module GraphQL
|
|
226
226
|
if key == :current_path
|
227
227
|
current_path
|
228
228
|
else
|
229
|
-
|
230
|
-
|
229
|
+
(current_runtime_state = Thread.current[:__graphql_runtime_info]) &&
|
230
|
+
(current_runtime_state.public_send(key))
|
231
231
|
end
|
232
232
|
else
|
233
233
|
# not found
|
@@ -236,11 +236,11 @@ module GraphQL
|
|
236
236
|
end
|
237
237
|
|
238
238
|
def current_path
|
239
|
-
|
240
|
-
path =
|
241
|
-
(result =
|
239
|
+
current_runtime_state = Thread.current[:__graphql_runtime_info]
|
240
|
+
path = current_runtime_state &&
|
241
|
+
(result = current_runtime_state.current_result) &&
|
242
242
|
(result.path)
|
243
|
-
if path && (rn =
|
243
|
+
if path && (rn = current_runtime_state.current_result_name)
|
244
244
|
path = path.dup
|
245
245
|
path.push(rn)
|
246
246
|
end
|
@@ -259,8 +259,8 @@ module GraphQL
|
|
259
259
|
|
260
260
|
def fetch(key, default = UNSPECIFIED_FETCH_DEFAULT)
|
261
261
|
if RUNTIME_METADATA_KEYS.include?(key)
|
262
|
-
(
|
263
|
-
|
262
|
+
(runtime = Thread.current[:__graphql_runtime_info]) &&
|
263
|
+
(runtime.public_send(key))
|
264
264
|
elsif @scoped_context.key?(key)
|
265
265
|
scoped_context[key]
|
266
266
|
elsif @provided_values.key?(key)
|
@@ -276,8 +276,9 @@ module GraphQL
|
|
276
276
|
|
277
277
|
def dig(key, *other_keys)
|
278
278
|
if RUNTIME_METADATA_KEYS.include?(key)
|
279
|
-
(
|
280
|
-
|
279
|
+
(current_runtime_state = Thread.current[:__graphql_runtime_info]) &&
|
280
|
+
(obj = current_runtime_state.public_send(key)) &&
|
281
|
+
obj.dig(*other_keys)
|
281
282
|
elsif @scoped_context.key?(key)
|
282
283
|
@scoped_context.dig(key, *other_keys)
|
283
284
|
else
|
data/lib/graphql/query.rb
CHANGED
@@ -100,12 +100,16 @@ module GraphQL
|
|
100
100
|
|
101
101
|
# Support `ctx[:backtrace] = true` for wrapping backtraces
|
102
102
|
if context && context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
|
103
|
-
|
104
|
-
|
103
|
+
if schema.trace_class <= GraphQL::Tracing::LegacyTrace
|
104
|
+
context_tracers += [GraphQL::Backtrace::Tracer]
|
105
|
+
@tracers << GraphQL::Backtrace::Tracer
|
106
|
+
elsif !(current_trace.class <= GraphQL::Backtrace::Trace)
|
107
|
+
raise "Invariant: `backtrace: true` should have provided a trace class with Backtrace mixed in, but it didnt. (Found: #{current_trace.class.ancestors}). This is a bug in GraphQL-Ruby, please report it on GitHub."
|
108
|
+
end
|
105
109
|
end
|
106
110
|
|
107
111
|
if context_tracers.any? && !(schema.trace_class <= GraphQL::Tracing::LegacyTrace)
|
108
|
-
raise ArgumentError, "context[:tracers]
|
112
|
+
raise ArgumentError, "context[:tracers] are not supported without `trace_class(GraphQL::Tracing::LegacyTrace)` in the schema configuration, please add it."
|
109
113
|
end
|
110
114
|
|
111
115
|
|
@@ -318,8 +322,8 @@ module GraphQL
|
|
318
322
|
# @param value [Object] Any runtime value
|
319
323
|
# @return [GraphQL::ObjectType, nil] The runtime type of `value` from {Schema#resolve_type}
|
320
324
|
# @see {#possible_types} to apply filtering from `only` / `except`
|
321
|
-
def resolve_type(abstract_type, value =
|
322
|
-
if value.is_a?(Symbol) && value ==
|
325
|
+
def resolve_type(abstract_type, value = NOT_CONFIGURED)
|
326
|
+
if value.is_a?(Symbol) && value == NOT_CONFIGURED
|
323
327
|
# Old method signature
|
324
328
|
value = abstract_type
|
325
329
|
abstract_type = nil
|
@@ -7,9 +7,7 @@ module GraphQL
|
|
7
7
|
include GraphQL::Schema::Member::HasDirectives
|
8
8
|
include GraphQL::Schema::Member::HasDeprecationReason
|
9
9
|
include GraphQL::Schema::Member::HasValidators
|
10
|
-
include GraphQL::
|
11
|
-
|
12
|
-
NO_DEFAULT = :__no_default__
|
10
|
+
include GraphQL::EmptyObjects
|
13
11
|
|
14
12
|
# @return [String] the GraphQL name for this argument, camelized unless `camelize: false` is provided
|
15
13
|
attr_reader :name
|
@@ -20,8 +18,8 @@ module GraphQL
|
|
20
18
|
|
21
19
|
# @param new_prepare [Method, Proc]
|
22
20
|
# @return [Symbol] A method or proc to call to transform this value before sending it to field resolution method
|
23
|
-
def prepare(new_prepare =
|
24
|
-
if new_prepare !=
|
21
|
+
def prepare(new_prepare = NOT_CONFIGURED)
|
22
|
+
if new_prepare != NOT_CONFIGURED
|
25
23
|
@prepare = new_prepare
|
26
24
|
end
|
27
25
|
@prepare
|
@@ -52,7 +50,7 @@ module GraphQL
|
|
52
50
|
# @param deprecation_reason [String]
|
53
51
|
# @param validates [Hash, nil] Options for building validators, if any should be applied
|
54
52
|
# @param replace_null_with_default [Boolean] if `true`, incoming values of `null` will be replaced with the configured `default_value`
|
55
|
-
def initialize(arg_name = nil, type_expr = nil, desc = nil, required: true, type: nil, name: nil, loads: nil, description: nil, ast_node: nil, default_value:
|
53
|
+
def initialize(arg_name = nil, type_expr = nil, desc = nil, required: true, type: nil, name: nil, loads: nil, description: nil, ast_node: nil, default_value: NOT_CONFIGURED, as: nil, from_resolver: false, camelize: true, prepare: nil, owner:, validates: nil, directives: nil, deprecation_reason: nil, replace_null_with_default: false, &definition_block)
|
56
54
|
arg_name ||= name
|
57
55
|
@name = -(camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s)
|
58
56
|
@type_expr = type_expr || type
|
@@ -104,8 +102,8 @@ module GraphQL
|
|
104
102
|
|
105
103
|
# @param default_value [Object] The value to use when the client doesn't provide one
|
106
104
|
# @return [Object] the value used when the client doesn't provide a value for this argument
|
107
|
-
def default_value(new_default_value =
|
108
|
-
if new_default_value !=
|
105
|
+
def default_value(new_default_value = NOT_CONFIGURED)
|
106
|
+
if new_default_value != NOT_CONFIGURED
|
109
107
|
@default_value = new_default_value
|
110
108
|
end
|
111
109
|
@default_value
|
@@ -113,7 +111,7 @@ module GraphQL
|
|
113
111
|
|
114
112
|
# @return [Boolean] True if this argument has a default value
|
115
113
|
def default_value?
|
116
|
-
@default_value !=
|
114
|
+
@default_value != NOT_CONFIGURED
|
117
115
|
end
|
118
116
|
|
119
117
|
def replace_null_with_default?
|
@@ -21,6 +21,7 @@ module GraphQL
|
|
21
21
|
|
22
22
|
# @api private
|
23
23
|
module Builder
|
24
|
+
include GraphQL::EmptyObjects
|
24
25
|
extend self
|
25
26
|
|
26
27
|
def build(schema_superclass, document, default_resolve:, using: {}, relay:)
|
@@ -99,6 +100,16 @@ module GraphQL
|
|
99
100
|
raise InvalidDocumentError.new("Specified subscription type \"#{schema_definition.subscription}\" not found in document.") unless types[schema_definition.subscription]
|
100
101
|
subscription_root_type = types[schema_definition.subscription]
|
101
102
|
end
|
103
|
+
|
104
|
+
if schema_definition.query.nil? &&
|
105
|
+
schema_definition.mutation.nil? &&
|
106
|
+
schema_definition.subscription.nil?
|
107
|
+
# This schema may have been given with directives only,
|
108
|
+
# check for defaults:
|
109
|
+
query_root_type = types['Query']
|
110
|
+
mutation_root_type = types['Mutation']
|
111
|
+
subscription_root_type = types['Subscription']
|
112
|
+
end
|
102
113
|
else
|
103
114
|
query_root_type = types['Query']
|
104
115
|
mutation_root_type = types['Mutation']
|
@@ -107,6 +118,8 @@ module GraphQL
|
|
107
118
|
|
108
119
|
raise InvalidDocumentError.new('Must provide schema definition with query type or a type named Query.') unless query_root_type
|
109
120
|
|
121
|
+
builder = self
|
122
|
+
|
110
123
|
schema_class = Class.new(schema_superclass) do
|
111
124
|
begin
|
112
125
|
# Add these first so that there's some chance of resolving late-bound types
|
@@ -134,6 +147,7 @@ module GraphQL
|
|
134
147
|
|
135
148
|
if schema_definition
|
136
149
|
ast_node(schema_definition)
|
150
|
+
builder.build_directives(self, schema_definition, type_resolver)
|
137
151
|
end
|
138
152
|
|
139
153
|
using.each do |plugin, options|
|
@@ -361,8 +375,6 @@ module GraphQL
|
|
361
375
|
end
|
362
376
|
end
|
363
377
|
|
364
|
-
NO_DEFAULT_VALUE = {}.freeze
|
365
|
-
|
366
378
|
def build_arguments(type_class, arguments, type_resolver)
|
367
379
|
builder = self
|
368
380
|
|
@@ -370,7 +382,7 @@ module GraphQL
|
|
370
382
|
default_value_kwargs = if !argument_defn.default_value.nil?
|
371
383
|
{ default_value: builder.build_default_value(argument_defn.default_value) }
|
372
384
|
else
|
373
|
-
|
385
|
+
EMPTY_HASH
|
374
386
|
end
|
375
387
|
|
376
388
|
type_class.argument(
|
@@ -25,19 +25,16 @@ module GraphQL
|
|
25
25
|
include GraphQL::Schema::Member::HasDirectives
|
26
26
|
include GraphQL::Schema::Member::HasDeprecationReason
|
27
27
|
|
28
|
-
UNDEFINED_VALUE = Object.new.freeze
|
29
|
-
private_constant :UNDEFINED_VALUE
|
30
|
-
|
31
28
|
attr_reader :graphql_name
|
32
29
|
|
33
30
|
# @return [Class] The enum type that owns this value
|
34
31
|
attr_reader :owner
|
35
32
|
|
36
|
-
def initialize(graphql_name, desc = nil, owner:, ast_node: nil, directives: nil, description: nil, value:
|
33
|
+
def initialize(graphql_name, desc = nil, owner:, ast_node: nil, directives: nil, description: nil, value: NOT_CONFIGURED, deprecation_reason: nil, &block)
|
37
34
|
@graphql_name = graphql_name.to_s
|
38
35
|
GraphQL::NameValidator.validate!(@graphql_name)
|
39
36
|
@description = desc || description
|
40
|
-
@value = value ===
|
37
|
+
@value = value === NOT_CONFIGURED ? @graphql_name : value
|
41
38
|
if deprecation_reason
|
42
39
|
self.deprecation_reason = deprecation_reason
|
43
40
|
end
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -11,7 +11,7 @@ module GraphQL
|
|
11
11
|
include GraphQL::Schema::Member::HasPath
|
12
12
|
include GraphQL::Schema::Member::HasValidators
|
13
13
|
extend GraphQL::Schema::FindInheritedValue
|
14
|
-
include GraphQL::
|
14
|
+
include GraphQL::EmptyObjects
|
15
15
|
include GraphQL::Schema::Member::HasDirectives
|
16
16
|
include GraphQL::Schema::Member::HasDeprecationReason
|
17
17
|
|
@@ -219,7 +219,7 @@ module GraphQL
|
|
219
219
|
# @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
|
220
220
|
# @param validates [Array<Hash>] Configurations for validating this field
|
221
221
|
# @fallback_value [Object] A fallback value if the method is not defined
|
222
|
-
def initialize(type: nil, name: nil, owner: nil, null: nil, description: NOT_CONFIGURED, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, connection: nil, max_page_size: NOT_CONFIGURED, default_page_size: NOT_CONFIGURED, scope: nil, introspection: false, camelize: true, trace: nil, complexity: nil, ast_node: nil, extras: EMPTY_ARRAY, extensions: EMPTY_ARRAY, connection_extension: self.class.connection_extension, resolver_class: nil, subscription_scope: nil, relay_node_field: false, relay_nodes_field: false, method_conflict_warning: true, broadcastable: NOT_CONFIGURED, arguments: EMPTY_HASH, directives: EMPTY_HASH, validates: EMPTY_ARRAY, fallback_value:
|
222
|
+
def initialize(type: nil, name: nil, owner: nil, null: nil, description: NOT_CONFIGURED, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, connection: nil, max_page_size: NOT_CONFIGURED, default_page_size: NOT_CONFIGURED, scope: nil, introspection: false, camelize: true, trace: nil, complexity: nil, ast_node: nil, extras: EMPTY_ARRAY, extensions: EMPTY_ARRAY, connection_extension: self.class.connection_extension, resolver_class: nil, subscription_scope: nil, relay_node_field: false, relay_nodes_field: false, method_conflict_warning: true, broadcastable: NOT_CONFIGURED, arguments: EMPTY_HASH, directives: EMPTY_HASH, validates: EMPTY_ARRAY, fallback_value: NOT_CONFIGURED, &definition_block)
|
223
223
|
if name.nil?
|
224
224
|
raise ArgumentError, "missing first `name` argument or keyword `name:`"
|
225
225
|
end
|
@@ -608,15 +608,16 @@ module GraphQL
|
|
608
608
|
# The resolver _instance_ will check itself during `resolve()`
|
609
609
|
@resolver_class.authorized?(object, context)
|
610
610
|
else
|
611
|
-
if (arg_values = context[:current_arguments])
|
612
|
-
# ^^ that's provided by the interpreter at runtime, and includes info about whether the default value was used or not.
|
613
|
-
using_arg_values = true
|
614
|
-
arg_values = arg_values.argument_values
|
615
|
-
else
|
616
|
-
arg_values = args
|
617
|
-
using_arg_values = false
|
618
|
-
end
|
619
611
|
if args.size > 0
|
612
|
+
if (arg_values = context[:current_arguments])
|
613
|
+
# ^^ that's provided by the interpreter at runtime, and includes info about whether the default value was used or not.
|
614
|
+
using_arg_values = true
|
615
|
+
arg_values = arg_values.argument_values
|
616
|
+
else
|
617
|
+
arg_values = args
|
618
|
+
using_arg_values = false
|
619
|
+
end
|
620
|
+
|
620
621
|
args = context.warden.arguments(self)
|
621
622
|
args.each do |arg|
|
622
623
|
arg_key = arg.keyword
|
@@ -684,7 +685,7 @@ module GraphQL
|
|
684
685
|
if hash_value == false
|
685
686
|
hash_value
|
686
687
|
else
|
687
|
-
hash_value || (@fallback_value !=
|
688
|
+
hash_value || (@fallback_value != NOT_CONFIGURED ? @fallback_value : nil)
|
688
689
|
end
|
689
690
|
elsif obj.respond_to?(resolver_method)
|
690
691
|
method_to_call = resolver_method
|
@@ -702,7 +703,7 @@ module GraphQL
|
|
702
703
|
inner_object[@method_sym]
|
703
704
|
elsif inner_object.key?(@method_str)
|
704
705
|
inner_object[@method_str]
|
705
|
-
elsif @fallback_value !=
|
706
|
+
elsif @fallback_value != NOT_CONFIGURED
|
706
707
|
@fallback_value
|
707
708
|
else
|
708
709
|
nil
|
@@ -715,7 +716,7 @@ module GraphQL
|
|
715
716
|
else
|
716
717
|
inner_object.public_send(@method_sym)
|
717
718
|
end
|
718
|
-
elsif @fallback_value !=
|
719
|
+
elsif @fallback_value != NOT_CONFIGURED
|
719
720
|
@fallback_value
|
720
721
|
else
|
721
722
|
raise <<-ERR
|
@@ -71,14 +71,11 @@ module GraphQL
|
|
71
71
|
elsif inherited_extras
|
72
72
|
inherited_extras
|
73
73
|
else
|
74
|
-
|
74
|
+
GraphQL::EmptyObjects::EMPTY_ARRAY
|
75
75
|
end
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
-
NO_EXTRAS = [].freeze
|
80
|
-
private_constant :NO_EXTRAS
|
81
|
-
|
82
79
|
# Called when this extension is attached to a field.
|
83
80
|
# The field definition may be extended during this method.
|
84
81
|
# @return [void]
|
@@ -2,17 +2,12 @@
|
|
2
2
|
module GraphQL
|
3
3
|
class Schema
|
4
4
|
module FindInheritedValue
|
5
|
-
module EmptyObjects
|
6
|
-
EMPTY_HASH = {}.freeze
|
7
|
-
EMPTY_ARRAY = [].freeze
|
8
|
-
end
|
9
|
-
|
10
5
|
def self.extended(child_cls)
|
11
|
-
child_cls.singleton_class.include(EmptyObjects)
|
6
|
+
child_cls.singleton_class.include(GraphQL::EmptyObjects)
|
12
7
|
end
|
13
8
|
|
14
9
|
def self.included(child_cls)
|
15
|
-
child_cls.include(EmptyObjects)
|
10
|
+
child_cls.include(GraphQL::EmptyObjects)
|
16
11
|
end
|
17
12
|
|
18
13
|
private
|
@@ -33,8 +33,6 @@ module GraphQL
|
|
33
33
|
nil
|
34
34
|
end
|
35
35
|
|
36
|
-
NO_DIRECTIVES = [].freeze
|
37
|
-
|
38
36
|
def directives
|
39
37
|
HasDirectives.get_directives(self, @own_directives, :directives)
|
40
38
|
end
|
@@ -55,7 +53,7 @@ module GraphQL
|
|
55
53
|
inherited_directives = if schema_member.superclass.respond_to?(directives_method)
|
56
54
|
get_directives(schema_member.superclass, schema_member.superclass.public_send(directives_method), directives_method)
|
57
55
|
else
|
58
|
-
|
56
|
+
GraphQL::EmptyObjects::EMPTY_ARRAY
|
59
57
|
end
|
60
58
|
if inherited_directives.any? && directives
|
61
59
|
dirs = []
|
@@ -67,7 +65,7 @@ module GraphQL
|
|
67
65
|
elsif inherited_directives.any?
|
68
66
|
inherited_directives
|
69
67
|
else
|
70
|
-
|
68
|
+
GraphQL::EmptyObjects::EMPTY_ARRAY
|
71
69
|
end
|
72
70
|
when Module
|
73
71
|
dirs = nil
|
@@ -82,9 +80,9 @@ module GraphQL
|
|
82
80
|
dirs ||= []
|
83
81
|
merge_directives(dirs, directives)
|
84
82
|
end
|
85
|
-
dirs ||
|
83
|
+
dirs || GraphQL::EmptyObjects::EMPTY_ARRAY
|
86
84
|
when HasDirectives
|
87
|
-
directives ||
|
85
|
+
directives || GraphQL::EmptyObjects::EMPTY_ARRAY
|
88
86
|
else
|
89
87
|
raise "Invariant: how could #{schema_member} not be a Class, Module, or instance of HasDirectives?"
|
90
88
|
end
|
@@ -14,42 +14,6 @@ module GraphQL
|
|
14
14
|
field_defn
|
15
15
|
end
|
16
16
|
|
17
|
-
# @return [Hash<String => GraphQL::Schema::Field>] Fields on this object, keyed by name, including inherited fields
|
18
|
-
def fields(context = GraphQL::Query::NullContext)
|
19
|
-
warden = Warden.from_context(context)
|
20
|
-
is_object = self.respond_to?(:kind) && self.kind.object?
|
21
|
-
# Local overrides take precedence over inherited fields
|
22
|
-
visible_fields = {}
|
23
|
-
for ancestor in ancestors
|
24
|
-
if ancestor.respond_to?(:own_fields) &&
|
25
|
-
(is_object ? visible_interface_implementation?(ancestor, context, warden) : true)
|
26
|
-
|
27
|
-
ancestor.own_fields.each do |field_name, fields_entry|
|
28
|
-
# Choose the most local definition that passes `.visible?` --
|
29
|
-
# stop checking for fields by name once one has been found.
|
30
|
-
if !visible_fields.key?(field_name) && (f = Warden.visible_entry?(:visible_field?, fields_entry, context, warden))
|
31
|
-
visible_fields[field_name] = f
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
visible_fields
|
37
|
-
end
|
38
|
-
|
39
|
-
def get_field(field_name, context = GraphQL::Query::NullContext)
|
40
|
-
warden = Warden.from_context(context)
|
41
|
-
is_object = self.respond_to?(:kind) && self.kind.object?
|
42
|
-
for ancestor in ancestors
|
43
|
-
if ancestor.respond_to?(:own_fields) &&
|
44
|
-
(is_object ? visible_interface_implementation?(ancestor, context, warden) : true) &&
|
45
|
-
(f_entry = ancestor.own_fields[field_name]) &&
|
46
|
-
(f = Warden.visible_entry?(:visible_field?, f_entry, context, warden))
|
47
|
-
return f
|
48
|
-
end
|
49
|
-
end
|
50
|
-
nil
|
51
|
-
end
|
52
|
-
|
53
17
|
# A list of Ruby keywords.
|
54
18
|
#
|
55
19
|
# @api private
|
@@ -132,6 +96,86 @@ module GraphQL
|
|
132
96
|
all_fields
|
133
97
|
end
|
134
98
|
|
99
|
+
module InterfaceMethods
|
100
|
+
def get_field(field_name, context = GraphQL::Query::NullContext)
|
101
|
+
warden = Warden.from_context(context)
|
102
|
+
for ancestor in ancestors
|
103
|
+
if ancestor.respond_to?(:own_fields) &&
|
104
|
+
(f_entry = ancestor.own_fields[field_name]) &&
|
105
|
+
(f = Warden.visible_entry?(:visible_field?, f_entry, context, warden))
|
106
|
+
return f
|
107
|
+
end
|
108
|
+
end
|
109
|
+
nil
|
110
|
+
end
|
111
|
+
|
112
|
+
# @return [Hash<String => GraphQL::Schema::Field>] Fields on this object, keyed by name, including inherited fields
|
113
|
+
def fields(context = GraphQL::Query::NullContext)
|
114
|
+
warden = Warden.from_context(context)
|
115
|
+
# Local overrides take precedence over inherited fields
|
116
|
+
visible_fields = {}
|
117
|
+
for ancestor in ancestors
|
118
|
+
if ancestor.respond_to?(:own_fields)
|
119
|
+
ancestor.own_fields.each do |field_name, fields_entry|
|
120
|
+
# Choose the most local definition that passes `.visible?` --
|
121
|
+
# stop checking for fields by name once one has been found.
|
122
|
+
if !visible_fields.key?(field_name) && (f = Warden.visible_entry?(:visible_field?, fields_entry, context, warden))
|
123
|
+
visible_fields[field_name] = f
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
visible_fields
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
module ObjectMethods
|
133
|
+
def get_field(field_name, context = GraphQL::Query::NullContext)
|
134
|
+
# Objects need to check that the interface implementation is visible, too
|
135
|
+
warden = Warden.from_context(context)
|
136
|
+
for ancestor in ancestors
|
137
|
+
if ancestor.respond_to?(:own_fields) &&
|
138
|
+
visible_interface_implementation?(ancestor, context, warden) &&
|
139
|
+
(f_entry = ancestor.own_fields[field_name]) &&
|
140
|
+
(f = Warden.visible_entry?(:visible_field?, f_entry, context, warden))
|
141
|
+
return f
|
142
|
+
end
|
143
|
+
end
|
144
|
+
nil
|
145
|
+
end
|
146
|
+
|
147
|
+
# @return [Hash<String => GraphQL::Schema::Field>] Fields on this object, keyed by name, including inherited fields
|
148
|
+
def fields(context = GraphQL::Query::NullContext)
|
149
|
+
# Objects need to check that the interface implementation is visible, too
|
150
|
+
warden = Warden.from_context(context)
|
151
|
+
# Local overrides take precedence over inherited fields
|
152
|
+
visible_fields = {}
|
153
|
+
for ancestor in ancestors
|
154
|
+
if ancestor.respond_to?(:own_fields) && visible_interface_implementation?(ancestor, context, warden)
|
155
|
+
ancestor.own_fields.each do |field_name, fields_entry|
|
156
|
+
# Choose the most local definition that passes `.visible?` --
|
157
|
+
# stop checking for fields by name once one has been found.
|
158
|
+
if !visible_fields.key?(field_name) && (f = Warden.visible_entry?(:visible_field?, fields_entry, context, warden))
|
159
|
+
visible_fields[field_name] = f
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
visible_fields
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def self.included(child_class)
|
169
|
+
# Included in an interface definition methods module
|
170
|
+
child_class.include(InterfaceMethods)
|
171
|
+
super
|
172
|
+
end
|
173
|
+
|
174
|
+
def self.extended(child_class)
|
175
|
+
child_class.extend(ObjectMethods)
|
176
|
+
super
|
177
|
+
end
|
178
|
+
|
135
179
|
private
|
136
180
|
|
137
181
|
def inherited(subclass)
|
@@ -3,7 +3,7 @@ module GraphQL
|
|
3
3
|
class Schema
|
4
4
|
class Member
|
5
5
|
module HasValidators
|
6
|
-
include
|
6
|
+
include GraphQL::EmptyObjects
|
7
7
|
|
8
8
|
# Build {GraphQL::Schema::Validator}s based on the given configuration
|
9
9
|
# and use them for this schema member
|
@@ -28,7 +28,7 @@ module GraphQL
|
|
28
28
|
end
|
29
29
|
|
30
30
|
module ClassValidators
|
31
|
-
include
|
31
|
+
include GraphQL::EmptyObjects
|
32
32
|
|
33
33
|
def validators
|
34
34
|
inherited_validators = superclass.validators
|
@@ -311,8 +311,8 @@ module GraphQL
|
|
311
311
|
# (`nil` means "unlimited max page size".)
|
312
312
|
# @param max_page_size [Integer, nil] Set a new value
|
313
313
|
# @return [Integer, nil] The `max_page_size` assigned to fields that use this resolver
|
314
|
-
def max_page_size(new_max_page_size =
|
315
|
-
if new_max_page_size !=
|
314
|
+
def max_page_size(new_max_page_size = NOT_CONFIGURED)
|
315
|
+
if new_max_page_size != NOT_CONFIGURED
|
316
316
|
@max_page_size = new_max_page_size
|
317
317
|
elsif defined?(@max_page_size)
|
318
318
|
@max_page_size
|
@@ -332,8 +332,8 @@ module GraphQL
|
|
332
332
|
# (`nil` means "unlimited default page size".)
|
333
333
|
# @param default_page_size [Integer, nil] Set a new value
|
334
334
|
# @return [Integer, nil] The `default_page_size` assigned to fields that use this resolver
|
335
|
-
def default_page_size(new_default_page_size =
|
336
|
-
if new_default_page_size !=
|
335
|
+
def default_page_size(new_default_page_size = NOT_CONFIGURED)
|
336
|
+
if new_default_page_size != NOT_CONFIGURED
|
337
337
|
@default_page_size = new_default_page_size
|
338
338
|
elsif defined?(@default_page_size)
|
339
339
|
@default_page_size
|
@@ -38,7 +38,9 @@ module GraphQL
|
|
38
38
|
# @api private
|
39
39
|
class Warden
|
40
40
|
def self.from_context(context)
|
41
|
-
|
41
|
+
context.warden # this might be a hash which won't respond to this
|
42
|
+
rescue
|
43
|
+
PassThruWarden
|
42
44
|
end
|
43
45
|
|
44
46
|
# @param visibility_method [Symbol] a Warden method to call for this entry
|