graphql 2.3.5 → 2.3.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/analysis/analyzer.rb +89 -0
  3. data/lib/graphql/analysis/field_usage.rb +82 -0
  4. data/lib/graphql/analysis/max_query_complexity.rb +20 -0
  5. data/lib/graphql/analysis/max_query_depth.rb +20 -0
  6. data/lib/graphql/analysis/query_complexity.rb +183 -0
  7. data/lib/graphql/analysis/{ast/query_depth.rb → query_depth.rb} +23 -25
  8. data/lib/graphql/analysis/visitor.rb +283 -0
  9. data/lib/graphql/analysis.rb +92 -1
  10. data/lib/graphql/dataloader/async_dataloader.rb +2 -0
  11. data/lib/graphql/dataloader/source.rb +5 -2
  12. data/lib/graphql/execution/interpreter/runtime.rb +6 -6
  13. data/lib/graphql/execution/interpreter.rb +1 -1
  14. data/lib/graphql/execution/lookahead.rb +10 -10
  15. data/lib/graphql/introspection/directive_type.rb +1 -1
  16. data/lib/graphql/introspection/entry_points.rb +2 -2
  17. data/lib/graphql/introspection/field_type.rb +1 -1
  18. data/lib/graphql/introspection/schema_type.rb +6 -11
  19. data/lib/graphql/introspection/type_type.rb +5 -5
  20. data/lib/graphql/language/document_from_schema_definition.rb +19 -26
  21. data/lib/graphql/language/lexer.rb +0 -3
  22. data/lib/graphql/language/parser.rb +9 -1
  23. data/lib/graphql/language/sanitized_printer.rb +1 -1
  24. data/lib/graphql/language.rb +0 -1
  25. data/lib/graphql/query/context.rb +4 -0
  26. data/lib/graphql/query/null_context.rb +4 -0
  27. data/lib/graphql/query/validation_pipeline.rb +2 -2
  28. data/lib/graphql/query.rb +26 -3
  29. data/lib/graphql/schema/always_visible.rb +1 -0
  30. data/lib/graphql/schema/argument.rb +19 -5
  31. data/lib/graphql/schema/directive.rb +2 -0
  32. data/lib/graphql/schema/enum.rb +9 -5
  33. data/lib/graphql/schema/field.rb +13 -1
  34. data/lib/graphql/schema/has_single_input_argument.rb +2 -1
  35. data/lib/graphql/schema/input_object.rb +8 -7
  36. data/lib/graphql/schema/introspection_system.rb +2 -14
  37. data/lib/graphql/schema/member/has_arguments.rb +7 -6
  38. data/lib/graphql/schema/member/has_fields.rb +6 -4
  39. data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
  40. data/lib/graphql/schema/resolver.rb +5 -5
  41. data/lib/graphql/schema/subset.rb +397 -0
  42. data/lib/graphql/schema/type_expression.rb +2 -2
  43. data/lib/graphql/schema/validator/all_validator.rb +60 -0
  44. data/lib/graphql/schema/validator.rb +2 -0
  45. data/lib/graphql/schema/warden.rb +88 -1
  46. data/lib/graphql/schema.rb +44 -15
  47. data/lib/graphql/static_validation/base_visitor.rb +6 -5
  48. data/lib/graphql/static_validation/literal_validator.rb +4 -4
  49. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
  50. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
  51. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -2
  52. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
  53. data/lib/graphql/static_validation/rules/fields_will_merge.rb +7 -7
  54. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  55. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
  56. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
  57. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
  58. data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
  59. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +3 -3
  60. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +3 -3
  61. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
  62. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
  63. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +1 -1
  64. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  65. data/lib/graphql/static_validation/validation_context.rb +2 -2
  66. data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
  67. data/lib/graphql/subscriptions/event.rb +1 -1
  68. data/lib/graphql/subscriptions.rb +3 -3
  69. data/lib/graphql/testing/helpers.rb +2 -2
  70. data/lib/graphql/types/relay/connection_behaviors.rb +10 -0
  71. data/lib/graphql/types/relay/edge_behaviors.rb +10 -0
  72. data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
  73. data/lib/graphql/version.rb +1 -1
  74. metadata +12 -13
  75. data/lib/graphql/analysis/ast/analyzer.rb +0 -91
  76. data/lib/graphql/analysis/ast/field_usage.rb +0 -84
  77. data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -22
  78. data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
  79. data/lib/graphql/analysis/ast/query_complexity.rb +0 -185
  80. data/lib/graphql/analysis/ast/visitor.rb +0 -284
  81. data/lib/graphql/analysis/ast.rb +0 -94
  82. data/lib/graphql/language/token.rb +0 -34
  83. data/lib/graphql/schema/invalid_type_error.rb +0 -7
