graphql 2.0.17.2 → 2.0.21

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.

Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/analysis/ast.rb +2 -2
  3. data/lib/graphql/backtrace/trace.rb +96 -0
  4. data/lib/graphql/backtrace/tracer.rb +1 -1
  5. data/lib/graphql/backtrace.rb +6 -1
  6. data/lib/graphql/execution/interpreter/arguments.rb +1 -1
  7. data/lib/graphql/execution/interpreter/arguments_cache.rb +2 -3
  8. data/lib/graphql/execution/interpreter/resolve.rb +19 -0
  9. data/lib/graphql/execution/interpreter/runtime.rb +254 -211
  10. data/lib/graphql/execution/interpreter.rb +9 -14
  11. data/lib/graphql/execution/lazy.rb +2 -4
  12. data/lib/graphql/execution/multiplex.rb +2 -1
  13. data/lib/graphql/filter.rb +7 -2
  14. data/lib/graphql/language/document_from_schema_definition.rb +25 -9
  15. data/lib/graphql/language/lexer.rb +216 -1505
  16. data/lib/graphql/language/nodes.rb +27 -9
  17. data/lib/graphql/language/parser.rb +509 -491
  18. data/lib/graphql/language/parser.y +43 -38
  19. data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
  20. data/lib/graphql/pagination/connection.rb +5 -5
  21. data/lib/graphql/query/context.rb +62 -31
  22. data/lib/graphql/query/null_context.rb +1 -1
  23. data/lib/graphql/query.rb +22 -5
  24. data/lib/graphql/schema/argument.rb +7 -9
  25. data/lib/graphql/schema/build_from_definition.rb +15 -3
  26. data/lib/graphql/schema/enum_value.rb +2 -5
  27. data/lib/graphql/schema/field.rb +44 -31
  28. data/lib/graphql/schema/field_extension.rb +1 -4
  29. data/lib/graphql/schema/find_inherited_value.rb +2 -7
  30. data/lib/graphql/schema/member/base_dsl_methods.rb +13 -11
  31. data/lib/graphql/schema/member/has_arguments.rb +1 -1
  32. data/lib/graphql/schema/member/has_ast_node.rb +12 -0
  33. data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
  34. data/lib/graphql/schema/member/has_directives.rb +15 -10
  35. data/lib/graphql/schema/member/has_fields.rb +87 -37
  36. data/lib/graphql/schema/member/has_validators.rb +2 -2
  37. data/lib/graphql/schema/member/relay_shortcuts.rb +19 -0
  38. data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
  39. data/lib/graphql/schema/object.rb +2 -4
  40. data/lib/graphql/schema/resolver/has_payload_type.rb +9 -9
  41. data/lib/graphql/schema/resolver.rb +4 -4
  42. data/lib/graphql/schema/timeout.rb +24 -28
  43. data/lib/graphql/schema/validator.rb +1 -1
  44. data/lib/graphql/schema/warden.rb +11 -2
  45. data/lib/graphql/schema.rb +72 -1
  46. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
  47. data/lib/graphql/static_validation/rules/fields_will_merge.rb +2 -2
  48. data/lib/graphql/static_validation/validator.rb +1 -1
  49. data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
  50. data/lib/graphql/tracing/appoptics_trace.rb +231 -0
  51. data/lib/graphql/tracing/appsignal_trace.rb +77 -0
  52. data/lib/graphql/tracing/data_dog_trace.rb +148 -0
  53. data/lib/graphql/tracing/legacy_trace.rb +65 -0
  54. data/lib/graphql/tracing/new_relic_trace.rb +75 -0
  55. data/lib/graphql/tracing/notifications_trace.rb +42 -0
  56. data/lib/graphql/tracing/platform_trace.rb +109 -0
  57. data/lib/graphql/tracing/platform_tracing.rb +15 -3
  58. data/lib/graphql/tracing/prometheus_trace.rb +89 -0
  59. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +1 -1
  60. data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
  61. data/lib/graphql/tracing/scout_trace.rb +72 -0
  62. data/lib/graphql/tracing/statsd_trace.rb +56 -0
  63. data/lib/graphql/tracing/trace.rb +75 -0
  64. data/lib/graphql/tracing.rb +16 -39
  65. data/lib/graphql/type_kinds.rb +6 -3
  66. data/lib/graphql/types/relay/base_connection.rb +1 -1
  67. data/lib/graphql/types/relay/connection_behaviors.rb +24 -2
  68. data/lib/graphql/types/relay/edge_behaviors.rb +16 -2
  69. data/lib/graphql/types/relay/node_behaviors.rb +7 -1
  70. data/lib/graphql/types/relay/page_info_behaviors.rb +7 -2
  71. data/lib/graphql/types/relay.rb +0 -1
  72. data/lib/graphql/version.rb +1 -1
  73. data/lib/graphql.rb +16 -9
  74. metadata +33 -8
  75. data/lib/graphql/language/lexer.rl +0 -280
  76. data/lib/graphql/types/relay/default_relay.rb +0 -27
