graphql 2.6.14 → 2.6.15

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.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/templates/graphql_controller.erb +7 -1
  3. data/lib/graphql/analysis/max_query_complexity.rb +2 -1
  4. data/lib/graphql/analysis/max_query_depth.rb +2 -1
  5. data/lib/graphql/analysis/query_complexity.rb +2 -1
  6. data/lib/graphql/analysis/query_depth.rb +1 -1
  7. data/lib/graphql/analysis/visitor.rb +14 -2
  8. data/lib/graphql/analysis.rb +4 -5
  9. data/lib/graphql/analysis_error.rb +1 -1
  10. data/lib/graphql/coercion_error.rb +1 -1
  11. data/lib/graphql/current.rb +5 -1
  12. data/lib/graphql/dashboard.rb +1 -1
  13. data/lib/graphql/date_encoding_error.rb +3 -1
  14. data/lib/graphql/duration_encoding_error.rb +3 -1
  15. data/lib/graphql/execution/directive_checks.rb +2 -1
  16. data/lib/graphql/execution/errors.rb +18 -7
  17. data/lib/graphql/execution/field_resolve_step.rb +3 -3
  18. data/lib/graphql/execution/input_values.rb +160 -120
  19. data/lib/graphql/execution/interpreter/runtime.rb +9 -5
  20. data/lib/graphql/execution/lookahead.rb +19 -8
  21. data/lib/graphql/execution/next.rb +1 -0
  22. data/lib/graphql/execution/runner.rb +19 -12
  23. data/lib/graphql/execution/selections_step.rb +1 -1
  24. data/lib/graphql/execution/variable_values.rb +248 -0
  25. data/lib/graphql/float_decoding_error.rb +3 -1
  26. data/lib/graphql/integer_decoding_error.rb +3 -1
  27. data/lib/graphql/introspection/base_object.rb +1 -1
  28. data/lib/graphql/introspection/directive_location_enum.rb +1 -1
  29. data/lib/graphql/introspection/directive_type.rb +3 -1
  30. data/lib/graphql/introspection/dynamic_fields.rb +3 -1
  31. data/lib/graphql/introspection/enum_value_type.rb +3 -1
  32. data/lib/graphql/introspection/field_type.rb +5 -1
  33. data/lib/graphql/introspection/type_kind_enum.rb +1 -1
  34. data/lib/graphql/introspection.rb +2 -1
  35. data/lib/graphql/language/comment.rb +2 -1
  36. data/lib/graphql/language/generation.rb +2 -1
  37. data/lib/graphql/language/lexer.rb +29 -21
  38. data/lib/graphql/language/parser.rb +10 -7
  39. data/lib/graphql/language.rb +1 -1
  40. data/lib/graphql/name_validator.rb +2 -1
  41. data/lib/graphql/pagination.rb +1 -1
  42. data/lib/graphql/query/fingerprint.rb +2 -1
  43. data/lib/graphql/query/partial.rb +4 -0
  44. data/lib/graphql/query.rb +8 -12
  45. data/lib/graphql/railtie.rb +1 -1
  46. data/lib/graphql/relay.rb +1 -1
  47. data/lib/graphql/rubocop.rb +1 -1
  48. data/lib/graphql/runtime_error.rb +1 -1
  49. data/lib/graphql/runtime_type_error.rb +1 -1
  50. data/lib/graphql/schema/always_visible.rb +3 -1
  51. data/lib/graphql/schema/base_64_encoder.rb +3 -1
  52. data/lib/graphql/schema/built_in_types.rb +2 -2
  53. data/lib/graphql/schema/directive/deprecated.rb +1 -1
  54. data/lib/graphql/schema/directive/include.rb +2 -1
  55. data/lib/graphql/schema/directive/skip.rb +2 -1
  56. data/lib/graphql/schema/directive/specified_by.rb +1 -1
  57. data/lib/graphql/schema/field/scope_extension.rb +2 -1
  58. data/lib/graphql/schema/field.rb +3 -0
  59. data/lib/graphql/schema/find_inherited_value.rb +5 -1
  60. data/lib/graphql/schema/member/graphql_type_names.rb +1 -1
  61. data/lib/graphql/schema/member/has_directives.rb +20 -22
  62. data/lib/graphql/schema/member/has_path.rb +2 -1
  63. data/lib/graphql/schema/member/has_unresolved_type_error.rb +2 -1
  64. data/lib/graphql/schema/member.rb +3 -2
  65. data/lib/graphql/schema/mutation.rb +6 -1
  66. data/lib/graphql/schema/object.rb +1 -1
  67. data/lib/graphql/schema/resolver.rb +2 -2
  68. data/lib/graphql/schema/type_expression.rb +3 -1
  69. data/lib/graphql/schema/validator/all_validator.rb +6 -3
  70. data/lib/graphql/static_validation/all_rules.rb +1 -1
  71. data/lib/graphql/static_validation/base_visitor.rb +125 -53
  72. data/lib/graphql/static_validation/definition_dependencies.rb +14 -2
  73. data/lib/graphql/static_validation/interpreter_visitor.rb +1 -1
  74. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +4 -1
  75. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
  76. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +8 -4
  77. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -1
  78. data/lib/graphql/static_validation/rules/fragments_are_named.rb +2 -1
  79. data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +4 -1
  80. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +6 -3
  81. data/lib/graphql/static_validation/rules/fragments_are_used.rb +2 -1
  82. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +3 -1
  83. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +3 -2
  84. data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +4 -1
  85. data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +4 -1
  86. data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +4 -1
  87. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +9 -2
  88. data/lib/graphql/static_validation/rules/query_root_exists.rb +3 -2
  89. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +4 -1
  90. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +10 -4
  91. data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +8 -6
  92. data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +4 -1
  93. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +5 -4
  94. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +2 -1
  95. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +2 -1
  96. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +1 -1
  97. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  98. data/lib/graphql/static_validation/validation_context.rb +49 -14
  99. data/lib/graphql/static_validation/validation_timeout_error.rb +4 -1
  100. data/lib/graphql/static_validation.rb +1 -2
  101. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +14 -13
  102. data/lib/graphql/testing.rb +1 -1
  103. data/lib/graphql/tracing/legacy_trace.rb +1 -1
  104. data/lib/graphql/tracing/null_trace.rb +1 -1
  105. data/lib/graphql/types/big_int.rb +4 -1
  106. data/lib/graphql/types/boolean.rb +3 -1
  107. data/lib/graphql/types/id.rb +3 -1
  108. data/lib/graphql/types/iso_8601_date.rb +1 -0
  109. data/lib/graphql/types/iso_8601_date_time.rb +6 -2
  110. data/lib/graphql/types/iso_8601_duration.rb +3 -0
  111. data/lib/graphql/types/relay/base_connection.rb +1 -1
  112. data/lib/graphql/types/relay/base_edge.rb +1 -1
  113. data/lib/graphql/types/relay/node.rb +1 -1
  114. data/lib/graphql/types/relay/page_info.rb +1 -1
  115. data/lib/graphql/types/relay/page_info_behaviors.rb +4 -1
  116. data/lib/graphql/types/relay.rb +1 -1
  117. data/lib/graphql/types/string.rb +1 -0
  118. data/lib/graphql/types.rb +1 -1
  119. data/lib/graphql/version.rb +2 -2
  120. metadata +3 -4
  121. data/lib/graphql/query/variables.rb +0 -99
  122. data/lib/graphql/static_validation/literal_validator.rb +0 -157
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
- # typed: true
2
+ # typed: strict
3
3
  module GraphQL