@@ -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
@@ -5,36 +5,27 @@ module GraphQL
5
5
  def on_variable_definition(node, parent)
6
6
  if !node.default_value.nil?
7
7
  value = node.default_value
8
- if node.type.is_a?(GraphQL::Language::Nodes::NonNullType)
9
- add_error(GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTypedError.new(
10
- "Non-null variable $#{node.name} can't have a default value",
11
- nodes: node,
12
- name: node.name,
13
- error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_ON_NON_NULL]
14
- ))
8
+ type = context.schema.type_from_ast(node.type, context: context)
9
+ if type.nil?
10
+ # This is handled by another validator
15
11
  else
16
- type = context.schema.type_from_ast(node.type, context: context)
17
- if type.nil?
18
- # This is handled by another validator
19
- else
20
- validation_result = context.validate_literal(value, type)
12
+ validation_result = context.validate_literal(value, type)
21
13
 
22
- if !validation_result.valid?
23
- problems = validation_result.problems
24
- first_problem = problems && problems.first
25
- if first_problem
26
- error_message = first_problem["explanation"]
27
- end
28
-
29
- error_message ||= "Default value for $#{node.name} doesn't match type #{type.to_type_signature}"
30
- add_error(GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTypedError.new(
31
- error_message,
32
- nodes: node,
33
- name: node.name,
34
- type: type.to_type_signature,
35
- error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_TYPE],
36
- ))
14
+ if !validation_result.valid?
15
+ problems = validation_result.problems
16
+ first_problem = problems && problems.first
17
+ if first_problem
18
+ error_message = first_problem["explanation"]
37
19
  end
20
+
21
+ error_message ||= "Default value for $#{node.name} doesn't match type #{type.to_type_signature}"
22
+ add_error(GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTypedError.new(
23
+ error_message,
24
+ nodes: node,
25
+ name: node.name,
26
+ type: type.to_type_signature,
27
+ error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_TYPE],
28
+ ))
38
29
  end
39
30
  end
40
31
  end
@@ -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 = []
@@ -9,7 +9,7 @@ module GraphQL
9
9
  # Assign the result to `context.namespace(:subscriptions)[:subscription_broadcastable]`
10
10
  # @api private
11
11
  # @see Subscriptions#broadcastable? for a public API
12
- class BroadcastAnalyzer < GraphQL::Analysis::AST::Analyzer
12
+ class BroadcastAnalyzer < GraphQL::Analysis::Analyzer
13
13
  def initialize(subject)
14
14
  super
15
15
  @default_broadcastable = subject.schema.subscriptions.default_broadcastable
@@ -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
@@ -235,7 +235,7 @@ module GraphQL
235
235
  if !query.valid?
236
236
  raise "Invalid query: #{query.validation_errors.map(&:to_h).inspect}"
237
237
  end
238
- GraphQL::Analysis::AST.analyze_query(query, @schema.query_analyzers)
238
+ GraphQL::Analysis.analyze_query(query, @schema.query_analyzers)
239
239
  query.context.namespace(:subscriptions)[:subscription_broadcastable]
240
240
  end
241
241
 
@@ -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)
@@ -18,6 +18,7 @@ module GraphQL
18
18
  self.node_type = nil
19
19
  self.edge_class = nil
20
20
  }
21
+ child_class.default_broadcastable(nil)
21
22
  add_page_info_field(child_class)
22
23
  end
23
24
 
@@ -31,12 +32,21 @@ module GraphQL
31
32
  child_class.edge_type = nil
32
33
  child_class.node_type = nil
33
34
  child_class.edge_class = nil
35
+ child_class.default_broadcastable(default_broadcastable?)
34
36
  end
35
37
 
36
38
  def default_relay?
37
39
  true
38
40
  end
39
41
 
42
+ def default_broadcastable?
43
+ @default_broadcastable
44
+ end
45
+
46
+ def default_broadcastable(new_value)
47
+ @default_broadcastable = new_value
48
+ end
49
+
40
50
  # @return [Class]
41
51
  attr_reader :node_type
42
52
 
@@ -10,6 +10,7 @@ module GraphQL
10
10
  child_class.extend(ClassMethods)
11
11
  child_class.class_eval { self.node_type = nil }
12
12
  child_class.node_nullable(true)
13
+ child_class.default_broadcastable(nil)
13
14
  end
14
15
 
15
16
  def node
@@ -24,12 +25,21 @@ module GraphQL
24
25
  super
