graphql 2.3.7 → 2.3.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/analysis/field_usage.rb +1 -1
  3. data/lib/graphql/analysis/query_complexity.rb +3 -3
  4. data/lib/graphql/analysis/visitor.rb +7 -6
  5. data/lib/graphql/execution/interpreter/runtime.rb +6 -6
  6. data/lib/graphql/execution/lookahead.rb +10 -10
  7. data/lib/graphql/introspection/directive_type.rb +1 -1
  8. data/lib/graphql/introspection/entry_points.rb +2 -2
  9. data/lib/graphql/introspection/field_type.rb +1 -1
  10. data/lib/graphql/introspection/schema_type.rb +13 -3
  11. data/lib/graphql/introspection/type_type.rb +5 -5
  12. data/lib/graphql/language/document_from_schema_definition.rb +19 -26
  13. data/lib/graphql/language/lexer.rb +0 -3
  14. data/lib/graphql/language/sanitized_printer.rb +1 -1
  15. data/lib/graphql/language.rb +0 -1
  16. data/lib/graphql/query/context.rb +4 -0
  17. data/lib/graphql/query/null_context.rb +4 -0
  18. data/lib/graphql/query.rb +26 -3
  19. data/lib/graphql/schema/always_visible.rb +1 -0
  20. data/lib/graphql/schema/enum.rb +4 -4
  21. data/lib/graphql/schema/field.rb +1 -1
  22. data/lib/graphql/schema/has_single_input_argument.rb +2 -1
  23. data/lib/graphql/schema/input_object.rb +8 -7
  24. data/lib/graphql/schema/introspection_system.rb +2 -14
  25. data/lib/graphql/schema/member/has_arguments.rb +7 -6
  26. data/lib/graphql/schema/member/has_fields.rb +6 -4
  27. data/lib/graphql/schema/resolver.rb +4 -5
  28. data/lib/graphql/schema/subset.rb +397 -0
  29. data/lib/graphql/schema/type_expression.rb +2 -2
  30. data/lib/graphql/schema/validator/all_validator.rb +60 -0
  31. data/lib/graphql/schema/validator.rb +2 -0
  32. data/lib/graphql/schema/warden.rb +88 -1
  33. data/lib/graphql/schema.rb +44 -15
  34. data/lib/graphql/static_validation/base_visitor.rb +6 -5
  35. data/lib/graphql/static_validation/literal_validator.rb +4 -4
  36. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
  37. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
  38. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -2
  39. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
  40. data/lib/graphql/static_validation/rules/fields_will_merge.rb +7 -7
  41. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  42. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
  43. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
  44. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
  45. data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
  46. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +3 -3
  47. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +3 -3
  48. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
  49. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +1 -1
  50. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  51. data/lib/graphql/static_validation/validation_context.rb +2 -2
  52. data/lib/graphql/subscriptions/broadcast_analyzer.rb +10 -4
  53. data/lib/graphql/subscriptions/event.rb +1 -1
  54. data/lib/graphql/subscriptions.rb +2 -2
  55. data/lib/graphql/testing/helpers.rb +2 -2
  56. data/lib/graphql/types/relay/connection_behaviors.rb +10 -0
  57. data/lib/graphql/types/relay/edge_behaviors.rb +10 -0
  58. data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
  59. data/lib/graphql/version.rb +1 -1
  60. metadata +4 -4
  61. data/lib/graphql/language/token.rb +0 -34
  62. data/lib/graphql/schema/invalid_type_error.rb +0 -7
@@ -61,14 +61,27 @@ module GraphQL
61
61
  def interface_type_memberships(obj_t, ctx); obj_t.interface_type_memberships; end
62
62
  def arguments(owner, ctx); owner.arguments(ctx); end
63
63
  def loadable?(type, ctx); type.visible?(ctx); end
64
+ def schema_subset
65
+ @schema_subset ||= Warden::SchemaSubset.new(self)
66
+ end
64
67
  end
65
68
  end
66
69
 
67
70
  class NullWarden
68
71
  def initialize(_filter = nil, context:, schema:)