4
4
  module Types
5
5
  module Relay
6
6
  module PageInfoBehaviors
7
+ #: (singleton(GraphQL::Schema::Object) child_class) -> void
7
8
  def self.included(child_class)
8
9
  child_class.extend ClassMethods
9
10
  child_class.description "Information about pagination in a connection."
@@ -22,10 +23,12 @@ module GraphQL
22
23
  end
23
24
 
24
25
  module ClassMethods
26
+ #: () -> bool
25
27
  def default_relay?
26
28
  true
27
29
  end
28
30
 
31
+ #: () -> bool
29
32
  def default_broadcastable?
30
33
  true
31
34
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- # typed: true
2
+ # typed: strict
3
3
 
4
4
  # behavior modules:
5
5
  require "graphql/types/relay/connection_behaviors"
@@ -20,6 +20,7 @@ module GraphQL
20
20
  ctx.schema.type_error(err, ctx)
21
21
  end
22
22
 
23
+ #: (untyped value, GraphQL::Query::Context _ctx) -> ::String?
23
24
  def self.coerce_input(value, _ctx)
24
25
  value.is_a?(::String) ? value : nil
25
26
  end
data/lib/graphql/types.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- # typed: true
2
+ # typed: strict
3
3
 
4
4
  module GraphQL
5
5
  module Types
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- # typed: true
2
+ # typed: strict
3
3
  module GraphQL