25
26
  child_class.node_type = nil
26
27
  child_class.node_nullable = nil
28
+ child_class.default_broadcastable(default_broadcastable?)
27
29
  end
28
30
 
29
31
  def default_relay?
30
32
  true
31
33
  end
32
34
 
35
+ def default_broadcastable?
36
+ @default_broadcastable
37
+ end
38
+
39
+ def default_broadcastable(new_value)
40
+ @default_broadcastable = new_value
41
+ end
42
+
33
43
  # Get or set the Object type that this edge wraps.
34
44
  #
35
45
  # @param node_type [Class] A `Schema::Object` subclass
@@ -24,6 +24,10 @@ module GraphQL
24
24
  def default_relay?
25
25
  true
26
26
  end
27
+
28
+ def default_broadcastable?
29
+ true
30
+ end
27
31
  end
28
32
  end
29
33
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.3.5"
3
+ VERSION = "2.3.10"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.5
4
+ version: 2.3.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-13 00:00:00.000000000 Z
11
+ date: 2024-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -306,14 +306,13 @@ files:
306
306
  - lib/generators/graphql/union_generator.rb
307
307
  - lib/graphql.rb
308
308
  - lib/graphql/analysis.rb
309
- - lib/graphql/analysis/ast.rb
310
- - lib/graphql/analysis/ast/analyzer.rb
311
- - lib/graphql/analysis/ast/field_usage.rb
312
- - lib/graphql/analysis/ast/max_query_complexity.rb
313
- - lib/graphql/analysis/ast/max_query_depth.rb
314
- - lib/graphql/analysis/ast/query_complexity.rb
315
- - lib/graphql/analysis/ast/query_depth.rb
316
- - lib/graphql/analysis/ast/visitor.rb
309
+ - lib/graphql/analysis/analyzer.rb
310
+ - lib/graphql/analysis/field_usage.rb
311
+ - lib/graphql/analysis/max_query_complexity.rb
312
+ - lib/graphql/analysis/max_query_depth.rb
313
+ - lib/graphql/analysis/query_complexity.rb
314
+ - lib/graphql/analysis/query_depth.rb
315
+ - lib/graphql/analysis/visitor.rb
317
316
  - lib/graphql/analysis_error.rb
318
317
  - lib/graphql/backtrace.rb
319
318
  - lib/graphql/backtrace/inspect_result.rb
@@ -377,7 +376,6 @@ files:
377
376
  - lib/graphql/language/printer.rb
378
377
  - lib/graphql/language/sanitized_printer.rb
379
378
  - lib/graphql/language/static_visitor.rb
380
- - lib/graphql/language/token.rb
381
379
  - lib/graphql/language/visitor.rb
382
380
  - lib/graphql/load_application_object_failed_error.rb
383
381
  - lib/graphql/name_validator.rb
@@ -440,7 +438,6 @@ files:
440
438
  - lib/graphql/schema/input_object.rb
441
439
  - lib/graphql/schema/interface.rb
442
440
  - lib/graphql/schema/introspection_system.rb
443
- - lib/graphql/schema/invalid_type_error.rb
444
441
  - lib/graphql/schema/late_bound_type.rb
445
442
  - lib/graphql/schema/list.rb
446
443
  - lib/graphql/schema/loader.rb
@@ -471,12 +468,14 @@ files:
471
468
  - lib/graphql/schema/resolver/has_payload_type.rb
472
469
  - lib/graphql/schema/scalar.rb
473
470
  - lib/graphql/schema/subscription.rb
471
+ - lib/graphql/schema/subset.rb
474
472
  - lib/graphql/schema/timeout.rb
475
473
  - lib/graphql/schema/type_expression.rb
476
474
  - lib/graphql/schema/type_membership.rb
477
475
  - lib/graphql/schema/union.rb
478
476
  - lib/graphql/schema/unique_within_type.rb
479
477
  - lib/graphql/schema/validator.rb
478
+ - lib/graphql/schema/validator/all_validator.rb
480
479
  - lib/graphql/schema/validator/allow_blank_validator.rb
481
480
  - lib/graphql/schema/validator/allow_null_validator.rb
482
481
  - lib/graphql/schema/validator/exclusion_validator.rb
@@ -645,7 +644,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
645
644
  - !ruby/object:Gem::Version
646
645
  version: '0'
647
646
  requirements: []
648
- rubygems_version: 3.5.3
647
+ rubygems_version: 3.5.12
649
648
  signing_key:
650
649
  specification_version: 4
651
650
  summary: A GraphQL language and runtime for Ruby