69
72
  @schema = schema
73
+ @schema_subset = Warden::SchemaSubset.new(self)
74
+ end
75
+
76
+ # @api private
77
+ module NullSubset
78
+ def self.new(query)
79
+ NullWarden.new(context: query.context, schema: query.schema).schema_subset
80
+ end
70
81
  end
71
82
 
83
+ attr_reader :schema_subset
84
+
72
85
  def visible_field?(field_defn, _ctx = nil, owner = nil); true; end
73
86
  def visible_argument?(arg_defn, _ctx = nil); true; end
74
87
  def visible_type?(type_defn, _ctx = nil); true; end
@@ -91,6 +104,80 @@ module GraphQL
91
104
  def interfaces(obj_type); obj_type.interfaces; end
92
105
  end
93
106
 
107
+ def schema_subset
108
+ @schema_subset ||= SchemaSubset.new(self)
109
+ end
110
+
111
+ class SchemaSubset
112
+ def initialize(warden)
113
+ @warden = warden
114
+ end
115
+
116
+ def directives
117
+ @warden.directives
118
+ end
119
+
120
+ def directive_exists?(dir_name)
121
+ @warden.directives.any? { |d| d.graphql_name == dir_name }
122
+ end
123
+
124
+ def type(name)
125
+ @warden.get_type(name)
126
+ end
127
+
128
+ def field(owner, field_name)
129
+ @warden.get_field(owner, field_name)
130
+ end
131
+
132
+ def argument(owner, arg_name)
133
+ @warden.get_argument(owner, arg_name)
134
+ end
135
+
136
+ def query_root
137
+ @warden.root_type_for_operation("query")
138
+ end
139
+
140
+ def mutation_root
141
+ @warden.root_type_for_operation("mutation")
142
+ end
143
+
144
+ def subscription_root
145
+ @warden.root_type_for_operation("subscription")
146
+ end
147
+
148
+ def arguments(owner)
149
+ @warden.arguments(owner)
150
+ end
151
+
152
+ def fields(owner)
153
+ @warden.fields(owner)
154
+ end
155
+
156
+ def possible_types(type)
157
+ @warden.possible_types(type)
158
+ end
159
+
160
+ def enum_values(enum_type)
161
+ @warden.enum_values(enum_type)
162
+ end
163
+
164
+ def all_types
165
+ @warden.reachable_types
166
+ end
167
+
168
+ def interfaces(obj_type)
169
+ @warden.interfaces(obj_type)
170
+ end
171
+
172
+ def loadable?(t, ctx) # TODO remove ctx here?
173
+ @warden.loadable?(t, ctx)
174
+ end
175
+
176
+ def reachable_type?(type_name)
177
+ @warden.reachable_type?(type_name)
178
+ end
179
+ end
180
+
94
181
  # @param context [GraphQL::Query::Context]
95
182
  # @param schema [GraphQL::Schema]
96
183
  def initialize(context:, schema:)
@@ -107,7 +194,7 @@ module GraphQL
107
194
  @visible_possible_types = @visible_fields = @visible_arguments = @visible_enum_arrays =
108
195
  @visible_enum_values = @visible_interfaces = @type_visibility = @type_memberships =
109
196
  @visible_and_reachable_type = @unions = @unfiltered_interfaces =
110
- @reachable_type_set =
197
+ @reachable_type_set = @schema_subset =
111
198
  nil
112
199
  end
113
200
 
@@ -5,7 +5,6 @@ require "graphql/schema/always_visible"
5
5
  require "graphql/schema/base_64_encoder"
6
6
  require "graphql/schema/find_inherited_value"
7
7
  require "graphql/schema/finder"
8
- require "graphql/schema/invalid_type_error"
9
8
  require "graphql/schema/introspection_system"
10
9
  require "graphql/schema/late_bound_type"
11
10
  require "graphql/schema/null_mask"
@@ -46,6 +45,7 @@ require "graphql/schema/mutation"
46
45
  require "graphql/schema/has_single_input_argument"