@@ -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_given, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, connection: nil, max_page_size: :not_given, default_page_size: :not_given, 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: nil, 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
@@ -233,9 +233,10 @@ module GraphQL
233
233
 
234
234
  @underscored_name = -Member::BuildType.underscore(name_s)
235
235
  @name = -(camelize ? Member::BuildType.camelize(name_s) : name_s)
236
- if description != :not_given
237
- @description = description
238
- end
236
+
237
+ @description = description
238
+ @type = @owner_type = @own_validators = @own_directives = @own_arguments = nil # these will be prepared later if necessary
239
+
239
240
  self.deprecation_reason = deprecation_reason
240
241
 
241
242
  if method && hash_key && dig
@@ -257,6 +258,9 @@ module GraphQL
257
258
  if hash_key
258
259
  @hash_key = hash_key
259
260
  @hash_key_str = hash_key.to_s
261
+ else
262
+ @hash_key = NOT_CONFIGURED
263
+ @hash_key_str = NOT_CONFIGURED
260
264
  end
261
265
 
262
266
  @method_str = -method_name.to_s
@@ -272,15 +276,11 @@ module GraphQL
272
276
  true
273
277
  end
274
278
  @connection = connection
275
- @has_max_page_size = max_page_size != :not_given
276
- @max_page_size = max_page_size == :not_given ? nil : max_page_size
277
- @has_default_page_size = default_page_size != :not_given
278
- @default_page_size = default_page_size == :not_given ? nil : default_page_size
279
+ @max_page_size = max_page_size
280
+ @default_page_size = default_page_size
279
281
  @introspection = introspection
280
282
  @extras = extras
281
- if !broadcastable.nil?
282
- @broadcastable = broadcastable
283
- end
283
+ @broadcastable = broadcastable
284
284
  @resolver_class = resolver_class
285
285
  @scope = scope
286
286
  @trace = trace
@@ -355,7 +355,7 @@ module GraphQL
355
355
  # @return [Boolean, nil]
356
356
  # @see GraphQL::Subscriptions::BroadcastAnalyzer
357
357
  def broadcastable?
358
- if defined?(@broadcastable)
358
+ if !NOT_CONFIGURED.equal?(@broadcastable)
359
359
  @broadcastable
360
360
  elsif @resolver_class
361
361
  @resolver_class.broadcastable?
@@ -369,10 +369,10 @@ module GraphQL
369
369
  def description(text = nil)
370
370
  if text
371
371
  @description = text
372
- elsif defined?(@description)
372
+ elsif !NOT_CONFIGURED.equal?(@description)
373
373
  @description
374
374
  elsif @resolver_class
375
- @description || @resolver_class.description
375
+ @resolver_class.description
376
376
  else
377
377
  nil
378
378
  end
