graphql 2.0.20 → 2.0.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/backtrace/trace.rb +96 -0
  3. data/lib/graphql/backtrace.rb +6 -1
  4. data/lib/graphql/execution/interpreter/arguments.rb +1 -1
  5. data/lib/graphql/execution/interpreter/arguments_cache.rb +2 -3
  6. data/lib/graphql/execution/interpreter/runtime.rb +200 -161
  7. data/lib/graphql/execution/interpreter.rb +1 -1
  8. data/lib/graphql/filter.rb +7 -2
  9. data/lib/graphql/language/document_from_schema_definition.rb +25 -9
  10. data/lib/graphql/language/nodes.rb +2 -2
  11. data/lib/graphql/language/parser.rb +475 -458
  12. data/lib/graphql/language/parser.y +5 -1
  13. data/lib/graphql/pagination/connection.rb +5 -5
  14. data/lib/graphql/query/context.rb +13 -12
  15. data/lib/graphql/query/null_context.rb +1 -1
  16. data/lib/graphql/query.rb +9 -5
  17. data/lib/graphql/schema/argument.rb +7 -9
  18. data/lib/graphql/schema/build_from_definition.rb +15 -3
  19. data/lib/graphql/schema/enum_value.rb +2 -5
  20. data/lib/graphql/schema/field.rb +14 -13
  21. data/lib/graphql/schema/field_extension.rb +1 -4
  22. data/lib/graphql/schema/find_inherited_value.rb +2 -7
  23. data/lib/graphql/schema/member/has_arguments.rb +1 -1
  24. data/lib/graphql/schema/member/has_directives.rb +4 -6
  25. data/lib/graphql/schema/member/has_fields.rb +80 -36
  26. data/lib/graphql/schema/member/has_validators.rb +2 -2
  27. data/lib/graphql/schema/resolver.rb +4 -4
  28. data/lib/graphql/schema/validator.rb +1 -1
  29. data/lib/graphql/schema/warden.rb +3 -1
  30. data/lib/graphql/schema.rb +40 -11
  31. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
  32. data/lib/graphql/static_validation/rules/fields_will_merge.rb +2 -2
  33. data/lib/graphql/tracing/appsignal_trace.rb +6 -0
  34. data/lib/graphql/tracing/legacy_trace.rb +65 -0
  35. data/lib/graphql/tracing/notifications_trace.rb +2 -1
  36. data/lib/graphql/tracing/platform_trace.rb +21 -19
  37. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +1 -1
  38. data/lib/graphql/tracing/trace.rb +75 -0
  39. data/lib/graphql/tracing.rb +3 -123
  40. data/lib/graphql/version.rb +1 -1
  41. data/lib/graphql.rb +4 -0
  42. metadata +5 -2
@@ -284,7 +284,11 @@ rule
284
284
  | directive_definition
285
285
 
286
286
  schema_definition:
287
- SCHEMA directives_list_opt LCURLY operation_type_definition_list RCURLY { result = make_node(:SchemaDefinition, position_source: val[0], definition_line: val[0][1], directives: val[1], **val[3]) }
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: :not_given, default_page_size: :not_given, last: nil, before: nil, edge_class: nil, arguments: nil)
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 != :not_given
75
- @max_page_size = if max_page_size == :not_given
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 != :not_given
81
- @default_page_size = if default_page_size == :not_given
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 = [].freeze
95
- NO_CONTEXT = {}.freeze
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
- thread_info = Thread.current[:__graphql_runtime_info]
230
- thread_info && thread_info[key]
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
- thread_info = Thread.current[:__graphql_runtime_info]
240
- path = thread_info &&
241
- (result = thread_info[:current_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 = thread_info[:current_result_name])
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
- (thread_info = Thread.current[:__graphql_runtime_info]) &&
263
- thread_info[key]
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
- (thread_info = Thread.current[:__graphql_runtime_info]).key?(key) &&
280
- thread_info.dig(key, *other_keys)
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
@@ -24,7 +24,7 @@ module GraphQL
24
24
  @dataloader = GraphQL::Dataloader::NullDataloader.new
25
25
  @schema = NullSchema
26
26
  @warden = NullWarden.new(
27
- GraphQL::Filter.new,
27
+ GraphQL::Filter.new(silence_deprecation_warning: true),
28
28
  context: self,
29
29
  schema: @schema,
30
30
  )
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
- context_tracers += [GraphQL::Backtrace::Tracer]
104
- @tracers << GraphQL::Backtrace::Tracer
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] and context[:backtrace] are not supported without `tracer_class(GraphQL::Tracing::LegacyTrace)` in the schema configuration, please add it."
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 = :__undefined__)
322
- if value.is_a?(Symbol) && value == :__undefined__
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::Schema::FindInheritedValue::EmptyObjects
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 = NO_DEFAULT)
24
- if new_prepare != NO_DEFAULT
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: NO_DEFAULT, as: nil, from_resolver: false, camelize: true, prepare: nil, owner:, validates: nil, directives: nil, deprecation_reason: nil, replace_null_with_default: false, &definition_block)
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 = NO_DEFAULT)
108
- if new_default_value != NO_DEFAULT
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 != NO_DEFAULT
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
- NO_DEFAULT_VALUE
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: UNDEFINED_VALUE, deprecation_reason: nil, &block)
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 === UNDEFINED_VALUE ? @graphql_name : value
37
+ @value = value === NOT_CONFIGURED ? @graphql_name : value
41
38
  if deprecation_reason
42
39
  self.deprecation_reason = deprecation_reason
43
40
  end
@@ -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::Schema::FindInheritedValue::EmptyObjects
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: :not_given, &definition_block)
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 != :not_given ? @fallback_value : nil)
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 != :not_given
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 != :not_given
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
- NO_EXTRAS
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
@@ -413,7 +413,7 @@ module GraphQL
413
413
  end
414
414
  end
415
415
 
416
- NO_ARGUMENTS = {}.freeze
416
+ NO_ARGUMENTS = GraphQL::EmptyObjects::EMPTY_HASH
417
417
  def own_arguments
418
418
  @own_arguments || NO_ARGUMENTS
419
419
  end
@@ -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
- NO_DIRECTIVES
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
- NO_DIRECTIVES
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 || NO_DIRECTIVES
83
+ dirs || GraphQL::EmptyObjects::EMPTY_ARRAY
86
84
  when HasDirectives
87
- directives || NO_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 Schema::FindInheritedValue::EmptyObjects
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 Schema::FindInheritedValue::EmptyObjects
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 = :not_given)
315
- if new_max_page_size != :not_given
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 = :not_given)
336
- if new_default_page_size != :not_given
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
@@ -102,7 +102,7 @@ module GraphQL
102
102
 
103
103
  self.all_validators = {}
104
104
 
105
- include Schema::FindInheritedValue::EmptyObjects
105
+ include GraphQL::EmptyObjects
106
106
 
107
107
  class ValidationFailedError < GraphQL::ExecutionError
108
108
  attr_reader :errors
@@ -38,7 +38,9 @@ module GraphQL
38
38
  # @api private
39
39
  class Warden
40
40
  def self.from_context(context)
41
- (context.respond_to?(:warden) && context.warden) || PassThruWarden
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