47
46
  require "graphql/schema/relay_classic_mutation"
48
47
  require "graphql/schema/subscription"
48
+ require "graphql/schema/subset"
49
49
 
50
50
  module GraphQL
51
51
  # A GraphQL schema which may be queried with {GraphQL::Query}.
@@ -370,20 +370,24 @@ module GraphQL
370
370
  when nil
371
371
  nil
372
372
  when Array
373
- visible_t = nil
374
- warden = Warden.from_context(context)
375
- local_entry.each do |t|
376
- if warden.visible_type?(t, context)
377
- if visible_t.nil?
378
- visible_t = t
379
- else
380
- raise DuplicateNamesError.new(
381
- duplicated_name: type_name, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
382
- )
373
+ if context.respond_to?(:types) && context.types.is_a?(GraphQL::Schema::Subset)
374
+ local_entry
375
+ else
376
+ visible_t = nil
377
+ warden = Warden.from_context(context)
378
+ local_entry.each do |t|
379
+ if warden.visible_type?(t, context)
380
+ if visible_t.nil?
381
+ visible_t = t
382
+ else
383
+ raise DuplicateNamesError.new(
384
+ duplicated_name: type_name, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
385
+ )
386
+ end
383
387
  end
384
388
  end
389
+ visible_t
385
390
  end
386
- visible_t
387
391
  when Module
388
392
  local_entry
389
393
  else
@@ -497,6 +501,28 @@ module GraphQL
497
501
 
498
502
  attr_writer :warden_class
499
503
 
504
+ def subset_class
505
+ if defined?(@subset_class)
506
+ @subset_class
507
+ elsif superclass.respond_to?(:subset_class)
508
+ superclass.subset_class
509
+ else
510
+ GraphQL::Schema::Subset
511
+ end
512
+ end
513
+
514
+ attr_writer :subset_class, :use_schema_subset
515
+
516
+ def use_schema_subset?
517
+ if defined?(@use_schema_subset)
518
+ @use_schema_subset
519
+ elsif superclass.respond_to?(:use_schema_subset?)
520
+ superclass.use_schema_subset?
521
+ else
522
+ false
523
+ end
524
+ end
525
+
500
526
  # @param type [Module] The type definition whose possible types you want to see
501
527
  # @return [Hash<String, Module>] All possible types, if no `type` is given.
502
528
  # @return [Array<Module>] Possible types for `type`, if it's given.
@@ -573,9 +599,8 @@ module GraphQL
573
599
  end
574
600
  end
575
601
 
576
- def type_from_ast(ast_node, context: nil)
577
- type_owner = context ? context.warden : self
578
- GraphQL::Schema::TypeExpression.build_type(type_owner, ast_node)
602
+ def type_from_ast(ast_node, context: self.query_class.new(self, "{ __typename }").context)
603
+ GraphQL::Schema::TypeExpression.build_type(context.query.types, ast_node)
579
604
  end
580
605
 
581
606
  def get_field(type_or_name, field_name, context = GraphQL::Query::NullContext.instance)
@@ -1053,6 +1078,10 @@ module GraphQL
1053
1078
  Member::HasDirectives.get_directives(self, @own_schema_directives, :schema_directives)
1054
1079
  end
1055
1080
 
1081
+ # Called when a type is needed by name at runtime
1082
+ def load_type(type_name, ctx)
1083
+ get_type(type_name, ctx)
1084
+ end
1056
1085
  # This hook is called when an object fails an `authorized?` check.
1057
1086
  # You might report to your bug tracker here, so you can correct
1058
1087
  # the field resolvers not to return unauthorized objects.
@@ -10,6 +10,7 @@ module GraphQL
10
10
  @argument_definitions = []
11
11
  @directive_definitions = []
12
12
  @context = context
13
+ @types = context.query.types
13
14
  @schema = context.schema
14
15
  super(document)
15
16
  end
@@ -77,7 +78,7 @@ module GraphQL
77
78
 
78
79
  def on_field(node, parent)
79
80
  parent_type = @object_types.last