@@ -544,22 +544,34 @@ module GraphQL
544
544
 
545
545
  # @return [Boolean] True if this field's {#max_page_size} should override the schema default.
546
546
  def has_max_page_size?
547
- @has_max_page_size || (@resolver_class && @resolver_class.has_max_page_size?)
547
+ !NOT_CONFIGURED.equal?(@max_page_size) || (@resolver_class && @resolver_class.has_max_page_size?)
548
548
  end
549
549
 
550
550
  # @return [Integer, nil] Applied to connections if {#has_max_page_size?}
551
551
  def max_page_size
552
- @max_page_size || (@resolver_class && @resolver_class.max_page_size)
552
+ if !NOT_CONFIGURED.equal?(@max_page_size)
553
+ @max_page_size
554
+ elsif @resolver_class && @resolver_class.has_max_page_size?
555
+ @resolver_class.max_page_size
556
+ else
557
+ nil
558
+ end
553
559
  end
554
560
 
555
561
  # @return [Boolean] True if this field's {#default_page_size} should override the schema default.
556
562
  def has_default_page_size?
557
- @has_default_page_size || (@resolver_class && @resolver_class.has_default_page_size?)
563
+ !NOT_CONFIGURED.equal?(@default_page_size) || (@resolver_class && @resolver_class.has_default_page_size?)
558
564
  end
559
565
 
560
566
  # @return [Integer, nil] Applied to connections if {#has_default_page_size?}
561
567
  def default_page_size
562
- @default_page_size || (@resolver_class && @resolver_class.default_page_size)
568
+ if !NOT_CONFIGURED.equal?(@default_page_size)
569
+ @default_page_size
570
+ elsif @resolver_class && @resolver_class.has_default_page_size?
571
+ @resolver_class.default_page_size
572
+ else
573
+ nil
574
+ end
563
575
  end
564
576
 
565
577
  class MissingReturnTypeError < GraphQL::Error; end
@@ -596,15 +608,16 @@ module GraphQL
596
608
  # The resolver _instance_ will check itself during `resolve()`
597
609
  @resolver_class.authorized?(object, context)
598
610
  else
599
- if (arg_values = context[:current_arguments])
600
- # ^^ that's provided by the interpreter at runtime, and includes info about whether the default value was used or not.
601
- using_arg_values = true
602
- arg_values = arg_values.argument_values
603
- else
604
- arg_values = args
605
- using_arg_values = false
606
- end
607
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
+
608
621
  args = context.warden.arguments(self)
609
622
  args.each do |arg|
610
623
  arg_key = arg.keyword
@@ -661,7 +674,7 @@ module GraphQL
661
674
 
662
675
  inner_object = obj.object
663
676
 
664
- if defined?(@hash_key)
677
+ if !NOT_CONFIGURED.equal?(@hash_key)
665
678
  hash_value = if inner_object.is_a?(Hash)
666
679
  inner_object.key?(@hash_key) ? inner_object[@hash_key] : inner_object[@hash_key_str]
667
680
  elsif inner_object.respond_to?(:[])
@@ -672,7 +685,7 @@ module GraphQL
672
685
  if hash_value == false
673
686
  hash_value
674
687
  else
675
- hash_value || (@fallback_value != :not_given ? @fallback_value : nil)
688
+ hash_value || (@fallback_value != NOT_CONFIGURED ? @fallback_value : nil)
676
689
  end
677
690
  elsif obj.respond_to?(resolver_method)
678
691
  method_to_call = resolver_method
@@ -690,7 +703,7 @@ module GraphQL
690
703
  inner_object[@method_sym]
691
704
  elsif inner_object.key?(@method_str)
692
705
  inner_object[@method_str]
693
- elsif @fallback_value != :not_given
706
+ elsif @fallback_value != NOT_CONFIGURED
694
707
  @fallback_value
695
708
  else
696
709
  nil