4
- VERSION = "2.6.14"
4
+ VERSION = "2.6.15"
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.14
4
+ version: 2.6.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-10-29 00:00:00.000000000 Z
10
+ date: 2026-11-09 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: base64
@@ -543,6 +543,7 @@ files:
543
543
  - lib/graphql/execution/resolve_type_step.rb
544
544
  - lib/graphql/execution/runner.rb
545
545
  - lib/graphql/execution/selections_step.rb
546
+ - lib/graphql/execution/variable_values.rb
546
547
  - lib/graphql/execution_error.rb
547
548
  - lib/graphql/float_decoding_error.rb
548
549
  - lib/graphql/float_encoding_error.rb
@@ -598,7 +599,6 @@ files:
598
599
  - lib/graphql/query/result.rb
599
600
  - lib/graphql/query/validation_pipeline.rb
600
601
  - lib/graphql/query/variable_validation_error.rb
601
- - lib/graphql/query/variables.rb
602
602
  - lib/graphql/railtie.rb
603
603
  - lib/graphql/rake_task.rb
604
604
  - lib/graphql/rake_task/validate.rb
@@ -701,7 +701,6 @@ files:
701
701
  - lib/graphql/static_validation/definition_dependencies.rb
702
702
  - lib/graphql/static_validation/error.rb
703
703
  - lib/graphql/static_validation/interpreter_visitor.rb
704
- - lib/graphql/static_validation/literal_validator.rb
705
704
  - lib/graphql/static_validation/rules/argument_literals_are_compatible.rb
706
705
  - lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb
707
706
  - lib/graphql/static_validation/rules/argument_names_are_unique.rb