80
- field_definition = @schema.get_field(parent_type, node.name, @context.query.context)
81
+ field_definition = @types.field(parent_type, node.name)
81
82
  @field_definitions.push(field_definition)
82
83
  if !field_definition.nil?
83
84
  next_object_type = field_definition.type.unwrap
@@ -103,14 +104,14 @@ module GraphQL
103
104
  argument_defn = if (arg = @argument_definitions.last)
104
105
  arg_type = arg.type.unwrap
105
106
  if arg_type.kind.input_object?
106
- @context.warden.get_argument(arg_type, node.name)
107
+ @types.argument(arg_type, node.name)
107
108
  else
108
109
  nil
109
110
  end
110
111
  elsif (directive_defn = @directive_definitions.last)
111
- @context.warden.get_argument(directive_defn, node.name)
112
+ @types.argument(directive_defn, node.name)
112
113
  elsif (field_defn = @field_definitions.last)
113
- @context.warden.get_argument(field_defn, node.name)
114
+ @types.argument(field_defn, node.name)
114
115
  else
115
116
  nil
116
117
  end
@@ -170,7 +171,7 @@ module GraphQL
170
171
 
171
172
  def on_fragment_with_type(node)
172
173
  object_type = if node.type
173
- @context.warden.get_type(node.type.name)
174
+ @types.type(node.type.name)
174
175
  else
175
176
  @object_types.last
176
177
  end
@@ -5,7 +5,7 @@ module GraphQL
5
5
  class LiteralValidator
6
6
  def initialize(context:)
7
7
  @context = context
8
- @warden = context.warden
8
+ @types = context.types
9
9
  @invalid_response = GraphQL::Query::InputValidationResult.new(valid: false, problems: [])
10
10
  @valid_response = GraphQL::Query::InputValidationResult.new(valid: true, problems: [])
11
11
  end
@@ -109,7 +109,7 @@ module GraphQL
109
109
  def required_input_fields_are_present(type, ast_node)
110
110
  # TODO - would be nice to use these to create an error message so the caller knows
111
111
  # that required fields are missing
112
- required_field_names = @warden.arguments(type)
112
+ required_field_names = @types.arguments(type)
113
113
  .select { |argument| argument.type.kind.non_null? && !argument.default_value? }
114
114
  .map!(&:name)
115
115
 
@@ -119,7 +119,7 @@ module GraphQL
119
119
  missing_required_field_names.empty? ? @valid_response : @invalid_response
120
120
  else
121
121
  results = missing_required_field_names.map do |name|
122
- arg_type = @warden.get_argument(type, name).type
122
+ arg_type = @types.argument(type, name).type
123
123
  recursively_validate(GraphQL::Language::Nodes::NullValue.new(name: name), arg_type)
124
124
  end
125
125
  if type.one_of? && ast_node.arguments.size != 1
@@ -131,7 +131,7 @@ module GraphQL
131
131
 
132
132
  def present_input_field_values_are_valid(type, ast_node)
133
133
  results = ast_node.arguments.map do |value|
134
- field = @warden.get_argument(type, value.name)
134
+ field = @types.argument(type, value.name)
135
135
  # we want to call validate on an argument even if it's an invalid one
136
136
  # so that our raise exception is on it instead of the entire InputObject
137
137
  field_type = field && field.type
@@ -15,7 +15,7 @@ module GraphQL
15
15
  if @context.schema.error_bubbling || context.errors.none? { |err| err.path.take(@path.size) == @path }
16
16
  parent_defn = parent_definition(parent)
17
17
 
18
- if parent_defn && (arg_defn = context.warden.get_argument(parent_defn, node.name))
18
+ if parent_defn && (arg_defn = @types.argument(parent_defn, node.name))
19
19
  validation_result = context.validate_literal(node.value, arg_defn.type)
20
20
  if !validation_result.valid?
21
21
  kind_of_node = node_type(parent)
@@ -5,7 +5,7 @@ module GraphQL
5
5
  def on_argument(node, parent)
6
6
  parent_defn = parent_definition(parent)
7
7
 