@@ -703,7 +716,7 @@ module GraphQL
703
716
  else
704
717
  inner_object.public_send(@method_sym)
705
718
  end
706
- elsif @fallback_value != :not_given
719
+ elsif @fallback_value != NOT_CONFIGURED
707
720
  @fallback_value
708
721
  else
709
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
@@ -46,7 +46,7 @@ module GraphQL
46
46
  elsif defined?(@description)
47
47
  @description
48
48
  else
49
- nil
49
+ @description = nil
50
50
  end
51
51
  end
52
52
 
@@ -56,8 +56,12 @@ module GraphQL
56
56
  def inherited(child_class)
57
57
  child_class.introspection(introspection)
58
58
  child_class.description(description)
59
- if defined?(@graphql_name) && (self.name.nil? || graphql_name != default_graphql_name)
59
+ child_class.default_graphql_name = nil
60
+
61
+ if defined?(@graphql_name) && @graphql_name && (self.name.nil? || graphql_name != default_graphql_name)
60
62
  child_class.graphql_name(graphql_name)
63
+ else
64
+ child_class.graphql_name = nil
61
65
  end
62
66
  super
63
67
  end
@@ -98,7 +102,8 @@ module GraphQL
98
102
  def default_graphql_name
99
103
  @default_graphql_name ||= begin
100
104
  raise GraphQL::RequiredImplementationMissingError, 'Anonymous class should declare a `graphql_name`' if name.nil?
101
- -name.split("::").last.sub(/Type\Z/, "") end
105
+ -name.split("::").last.sub(/Type\Z/, "")
106
+ end
102
107
  end
103
108
 
104
109
  def visible?(context)
@@ -109,16 +114,13 @@ module GraphQL
109
114
  true
110
115
  end
111
116
 
112
- protected
113
-
114
- attr_writer :default_graphql_name
117
+ def default_relay
118
+ false
119
+ end
115
120
 
116
- private
121
+ protected
117
122
 
118
- def inherited(subclass)
119
- super
120
- subclass.default_graphql_name = nil
121
- end
123
+ attr_writer :default_graphql_name, :graphql_name
122
124
  end
123
125
  end
124
126
  end
@@ -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
@@ -3,6 +3,16 @@ module GraphQL
3
3
  class Schema
4
4
  class Member
5
5
  module HasAstNode
6
+ def self.extended(child_cls)
7
+ super
8
+ child_cls.ast_node = nil
9
+ end
10
+
11
+ def inherited(child_cls)
12
+ super
13
+ child_cls.ast_node = nil
14
+ end
15
+
6
16
  # If this schema was parsed from a `.graphql` file (or other SDL),
7
17
  # this is the AST node that defined this part of the schema.
8
18
  def ast_node(new_ast_node = nil)
@@ -14,6 +24,8 @@ module GraphQL
14
24
  nil
15
25
  end
16
26
  end
27
+
28
+ attr_writer :ast_node
17
29
  end
18
30
  end
19
31
  end
@@ -5,17 +5,16 @@ module GraphQL
5
5
  class Member
6
6
  module HasDeprecationReason
7
7
  # @return [String, nil] Explains why this member was deprecated (if present, this will be marked deprecated in introspection)
8
- def deprecation_reason
9
- dir = self.directives.find { |d| d.is_a?(GraphQL::Schema::Directive::Deprecated) }
10
- dir && dir.arguments[:reason] # rubocop:disable Development/ContextIsPassedCop -- definition-related
11
- end
8
+ attr_reader :deprecation_reason
12
9
 
13
10
  # Set the deprecation reason for this member, or remove it by assigning `nil`
14
11
  # @param text [String, nil]
15
12
  def deprecation_reason=(text)
13
+ @deprecation_reason = text
16
14
  if text.nil?
17
15
  remove_directive(GraphQL::Schema::Directive::Deprecated)
18
16
  else