@@ -1,99 +0,0 @@
1
- # frozen_string_literal: true
2
- # typed: true
3
- module GraphQL
4
- class Query
5
- # Read-only access to query variables, applying default values if needed.
6
- class Variables
7
- extend Forwardable
8
-
9
- # **Returns**
10
- #
11
- # - `Array<GraphQL::Query::VariableValidationError>` — Any errors encountered when parsing the provided variables and literal values
12
- attr_reader :errors
13
-
14
- attr_reader :context
15
-
16
- def initialize(ctx, ast_variables, provided_variables)
17
- schema = ctx.schema
18
- @context = ctx
19
-
20
- @provided_variables = deep_stringify(provided_variables)
21
- @errors = []
22
- @storage = ast_variables.each_with_object({}) do |ast_variable, memo|
23
- if schema.validate_max_errors && schema.validate_max_errors <= @errors.count
24
- add_max_errors_reached_message
25
- break memo
26
- end
27
- # Find the right value for this variable:
28
- # - First, use the value provided at runtime
29
- # - Then, fall back to the default value from the query string
30
- # If it's still nil, raise an error if it's required.
31
- variable_type = schema.type_from_ast(ast_variable.type, context: ctx)
32
- if variable_type.nil? || !variable_type.unwrap.kind.input?
33
- # Pass -- it will get handled by a validator
34
- else
35
- variable_name = ast_variable.name
36
- default_value = ast_variable.default_value
37
- provided_value = @provided_variables[variable_name]
38
- value_was_provided = @provided_variables.key?(variable_name)
39
- max_errors = schema.validate_max_errors - @errors.count if schema.validate_max_errors
40
- begin
41
- validation_result = if value_was_provided || default_value.nil?
42
- variable_type.validate_input(provided_value, ctx, max_errors: max_errors)
43
- else
44
- GraphQL::Query::InputValidationResult::VALID
45
- end
46
- if validation_result.valid?
47
- if value_was_provided
48
- # Add the variable if a value was provided
49
- memo[variable_name] = provided_value
50
- elsif default_value != nil
51
- memo[variable_name] = if default_value.is_a?(Language::Nodes::NullValue)
52
- nil
53
- else
54
- default_value
55
- end
56
- end
57
- end
58
- rescue GraphQL::ExecutionError => ex
59
- # TODO: This should really include the path to the problematic node in the variable value
60
- # like InputValidationResults generated by validate_non_null_input but unfortunately we don't
61
- # have this information available in the coerce_input call chain. Note this path is the path
62
- # that appears under errors.extensions.problems.path and NOT the result path under errors.path.
63
- validation_result = GraphQL::Query::InputValidationResult.from_problem(ex.message)
64
- end
65
-
66
- if !validation_result.valid?
67
- @errors << GraphQL::Query::VariableValidationError.new(ast_variable, variable_type, provided_value, validation_result)
68
- end
69
- end
70
- end
71
- end
72
-
73
- def_delegators :@storage, :length, :key?, :[], :fetch, :to_h
74
-
75
- private
76
-
77
- def deep_stringify(val)
78
- case val
79
- when Array
80
- val.map { |v| deep_stringify(v) }
81
- when Hash
82
- new_val = {}
83
- val.each do |k, v|
84
- new_val[k.to_s] = deep_stringify(v)
85
- end
86
- new_val
87
- else
88
- val
89
- end
90
- end
91
-
92
- def add_max_errors_reached_message
93
- message = "Too many errors processing variables, max validation error limit reached. Execution aborted"
94
- validation_result = GraphQL::Query::InputValidationResult.from_problem(message)
95
- errors << GraphQL::Query::VariableValidationError.new(nil, nil, nil, validation_result, msg: message)
96
- end
97
- end
98
- end
99
- end
@@ -1,157 +0,0 @@
1
- # frozen_string_literal: true
2
- # typed: true
3
- module GraphQL
4
- module StaticValidation
5
- # Test whether `ast_value` is a valid input for `type`
6
- class LiteralValidator
7
- def initialize(context:)
8
- @context = context
9
- @types = context.types
10
- @invalid_response = GraphQL::Query::InputValidationResult.new(valid: false, problems: [])
11
- @valid_response = GraphQL::Query::InputValidationResult.new(valid: true, problems: [])
12
- end
13
-
14
- def validate(ast_value, type)
15
- catch(:invalid) do
16
- recursively_validate(ast_value, type)
17
- end
18
- end
19
-
20
- private
21
-
22
- def replace_nulls_in(ast_value)
23
- case ast_value
24
- when Array
25
- ast_value.map { |v| replace_nulls_in(v) }
26
- when GraphQL::Language::Nodes::InputObject
27
- ast_value.to_h
28
- when GraphQL::Language::Nodes::NullValue
29
- nil
30
- else
31
- ast_value
32
- end
33
- end
34
-
35
- def recursively_validate(ast_value, type)
36
- if type.nil?
37
- # this means we're an undefined argument, see #present_input_field_values_are_valid
38
- maybe_raise_if_invalid(ast_value) do
39
- @invalid_response
40
- end
41
- elsif ast_value.is_a?(GraphQL::Language::Nodes::NullValue)
42
- maybe_raise_if_invalid(ast_value) do
43
- type.kind.non_null? ? @invalid_response : @valid_response
44
- end
45
- elsif type.kind.non_null?
46
- maybe_raise_if_invalid(ast_value) do
47
- ast_value.nil? ?
48
- @invalid_response :
49
- recursively_validate(ast_value, type.of_type)
50
- end
51
- elsif type.kind.list?
52
- item_type = type.of_type
53
- results = ensure_array(ast_value).map { |val| recursively_validate(val, item_type) }
54
- merge_results(results)
55
- elsif ast_value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
56
- @valid_response
57
- elsif type.kind.scalar? && constant_scalar?(ast_value)
58
- maybe_raise_if_invalid(ast_value) do
59
- ruby_value = replace_nulls_in(ast_value)
60
- type.validate_input(ruby_value, @context)
61
- end
62
- elsif type.kind.enum?
63
- maybe_raise_if_invalid(ast_value) do
64
- if ast_value.is_a?(GraphQL::Language::Nodes::Enum)
65
- type.validate_input(ast_value.name, @context)
66
- else
67
- # if our ast_value isn't an Enum it's going to be invalid so return false
68
- @invalid_response
69
- end
70
- end
71
- elsif type.kind.input_object? && ast_value.is_a?(GraphQL::Language::Nodes::InputObject)
72
- maybe_raise_if_invalid(ast_value) do
73
- merge_results([
74
- required_input_fields_are_present(type, ast_value),
75
- present_input_field_values_are_valid(type, ast_value)
76
- ])
77
- end
78
- else
79
- maybe_raise_if_invalid(ast_value) do
80
- @invalid_response
81
- end
82
- end
83
- end
84
-
85
- # When `error_bubbling` is false, we want to bail on the first failure that we find.
86
- # Use `throw` to escape the current call stack, returning the invalid response.
87
- def maybe_raise_if_invalid(ast_value)
88
- ret = yield
89
- if !@context.schema.error_bubbling && !ret.valid?
90
- throw(:invalid, ret)
91
- else
92
- ret
93
- end
94
- end
95
-
96
- # The GraphQL grammar supports variables embedded within scalars but graphql.js
97
- # doesn't support it so we won't either for simplicity
98
- def constant_scalar?(ast_value)
99
- if ast_value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
100
- false
101
- elsif ast_value.is_a?(Array)
102
- ast_value.all? { |element| constant_scalar?(element) }
103
- elsif ast_value.is_a?(GraphQL::Language::Nodes::InputObject)
104
- ast_value.arguments.all? { |arg| constant_scalar?(arg.value) }
105
- else
106
- true
107
- end
108
- end
109
-
110
- def required_input_fields_are_present(type, ast_node)
111
- # TODO - would be nice to use these to create an error message so the caller knows
112
- # that required fields are missing
113
- required_field_names = @types.arguments(type)
114
- .select { |argument| argument.type.kind.non_null? && !argument.default_value? }
115
- .map!(&:name)
116
-
117
- present_field_names = ast_node.arguments.map(&:name)
118
- missing_required_field_names = required_field_names - present_field_names
119
- if @context.schema.error_bubbling
120
- missing_required_field_names.empty? ? @valid_response : @invalid_response
121
- else
122
- results = missing_required_field_names.map do |name|
123
- arg_type = @types.argument(type, name).type
124
- recursively_validate(GraphQL::Language::Nodes::NullValue.new(name: name), arg_type)
125
- end
126
- if type.one_of? && ast_node.arguments.size != 1
127
- results << Query::InputValidationResult.from_problem("`#{type.graphql_name}` is a OneOf type, so only one argument may be given (instead of #{ast_node.arguments.size})")
128
- end
129
- merge_results(results)
130
- end
131
- end
132
-
133
- def present_input_field_values_are_valid(type, ast_node)
134
- results = ast_node.arguments.map do |value|
135
- field = @types.argument(type, value.name)
136
- # we want to call validate on an argument even if it's an invalid one
137
- # so that our raise exception is on it instead of the entire InputObject
138
- field_type = field && field.type
139
- recursively_validate(value.value, field_type)
140
- end
141
- merge_results(results)
142
- end
143
-
144
- def ensure_array(value)
145
- value.is_a?(Array) ? value : [value]
146
- end
147
-
148
- def merge_results(results_list)
149
- merged_result = Query::InputValidationResult.new
150
- results_list.each do |inner_result|
151
- merged_result.merge_result!([], inner_result)
152
- end
153
- merged_result
154
- end
155
- end
156
- end
157
- end