8
- if parent_defn && context.warden.get_argument(parent_defn, node.name)
8
+ if parent_defn && @types.argument(parent_defn, node.name)
9
9
  super
10
10
  elsif parent_defn
11
11
  kind_of_node = node_type(parent)
@@ -4,11 +4,10 @@ module GraphQL
4
4
  module DirectivesAreDefined
5
5
  def initialize(*)
6
6
  super
7
- @directive_names = context.warden.directives.map(&:graphql_name)
8
7
  end
9
8
 
10
9
  def on_directive(node, parent)
11
- if !@directive_names.include?(node.name)
10
+ if !@types.directive_exists?(node.name)
12
11
  @directives_are_defined_errors_by_name ||= {}
13
12
  error = @directives_are_defined_errors_by_name[node.name] ||= begin
14
13
  err = GraphQL::StaticValidation::DirectivesAreDefinedError.new(
@@ -4,7 +4,7 @@ module GraphQL
4
4
  module FieldsAreDefinedOnType
5
5
  def on_field(node, parent)
6
6
  parent_type = @object_types[-2]
7
- field = context.warden.get_field(parent_type, node.name)
7
+ field = context.query.types.field(parent_type, node.name)
8
8
 
9
9
  if field.nil?
10
10
  if parent_type.kind.union?
@@ -117,8 +117,8 @@ module GraphQL
117
117
 
118
118
  return if fragment1.nil? || fragment2.nil?
119
119
 
120
- fragment_type1 = context.warden.get_type(fragment1.type.name)
121
- fragment_type2 = context.warden.get_type(fragment2.type.name)
120
+ fragment_type1 = context.query.types.type(fragment1.type.name)
121
+ fragment_type2 = context.query.types.type(fragment2.type.name)
122
122
 
123
123
  return if fragment_type1.nil? || fragment_type2.nil?
124
124
 
@@ -170,7 +170,7 @@ module GraphQL
170
170
  fragment = context.fragments[fragment_name]
171
171
  return if fragment.nil?
172
172
 
173
- fragment_type = context.warden.get_type(fragment.type.name)
173
+ fragment_type = @types.type(fragment.type.name)
174
174
  return if fragment_type.nil?
175
175
 
176
176
  fragment_fields, fragment_spreads = fields_and_fragments_from_selection(fragment, owner_type: fragment_type, parents: [*fragment_spread.parents, fragment_type])
@@ -340,10 +340,10 @@ module GraphQL
340
340
  selections.each do |node|
341
341
  case node
342
342
  when GraphQL::Language::Nodes::Field
343
- definition = context.warden.get_field(owner_type, node.name)
343
+ definition = @types.field(owner_type, node.name)
344
344
  fields << Field.new(node, definition, owner_type, parents)
345
345
  when GraphQL::Language::Nodes::InlineFragment
346
- fragment_type = node.type ? context.warden.get_type(node.type.name) : owner_type
346
+ fragment_type = node.type ? @types.type(node.type.name) : owner_type
347
347
  find_fields_and_fragments(node.selections, parents: [*parents, fragment_type], owner_type: owner_type, fields: fields, fragment_spreads: fragment_spreads) if fragment_type
348
348
  when GraphQL::Language::Nodes::FragmentSpread
349
349
  fragment_spreads << FragmentSpread.new(node.name, parents)
@@ -411,8 +411,8 @@ module GraphQL
411
411
  false
412
412
  else
413
413
  # Check if these two scopes have _any_ types in common.
414
- possible_right_types = context.query.possible_types(type1)
415
- possible_left_types = context.query.possible_types(type2)
414
+ possible_right_types = context.types.possible_types(type1)
415
+ possible_left_types = context.types.possible_types(type2)
416
416
  (possible_right_types & possible_left_types).empty?
417
417
  end
418
418
  end
@@ -28,7 +28,7 @@ module GraphQL
28
28
  frag_node = context.fragments[frag_spread.node.name]
29
29
  if frag_node
30
30
  fragment_child_name = frag_node.type.name
31
- fragment_child = context.warden.get_type(fragment_child_name)
31
+ fragment_child = @types.type(fragment_child_name)
32
32
  # Might be non-existent type name
33
33
  if fragment_child
34
34
  validate_fragment_in_scope(frag_spread.parent_type, fragment_child, frag_spread.node, context, frag_spread.path)
@@ -44,8 +44,8 @@ module GraphQL
44
44
  # It's not a valid fragment type, this error was handled someplace else
45
45
  return
46
46
  end
47
- parent_types = context.warden.possible_types(parent_type.unwrap)
48
- child_types = context.warden.possible_types(child_type.unwrap)
47
+ parent_types = @types.possible_types(parent_type.unwrap)
48
+ child_types = @types.possible_types(child_type.unwrap)
49
49
 
50
50
  if child_types.none? { |c| parent_types.include?(c) }
51
51
  name = node.respond_to?(:name) ? " #{node.name}" : ""
@@ -21,7 +21,7 @@ module GraphQL
21
21
  true
22
22
  else
23
23
  type_name = fragment_node.type.name
24
- type = context.warden.get_type(type_name)
24
+ type = @types.type(type_name)
25
25
  if type.nil?
26
26
  add_error(GraphQL::StaticValidation::FragmentTypesExistError.new(
27
27
  "No such type #{type_name}, so it can't be a fragment condition",
@@ -19,7 +19,7 @@ module GraphQL
19
19
  true
20
20
  else
21
21
  type_name = node_type.to_query_string
22
- type_def = context.warden.get_type(type_name)
22
+ type_def = @types.type(type_name)
23
23
  if type_def.nil? || !type_def.kind.composite?
24
24
  add_error(GraphQL::StaticValidation::FragmentsAreOnCompositeTypesError.new(
25
25
  "Invalid fragment on type #{type_name} (must be Union, Interface or Object)",
@@ -3,7 +3,7 @@ module GraphQL
3
3
  module StaticValidation
4
4
  module MutationRootExists
5
5
  def on_operation_definition(node, _parent)
6
- if node.operation_type == 'mutation' && context.warden.root_type_for_operation("mutation").nil?
6
+ if node.operation_type == 'mutation' && context.query.types.mutation_root.nil?
7
7
  add_error(GraphQL::StaticValidation::MutationRootExistsError.new(
8
8
  'Schema is not configured for mutations',
9
9
  nodes: node
@@ -3,7 +3,7 @@ module GraphQL
3
3
  module StaticValidation
4
4
  module QueryRootExists
5
5
  def on_operation_definition(node, _parent)
6
- if (node.operation_type == 'query' || node.operation_type.nil?) && context.warden.root_type_for_operation("query").nil?
6
+ if (node.operation_type == 'query' || node.operation_type.nil?) && context.query.types.query_root.nil?
7
7
  add_error(GraphQL::StaticValidation::QueryRootExistsError.new(
8
8
  'Schema is not configured for queries',
9
9
  nodes: node
@@ -16,11 +16,11 @@ module GraphQL
16
16
  private
17
17
 
18
18
  def assert_required_args(ast_node, defn)
19
- args = defn.arguments(context.query.context)
19
+ args = @context.query.types.arguments(defn)
20
20
  return if args.empty?
21
21
  present_argument_names = ast_node.arguments.map(&:name)
22
- required_argument_names = context.warden.arguments(defn)
23
- .select { |a| a.type.kind.non_null? && !a.default_value? && context.warden.get_argument(defn, a.name) }
22
+ required_argument_names = context.query.types.arguments(defn)
23
+ .select { |a| a.type.kind.non_null? && !a.default_value? && context.query.types.argument(defn, a.name) }
24
24
  .map!(&:name)
25
25
 
26
26
  missing_names = required_argument_names - present_argument_names
@@ -26,7 +26,7 @@ module GraphQL
26
26
  context.directive_definition || context.field_definition
27
27
  end
28
28
 
29
- parent_type = context.warden.get_argument(defn, parent_name(parent, defn))
29
+ parent_type = context.types.argument(defn, parent_name(parent, defn))
30
30
  parent_type ? parent_type.type.unwrap : nil
31
31
  end
32
32
 
@@ -34,7 +34,7 @@ module GraphQL
34
34
  parent_type = get_parent_type(context, parent)
35
35
  return unless parent_type && parent_type.kind.input_object?
36
36
 
37
- required_fields = context.warden.arguments(parent_type)
37
+ required_fields = context.types.arguments(parent_type)
38
38
  .select{ |arg| arg.type.kind.non_null? && !arg.default_value? }
39
39
  .map!(&:graphql_name)
40
40
 
@@ -43,7 +43,7 @@ module GraphQL
43
43
 
44
44
  missing_fields.each do |missing_field|
45
45
  path = [*context.path, missing_field]
46
- missing_field_type = context.warden.get_argument(parent_type, missing_field).type
46
+ missing_field_type = context.types.argument(parent_type, missing_field).type
47
47
  add_error(RequiredInputObjectAttributesArePresentError.new(
48
48
  "Argument '#{missing_field}' on InputObject '#{parent_type.to_type_signature}' is required. Expected type #{missing_field_type.to_type_signature}",
49
49
  argument_name: missing_field,
@@ -3,7 +3,7 @@ module GraphQL
3
3
  module StaticValidation
4
4
  module SubscriptionRootExists
5
5
  def on_operation_definition(node, _parent)
6
- if node.operation_type == "subscription" && context.warden.root_type_for_operation("subscription").nil?
6
+ if node.operation_type == "subscription" && context.types.subscription_root.nil?
7
7
  add_error(GraphQL::StaticValidation::SubscriptionRootExistsError.new(
8
8
  'Schema is not configured for subscriptions',
9
9
  nodes: node
@@ -65,7 +65,7 @@ module GraphQL
65
65
  end
66
66
  end
67
67
 
68
- arg_defn = context.warden.get_argument(argument_owner, arg_node.name)
68
+ arg_defn = @types.argument(argument_owner, arg_node.name)
69
69
  arg_defn_type = arg_defn.type
70
70
 
71
71
  # If the argument is non-null, but it was given a default value,
@@ -4,7 +4,7 @@ module GraphQL
4
4
  module VariablesAreInputTypes
5
5
  def on_variable_definition(node, parent)
6
6
  type_name = get_type_name(node.type)
7
- type = context.warden.get_type(type_name)
7
+ type = context.query.types.type(type_name)
8
8
 
9
9
  if type.nil?
10
10
  add_error(GraphQL::StaticValidation::VariablesAreInputTypesError.new(
@@ -13,14 +13,14 @@ module GraphQL
13
13
 
14
14
  attr_reader :query, :errors, :visitor,
15
15
  :on_dependency_resolve_handlers,
16
- :max_errors, :warden, :schema
16
+ :max_errors, :types, :schema
17
17
 
18
18
 
19
19
  def_delegators :@query, :document, :fragments, :operations
20
20
 
21
21
  def initialize(query, visitor_class, max_errors)
22
22
  @query = query
23
- @warden = query.warden
23
+ @types = query.types # TODO update migrated callers to use this accessor
24
24
  @schema = query.schema
25
25
  @literal_validator = LiteralValidator.new(context: query.context)
26
26
  @errors = []
@@ -28,9 +28,8 @@ module GraphQL
28
28
  end
29
29
 
30
30
  current_field = visitor.field_definition
31
- apply_broadcastable(current_field)
32
-
33
31
  current_type = visitor.parent_type_definition
32
+ apply_broadcastable(current_type, current_field)
34
33
  if current_type.kind.interface?
35
34
  pt = @query.possible_types(current_type)
36
35
  pt.each do |object_type|
@@ -38,7 +37,7 @@ module GraphQL
38
37
  # Inherited fields would be exactly the same object;
39
38
  # only check fields that are overrides of the inherited one
40
39
  if ot_field && ot_field != current_field
41
- apply_broadcastable(ot_field)
40
+ apply_broadcastable(object_type, ot_field)
42
41
  end
43
42
  end
44
43
  end
@@ -55,10 +54,16 @@ module GraphQL
55
54
  private
56
55
 
57
56
  # Modify `@subscription_broadcastable` based on `field_defn`'s configuration (and/or the default value)
58
- def apply_broadcastable(field_defn)
57
+ def apply_broadcastable(owner_type, field_defn)
59
58
  current_field_broadcastable = field_defn.introspection? || field_defn.broadcastable?
59
+
60
+ if current_field_broadcastable.nil? && owner_type.respond_to?(:default_broadcastable?)
61
+ current_field_broadcastable = owner_type.default_broadcastable?
62
+ end
63
+
60
64
  case current_field_broadcastable
61
65
  when nil
66
+ query.logger.debug { "`broadcastable: nil` for field: #{field_defn.path}" }
62
67
  # If the value wasn't set, mix in the default value:
63
68
  # - If the default is false and the current value is true, make it false
64
69
  # - If the default is true and the current value is true, it stays true
@@ -66,6 +71,7 @@ module GraphQL
66
71
  # - If the default is true and the current value is false, keep it false
67
72
  @subscription_broadcastable = @subscription_broadcastable && @default_broadcastable
68
73
  when false
74
+ query.logger.debug { "`broadcastable: false` for field: #{field_defn.path}" }
69
75
  # One non-broadcastable field is enough to make the whole subscription non-broadcastable
70
76
  @subscription_broadcastable = false
71
77
  when true
@@ -137,7 +137,7 @@ module GraphQL
137
137
  end
138
138
 
139
139
  def get_arg_definition(arg_owner, arg_name, context)
140
- arg_owner.get_argument(arg_name, context) || arg_owner.arguments(context).each_value.find { |v| v.keyword.to_s == arg_name }
140
+ context.types.argument(arg_owner, arg_name) || context.types.arguments(arg_owner).find { |v| v.keyword.to_s == arg_name }
141
141
  end
142
142
  end
143
143
  end
@@ -64,12 +64,12 @@ module GraphQL
64
64
  event_name = event_name.to_s
65
65
 
66
66
  # Try with the verbatim input first:
67
- field = @schema.get_field(@schema.subscription, event_name, context)
67
+ field = dummy_query.types.field(@schema.subscription, event_name) # rubocop:disable Development/ContextIsPassedCop
68
68
 
69
69
  if field.nil?
70
70
  # And if it wasn't found, normalize it:
71
71
  normalized_event_name = normalize_name(event_name)
72
- field = @schema.get_field(@schema.subscription, normalized_event_name, context)
72
+ field = dummy_query.types.field(@schema.subscription, normalized_event_name) # rubocop:disable Development/ContextIsPassedCop
73
73
  if field.nil?
74
74
  raise InvalidTriggerError, "No subscription matching trigger: #{event_name} (looked for #{@schema.subscription.graphql_name}.#{normalized_event_name})"
75
75
  end
@@ -43,7 +43,7 @@ module GraphQL
43
43
  type_name, *field_names = field_path.split(".")
44
44
  dummy_query = GraphQL::Query.new(schema, "{ __typename }", context: context)
45
45
  query_context = dummy_query.context
46
- object_type = dummy_query.get_type(type_name) # rubocop:disable Development/ContextIsPassedCop
46
+ object_type = dummy_query.types.type(type_name) # rubocop:disable Development/ContextIsPassedCop
47
47
  if object_type
48
48
  graphql_result = object
49
49
  field_names.each do |field_name|
@@ -52,7 +52,7 @@ module GraphQL
52
52
  if graphql_result.nil?
53
53
  return nil
54
54
  end
55
- visible_field = dummy_query.get_field(object_type, field_name)
55
+ visible_field = dummy_query.types.field(object_type, field_name) # rubocop:disable Development/ContextIsPassedCop
56
56
  if visible_field
57
57
  dummy_query.context.dataloader.run_isolated {
58
58
  field_args = visible_field.coerce_arguments(graphql_result, arguments, query_context)