17
+ # This removes a previously-attached directive, if there is one:
19
18
  directive(GraphQL::Schema::Directive::Deprecated, reason: text)
20
19
  end
21
20
  end
@@ -4,6 +4,16 @@ module GraphQL
4
4
  class Schema
5
5
  class Member
6
6
  module HasDirectives
7
+ def self.extended(child_cls)
8
+ super
9
+ child_cls.module_eval { self.own_directives = nil }
10
+ end
11
+
12
+ def inherited(child_cls)
13
+ super
14
+ child_cls.own_directives = nil
15
+ end
16
+
7
17
  # Create an instance of `dir_class` for `self`, using `options`.
8
18
  #
9
19
  # It removes a previously-attached instance of `dir_class`, if there is one.
@@ -23,8 +33,6 @@ module GraphQL
23
33
  nil
24
34
  end
25
35
 
26
- NO_DIRECTIVES = [].freeze
27
-
28
36
  def directives
29
37
  HasDirectives.get_directives(self, @own_directives, :directives)
30
38
  end
@@ -45,7 +53,7 @@ module GraphQL
45
53
  inherited_directives = if schema_member.superclass.respond_to?(directives_method)
46
54
  get_directives(schema_member.superclass, schema_member.superclass.public_send(directives_method), directives_method)
47
55
  else
48
- NO_DIRECTIVES
56
+ GraphQL::EmptyObjects::EMPTY_ARRAY
49
57
  end
50
58
  if inherited_directives.any? && directives
51
59
  dirs = []
@@ -57,7 +65,7 @@ module GraphQL
57
65
  elsif inherited_directives.any?
58
66
  inherited_directives
59
67
  else
60
- NO_DIRECTIVES
68
+ GraphQL::EmptyObjects::EMPTY_ARRAY
61
69
  end
62
70
  when Module
63
71
  dirs = nil
@@ -72,9 +80,9 @@ module GraphQL
72
80
  dirs ||= []
73
81
  merge_directives(dirs, directives)
74
82
  end
75
- dirs || NO_DIRECTIVES
83
+ dirs || GraphQL::EmptyObjects::EMPTY_ARRAY
76
84
  when HasDirectives
77
- directives || NO_DIRECTIVES
85
+ directives || GraphQL::EmptyObjects::EMPTY_ARRAY
78
86
  else
79
87
  raise "Invariant: how could #{schema_member} not be a Class, Module, or instance of HasDirectives?"
80
88
  end
@@ -101,12 +109,9 @@ module GraphQL
101
109
  end
102
110
  end
103
111
 
104
-
105
112
  protected
106
113
 
107
- def own_directives
108
- @own_directives
109
- end
114
+ attr_accessor :own_directives
110
115
  end
111
116
  end
112
117
  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
@@ -72,7 +36,12 @@ module GraphQL
72
36
  def add_field(field_defn, method_conflict_warning: field_defn.method_conflict_warning?)
73
37
  # Check that `field_defn.original_name` equals `resolver_method` and `method_sym` --
74
38
  # that shows that no override value was given manually.
75
- if method_conflict_warning && CONFLICT_FIELD_NAMES.include?(field_defn.resolver_method) && field_defn.original_name == field_defn.resolver_method && field_defn.original_name == field_defn.method_sym && field_defn.hash_key.nil? && field_defn.dig_keys.nil?
39
+ if method_conflict_warning &&
40
+ CONFLICT_FIELD_NAMES.include?(field_defn.resolver_method) &&
41
+ field_defn.original_name == field_defn.resolver_method &&
42
+ field_defn.original_name == field_defn.method_sym &&
43
+ field_defn.hash_key == NOT_CONFIGURED &&
44
+ field_defn.dig_keys.nil?
76
45
  warn(conflict_field_name_warning(field_defn))
77
46
  end
78
47
  prev_defn = own_fields[field_defn.name]
@@ -127,12 +96,93 @@ module GraphQL
127
96
  all_fields
128
97
  end
129
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
+
130
179
  private
131
180
 
132
181
  def inherited(subclass)
133
182
  super
134
183
  subclass.class_eval do
135
184
  @own_fields ||= nil
185
+ @field_class ||= nil
136
186
  end
137
187
  end
138
188
 
@@ -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
@@ -6,6 +6,7 @@ module GraphQL
6
6
  module RelayShortcuts
7
7
  def edge_type_class(new_edge_type_class = nil)
8
8
  if new_edge_type_class
9
+ initialize_relay_metadata
9
10
  @edge_type_class = new_edge_type_class
10
11
  else
11
12
  # Don't call `ancestor.edge_type_class`
@@ -22,6 +23,7 @@ module GraphQL
22
23
 
23
24
  def connection_type_class(new_connection_type_class = nil)
24
25
  if new_connection_type_class
26
+ initialize_relay_metadata
25
27
  @connection_type_class = new_connection_type_class
26
28
  else
27
29
  # Don't call `ancestor.connection_type_class`
@@ -37,6 +39,7 @@ module GraphQL
37
39
  end
38
40
 
39
41
  def edge_type
42
+ initialize_relay_metadata
40
43
  @edge_type ||= begin
41
44
  edge_name = self.graphql_name + "Edge"
42
45
  node_type_class = self
@@ -48,6 +51,7 @@ module GraphQL
48
51
  end
49
52
 
50
53
  def connection_type
54
+ initialize_relay_metadata
51
55
  @connection_type ||= begin
52
56
  conn_name = self.graphql_name + "Connection"
53
57
  edge_type_class = self.edge_type
@@ -67,6 +71,21 @@ module GraphQL
67
71
  def configured_edge_type_class
68
72
  @edge_type_class
69
73
  end
74
+
75
+ attr_writer :edge_type, :connection_type, :connection_type_class, :edge_type_class
76
+
77
+ private
78
+
79
+ # If one of thse values is accessed, initialize all the instance variables to retain
80
+ # a consistent object shape.
81
+ def initialize_relay_metadata
82
+ if !defined?(@connection_type)
83
+ @connection_type = nil
84
+ @edge_type = nil
85
+ @connection_type_class = nil
86
+ @edge_type_class = nil
87
+ end
88
+ end
70
89
  end
71
90
  end
72
91
  end
@@ -43,11 +43,11 @@ module GraphQL
43
43
  private
44
44
 
45
45
  def inherited(subclass)
46
- super
47
46
  subclass.class_eval do
48
47
  @to_non_null_type ||= nil
49
48
  @to_list_type ||= nil
50
49
  end
50
+ super
51
51
  end
52
52
  end
53
53
  end
@@ -48,9 +48,7 @@ module GraphQL
48
48
  # @return [GraphQL::Schema::Object, GraphQL::Execution::Lazy]
49
49
  # @raise [GraphQL::UnauthorizedError] if the user-provided hook returns `false`
50
50
  def authorized_new(object, context)
51
- trace_payload = { context: context, type: self, object: object, path: context[:current_path] }
52
-
53
- maybe_lazy_auth_val = context.query.trace("authorized", trace_payload) do
51
+ maybe_lazy_auth_val = context.query.current_trace.authorized(query: context.query, type: self, object: object) do
54
52
  begin
55
53
  authorized?(object, context)
56
54
  rescue GraphQL::UnauthorizedError => err
@@ -62,7 +60,7 @@ module GraphQL
62
60
 
63
61
  auth_val = if context.schema.lazy?(maybe_lazy_auth_val)
64
62
  GraphQL::Execution::Lazy.new do
65
- context.query.trace("authorized_lazy", trace_payload) do
63
+ context.query.current_trace.authorized_lazy(query: context.query, type: self, object: object) do
66
64
  context.schema.sync_lazy(maybe_lazy_auth_val)
67
65
  end
68
66
  end