graphql 1.11.2 → 1.11.7

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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +8 -0
  3. data/lib/generators/graphql/object_generator.rb +2 -0
  4. data/lib/generators/graphql/templates/base_argument.erb +2 -0
  5. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  6. data/lib/generators/graphql/templates/base_field.erb +2 -0
  7. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  8. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  9. data/lib/generators/graphql/templates/base_mutation.erb +2 -0
  10. data/lib/generators/graphql/templates/base_object.erb +2 -0
  11. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  12. data/lib/generators/graphql/templates/base_union.erb +2 -0
  13. data/lib/generators/graphql/templates/enum.erb +2 -0
  14. data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
  15. data/lib/generators/graphql/templates/interface.erb +2 -0
  16. data/lib/generators/graphql/templates/loader.erb +2 -0
  17. data/lib/generators/graphql/templates/mutation.erb +2 -0
  18. data/lib/generators/graphql/templates/mutation_type.erb +2 -0
  19. data/lib/generators/graphql/templates/object.erb +2 -0
  20. data/lib/generators/graphql/templates/query_type.erb +2 -0
  21. data/lib/generators/graphql/templates/scalar.erb +2 -0
  22. data/lib/generators/graphql/templates/schema.erb +2 -0
  23. data/lib/generators/graphql/templates/union.erb +3 -1
  24. data/lib/graphql.rb +17 -0
  25. data/lib/graphql/argument.rb +3 -3
  26. data/lib/graphql/backtrace/tracer.rb +2 -1
  27. data/lib/graphql/define/assign_global_id_field.rb +2 -2
  28. data/lib/graphql/execution/interpreter.rb +10 -0
  29. data/lib/graphql/execution/interpreter/arguments.rb +21 -6
  30. data/lib/graphql/execution/interpreter/arguments_cache.rb +8 -0
  31. data/lib/graphql/execution/interpreter/runtime.rb +94 -67
  32. data/lib/graphql/integer_decoding_error.rb +17 -0
  33. data/lib/graphql/introspection.rb +96 -0
  34. data/lib/graphql/introspection/field_type.rb +7 -3
  35. data/lib/graphql/introspection/input_value_type.rb +6 -0
  36. data/lib/graphql/introspection/introspection_query.rb +6 -92
  37. data/lib/graphql/introspection/type_type.rb +7 -3
  38. data/lib/graphql/invalid_null_error.rb +1 -1
  39. data/lib/graphql/language/block_string.rb +24 -5
  40. data/lib/graphql/language/lexer.rb +7 -3
  41. data/lib/graphql/language/lexer.rl +7 -3
  42. data/lib/graphql/language/nodes.rb +1 -1
  43. data/lib/graphql/language/parser.rb +107 -103
  44. data/lib/graphql/language/parser.y +4 -0
  45. data/lib/graphql/language/sanitized_printer.rb +59 -26
  46. data/lib/graphql/name_validator.rb +6 -7
  47. data/lib/graphql/pagination/connections.rb +11 -3
  48. data/lib/graphql/query.rb +6 -3
  49. data/lib/graphql/query/context.rb +34 -4
  50. data/lib/graphql/query/fingerprint.rb +2 -0
  51. data/lib/graphql/query/validation_pipeline.rb +4 -1
  52. data/lib/graphql/relay/array_connection.rb +2 -2
  53. data/lib/graphql/relay/range_add.rb +14 -5
  54. data/lib/graphql/schema.rb +49 -18
  55. data/lib/graphql/schema/argument.rb +56 -10
  56. data/lib/graphql/schema/build_from_definition.rb +67 -38
  57. data/lib/graphql/schema/build_from_definition/resolve_map.rb +3 -1
  58. data/lib/graphql/schema/default_type_error.rb +2 -0
  59. data/lib/graphql/schema/directive/deprecated.rb +1 -1
  60. data/lib/graphql/schema/field.rb +32 -16
  61. data/lib/graphql/schema/field/connection_extension.rb +44 -37
  62. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  63. data/lib/graphql/schema/input_object.rb +5 -3
  64. data/lib/graphql/schema/interface.rb +1 -1
  65. data/lib/graphql/schema/late_bound_type.rb +2 -2
  66. data/lib/graphql/schema/loader.rb +1 -0
  67. data/lib/graphql/schema/member/build_type.rb +14 -4
  68. data/lib/graphql/schema/member/has_arguments.rb +54 -53
  69. data/lib/graphql/schema/member/has_fields.rb +17 -7
  70. data/lib/graphql/schema/member/type_system_helpers.rb +2 -2
  71. data/lib/graphql/schema/mutation.rb +4 -0
  72. data/lib/graphql/schema/relay_classic_mutation.rb +4 -2
  73. data/lib/graphql/schema/resolver.rb +6 -0
  74. data/lib/graphql/schema/resolver/has_payload_type.rb +2 -1
  75. data/lib/graphql/schema/subscription.rb +2 -12
  76. data/lib/graphql/schema/timeout.rb +29 -15
  77. data/lib/graphql/schema/unique_within_type.rb +1 -2
  78. data/lib/graphql/schema/validation.rb +8 -0
  79. data/lib/graphql/schema/warden.rb +2 -3
  80. data/lib/graphql/static_validation.rb +1 -0
  81. data/lib/graphql/static_validation/all_rules.rb +1 -0
  82. data/lib/graphql/static_validation/rules/fields_will_merge.rb +25 -17
  83. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  84. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  85. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  86. data/lib/graphql/static_validation/validator.rb +29 -7
  87. data/lib/graphql/subscriptions.rb +32 -22
  88. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +21 -7
  89. data/lib/graphql/tracing/appoptics_tracing.rb +10 -2
  90. data/lib/graphql/tracing/platform_tracing.rb +1 -1
  91. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  92. data/lib/graphql/types/int.rb +9 -2
  93. data/lib/graphql/types/iso_8601_date_time.rb +2 -1
  94. data/lib/graphql/types/relay/base_connection.rb +8 -6
  95. data/lib/graphql/types/relay/base_edge.rb +2 -1
  96. data/lib/graphql/types/string.rb +7 -1
  97. data/lib/graphql/unauthorized_error.rb +1 -1
  98. data/lib/graphql/version.rb +1 -1
  99. data/readme.md +1 -1
  100. metadata +10 -6
@@ -466,6 +466,10 @@ def self.parse(query_string, filename: nil, tracer: GraphQL::Tracing::NullTracer
466
466
  self.new(query_string, filename: filename, tracer: tracer).parse_document
467
467
  end
468
468
 
469
+ def self.parse_file(filename, tracer: GraphQL::Tracing::NullTracer)
470
+ self.parse(File.read(filename), filename: filename, tracer: tracer)
471
+ end
472
+
469
473
  private
470
474
 
471
475
  def next_token
@@ -19,11 +19,12 @@ module GraphQL
19
19
 
20
20
  REDACTED = "\"<REDACTED>\""
21
21
 
22
- def initialize(query)
22
+ def initialize(query, inline_variables: true)
23
23
  @query = query
24
24
  @current_type = nil
25
25
  @current_field = nil
26
26
  @current_input_type = nil
27
+ @inline_variables = inline_variables
27
28
  end
28
29
 
29
30
  # @return [String, nil] A scrubbed query string, if the query was valid.
@@ -36,15 +37,14 @@ module GraphQL
36
37
  end
37
38
 
38
39
  def print_node(node, indent: "")
39
- if node.is_a?(String)
40
- type = @current_input_type.unwrap
41
- # Replace any strings that aren't IDs or Enum values with REDACTED
42
- if type.kind.enum? || type.graphql_name == "ID"
43
- super
40
+ case node
41
+ when FalseClass, Float, Integer, String, TrueClass
42
+ if @current_argument && redact_argument_value?(@current_argument, node)
43
+ redacted_argument_value(@current_argument)
44
44
  else
45
- REDACTED
45
+ super
46
46
  end
47
- elsif node.is_a?(Array)
47
+ when Array
48
48
  old_input_type = @current_input_type
49
49
  if @current_input_type && @current_input_type.list?
50
50
  @current_input_type = @current_input_type.of_type
@@ -59,28 +59,57 @@ module GraphQL
59
59
  end
60
60
  end
61
61
 
62
+ # Indicates whether or not to redact non-null values for the given argument. Defaults to redacting all strings
63
+ # arguments but this can be customized by subclasses.
64
+ def redact_argument_value?(argument, value)
65
+ # Default to redacting any strings or custom scalars encoded as strings
66
+ type = argument.type.unwrap
67
+ value.is_a?(String) && type.kind.scalar? && (type.graphql_name == "String" || !type.default_scalar?)
68
+ end
69
+
70
+ # Returns the value to use for redacted versions of the given argument. Defaults to the
71
+ # string "<REDACTED>".
72
+ def redacted_argument_value(argument)
73
+ REDACTED
74
+ end
75
+
62
76
  def print_argument(argument)
77
+ # We won't have type information if we're recursing into a custom scalar
78
+ return super if @current_input_type && @current_input_type.kind.scalar?
79
+
63
80
  arg_owner = @current_input_type || @current_directive || @current_field
64
- arg_def = arg_owner.arguments[argument.name]
81
+ old_current_argument = @current_argument
82
+ @current_argument = arg_owner.arguments[argument.name]
65
83
 
66
84
  old_input_type = @current_input_type
67
- @current_input_type = arg_def.type.non_null? ? arg_def.type.of_type : arg_def.type
68
- res = super
85
+ @current_input_type = @current_argument.type.non_null? ? @current_argument.type.of_type : @current_argument.type
86
+
87
+ argument_value = if coerce_argument_value_to_list?(@current_input_type, argument.value)
88
+ [argument.value]
89
+ else
90
+ argument.value
91
+ end
92
+ res = "#{argument.name}: #{print_node(argument_value)}".dup
93
+
69
94
  @current_input_type = old_input_type
95
+ @current_argument = old_current_argument
70
96
  res
71
97
  end
72
98
 
73
- def print_list_type(list_type)
74
- old_input_type = @current_input_type
75
- @current_input_type = old_input_type.of_type
76
- res = super
77
- @current_input_type = old_input_type
78
- res
99
+ def coerce_argument_value_to_list?(type, value)
100
+ type.list? &&
101
+ !value.is_a?(Array) &&
102
+ !value.nil? &&
103
+ !value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
79
104
  end
80
105
 
81
106
  def print_variable_identifier(variable_id)
82
- variable_value = query.variables[variable_id.name]
83
- print_node(value_to_ast(variable_value, @current_input_type))
107
+ if @inline_variables
108
+ variable_value = query.variables[variable_id.name]
109
+ print_node(value_to_ast(variable_value, @current_input_type))
110
+ else
111
+ super
112
+ end
84
113
  end
85
114
 
86
115
  def print_field(field, indent: "")
@@ -132,10 +161,14 @@ module GraphQL
132
161
  old_type = @current_type
133
162
  @current_type = query.schema.public_send(operation_definition.operation_type)
134
163
 
135
- out = "#{indent}#{operation_definition.operation_type}".dup
136
- out << " #{operation_definition.name}" if operation_definition.name
137
- out << print_directives(operation_definition.directives)
138
- out << print_selections(operation_definition.selections, indent: indent)
164
+ if @inline_variables
165
+ out = "#{indent}#{operation_definition.operation_type}".dup
166
+ out << " #{operation_definition.name}" if operation_definition.name
167
+ out << print_directives(operation_definition.directives)
168
+ out << print_selections(operation_definition.selections, indent: indent)
169
+ else
170
+ out = super
171
+ end
139
172
 
140
173
  @current_type = old_type
141
174
  out
@@ -171,10 +204,10 @@ module GraphQL
171
204
  arguments: arguments
172
205
  )
173
206
  when "LIST"
174
- if value.respond_to?(:each)
175
- value.each { |v| value_to_ast(v, type.of_type) }
207
+ if value.is_a?(Array)
208
+ value.map { |v| value_to_ast(v, type.of_type) }
176
209
  else
177
- [value].each { |v| value_to_ast(v, type.of_type) }
210
+ [value].map { |v| value_to_ast(v, type.of_type) }
178
211
  end
179
212
  when "ENUM"
180
213
  GraphQL::Language::Nodes::Enum.new(name: value)
@@ -1,16 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  class NameValidator
4
- VALID_NAME_REGEX = /^[_a-zA-Z][_a-zA-Z0-9]*$/
5
-
6
- def self.validate!(name)
7
- raise GraphQL::InvalidNameError.new(name, VALID_NAME_REGEX) unless valid?(name)
4
+ if !String.method_defined?(:match?)
5
+ using GraphQL::StringMatchBackport
8
6
  end
9
7
 
10
- private
8
+ VALID_NAME_REGEX = /^[_a-zA-Z][_a-zA-Z0-9]*$/
11
9
 
12
- def self.valid?(name)
13
- name =~ VALID_NAME_REGEX
10
+ def self.validate!(name)
11
+ name = name.is_a?(String) ? name : name.to_s
12
+ raise GraphQL::InvalidNameError.new(name, VALID_NAME_REGEX) unless name.match?(VALID_NAME_REGEX)
14
13
  end
15
14
  end
16
15
  end
@@ -63,9 +63,7 @@ module GraphQL
63
63
  all_wrappers
64
64
  end
65
65
 
66
- # Used by the runtime to wrap values in connection wrappers.
67
- # @api Private
68
- def wrap(field, parent, items, arguments, context, wrappers: all_wrappers)
66
+ def wrapper_for(items, wrappers: all_wrappers)
69
67
  impl = nil
70
68
 
71
69
  items.class.ancestors.each { |cls|
@@ -73,6 +71,16 @@ module GraphQL
73
71
  break if impl
74
72
  }
75
73
 
74
+ impl
75
+ end
76
+
77
+ # Used by the runtime to wrap values in connection wrappers.
78
+ # @api Private
79
+ def wrap(field, parent, items, arguments, context, wrappers: all_wrappers)
80
+ return items if GraphQL::Execution::Interpreter::RawValue === items
81
+
82
+ impl = wrapper_for(items, wrappers: wrappers)
83
+
76
84
  if impl.nil?
77
85
  raise ImplementationMissingError, "Couldn't find a connection wrapper for #{items.class} during #{field.path} (#{items.inspect})"
78
86
  end
@@ -88,6 +88,7 @@ module GraphQL
88
88
  schema = schema.graphql_definition
89
89
  end
90
90
  @schema = schema
91
+ @interpreter = @schema.interpreter?
91
92
  @filter = schema.default_filter.merge(except: except, only: only)
92
93
  @context = schema.context_class.new(query: self, object: root_value, values: context)
93
94
  @warden = warden
@@ -148,7 +149,9 @@ module GraphQL
148
149
  @query_string ||= (document ? document.to_query_string : nil)
149
150
  end
150
151
 
151
- def_delegators :@schema, :interpreter?
152
+ def interpreter?
153
+ @interpreter
154
+ end
152
155
 
153
156
  def subscription_update?
154
157
  @subscription_topic && subscription?
@@ -259,9 +262,9 @@ module GraphQL
259
262
  # - Variables inlined to the query
260
263
  # - Strings replaced with `<REDACTED>`
261
264
  # @return [String, nil] Returns nil if the query is invalid.
262
- def sanitized_query_string
265
+ def sanitized_query_string(inline_variables: true)
263
266
  with_prepared_ast {
264
- GraphQL::Language::SanitizedPrinter.new(self).sanitized_query_string
267
+ GraphQL::Language::SanitizedPrinter.new(self, inline_variables: inline_variables).sanitized_query_string
265
268
  }
266
269
  end
267
270
 
@@ -34,7 +34,7 @@ module GraphQL
34
34
  # Remove this child from the result value
35
35
  # (used for null propagation and skip)
36
36
  # @api private
37
- def delete(child_ctx)
37
+ def delete_child(child_ctx)
38
38
  @value.delete(child_ctx.key)
39
39
  end
40
40
 
@@ -167,8 +167,10 @@ module GraphQL
167
167
  # @api private
168
168
  attr_accessor :scoped_context
169
169
 
170
- def_delegators :@provided_values, :[]=
171
- def_delegators :to_h, :fetch, :dig
170
+ def []=(key, value)
171
+ @provided_values[key] = value
172
+ end
173
+
172
174
  def_delegators :@query, :trace, :interpreter?
173
175
 
174
176
  # @!method []=(key, value)
@@ -180,6 +182,34 @@ module GraphQL
180
182
  @provided_values[key]
181
183
  end
182
184
 
185
+ def delete(key)
186
+ if @scoped_context.key?(key)
187
+ @scoped_context.delete(key)
188
+ else
189
+ @provided_values.delete(key)
190
+ end
191
+ end
192
+
193
+ UNSPECIFIED_FETCH_DEFAULT = Object.new
194
+
195
+ def fetch(key, default = UNSPECIFIED_FETCH_DEFAULT)
196
+ if @scoped_context.key?(key)
197
+ @scoped_context[key]
198
+ elsif @provided_values.key?(key)
199
+ @provided_values[key]
200
+ elsif default != UNSPECIFIED_FETCH_DEFAULT
201
+ default
202
+ elsif block_given?
203
+ yield(self, key)
204
+ else
205
+ raise KeyError.new(key: key)
206
+ end
207
+ end
208
+
209
+ def dig(key, *other_keys)
210
+ @scoped_context.key?(key) ? @scoped_context.dig(key, *other_keys) : @provided_values.dig(key, *other_keys)
211
+ end
212
+
183
213
  def to_h
184
214
  @provided_values.merge(@scoped_context)
185
215
  end
@@ -293,7 +323,7 @@ module GraphQL
293
323
  end
294
324
  when GraphQL::Execution::Execute::SKIP
295
325
  @parent.skipped = true
296
- @parent.delete(self)
326
+ @parent.delete_child(self)
297
327
  else
298
328
  @value = new_value
299
329
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'digest/sha2'
4
+
3
5
  module GraphQL
4
6
  class Query
5
7
  # @api private
@@ -72,7 +72,7 @@ module GraphQL
72
72
  elsif @operation_name_error
73
73
  @validation_errors << @operation_name_error
74
74
  else
75
- validation_result = @schema.static_validator.validate(@query, validate: @validate)
75
+ validation_result = @schema.static_validator.validate(@query, validate: @validate, timeout: @schema.validate_timeout)
76
76
  @validation_errors.concat(validation_result[:errors])
77
77
  @internal_representation = validation_result[:irep]
78
78
 
@@ -90,6 +90,9 @@ module GraphQL
90
90
  end
91
91
 
92
92
  @valid = @validation_errors.empty?
93
+ rescue SystemStackError => err
94
+ @valid = false
95
+ @schema.query_stack_error(@query, err)
93
96
  end
94
97
 
95
98
  # If there are max_* values, add them,
@@ -31,8 +31,6 @@ module GraphQL
31
31
  end
32
32
  end
33
33
 
34
- private
35
-
36
34
  def first
37
35
  @first ||= begin
38
36
  capped = limit_pagination_argument(arguments[:first], max_page_size)
@@ -47,6 +45,8 @@ module GraphQL
47
45
  @last ||= limit_pagination_argument(arguments[:last], max_page_size)
48
46
  end
49
47
 
48
+ private
49
+
50
50
  # apply first / last limit results
51
51
  def paged_nodes
52
52
  @paged_nodes ||= begin
@@ -33,12 +33,21 @@ module GraphQL
33
33
  # @param item [Object] The newly-added item (will be wrapped in `edge_class`)
34
34
  # @param parent [Object] The owner of `collection`, will be passed to the connection if provided
35
35
  # @param context [GraphQL::Query::Context] The surrounding `ctx`, will be passed to the connection if provided (this is required for cursor encoders)
36
- # @param edge_class [Class] The class to wrap `item` with
37
- def initialize(collection:, item:, parent: nil, context: nil, edge_class: Relay::Edge)
38
- connection_class = BaseConnection.connection_for_nodes(collection)
36
+ # @param edge_class [Class] The class to wrap `item` with (defaults to the connection's edge class)
37
+ def initialize(collection:, item:, parent: nil, context: nil, edge_class: nil)
38
+ if context && context.schema.new_connections?
39
+ conn_class = context.schema.connections.wrapper_for(collection)
40
+ # The rest will be added by ConnectionExtension
41
+ @connection = conn_class.new(collection, parent: parent, context: context, edge_class: edge_class)
42
+ @edge = @connection.edge_class.new(item, @connection)
43
+ else
44
+ connection_class = BaseConnection.connection_for_nodes(collection)
45
+ @connection = connection_class.new(collection, {}, parent: parent, context: context)
46
+ edge_class ||= Relay::Edge
47
+ @edge = edge_class.new(item, @connection)
48
+ end
49
+
39
50
  @parent = parent
40
- @connection = connection_class.new(collection, {}, parent: parent, context: context)
41
- @edge = edge_class.new(item, @connection)
42
51
  end
43
52
  end
44
53
  end
@@ -157,7 +157,7 @@ module GraphQL
157
157
 
158
158
  accepts_definitions \
159
159
  :query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
160
- :max_depth, :max_complexity, :default_max_page_size,
160
+ :validate_timeout, :max_depth, :max_complexity, :default_max_page_size,
161
161
  :orphan_types, :resolve_type, :type_error, :parse_error,
162
162
  :error_bubbling,
163
163
  :raise_definition_error,
@@ -196,7 +196,7 @@ module GraphQL
196
196
  attr_accessor \
197
197
  :query, :mutation, :subscription,
198
198
  :query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
199
- :max_depth, :max_complexity, :default_max_page_size,
199
+ :validate_timeout, :max_depth, :max_complexity, :default_max_page_size,
200
200
  :orphan_types, :directives,
201
201
  :query_analyzers, :multiplex_analyzers, :instrumenters, :lazy_methods,
202
202
  :cursor_encoder,
@@ -366,7 +366,7 @@ module GraphQL
366
366
  validator_opts = { schema: self }
367
367
  rules && (validator_opts[:rules] = rules)
368
368
  validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
369
- res = validator.validate(query)
369
+ res = validator.validate(query, timeout: validate_timeout)
370
370
  res[:errors]
371
371
  end
372
372
 
@@ -789,20 +789,25 @@ module GraphQL
789
789
  # @param using [Hash] Plugins to attach to the created schema with `use(key, value)`
790
790
  # @param interpreter [Boolean] If false, the legacy {Execution::Execute} runtime will be used
791
791
  # @return [Class] the schema described by `document`
792
- def self.from_definition(definition_or_path, default_resolve: nil, interpreter: true, parser: BuildFromDefinition::DefaultParser, using: {})
792
+ def self.from_definition(definition_or_path, default_resolve: nil, interpreter: true, parser: GraphQL.default_parser, using: {})
793
793
  # If the file ends in `.graphql`, treat it like a filepath
794
- definition = if definition_or_path.end_with?(".graphql")
795
- File.read(definition_or_path)
794
+ if definition_or_path.end_with?(".graphql")
795
+ GraphQL::Schema::BuildFromDefinition.from_definition_path(
796
+ definition_or_path,
797
+ default_resolve: default_resolve,
798
+ parser: parser,
799
+ using: using,
800
+ interpreter: interpreter,
801
+ )
796
802
  else
797
- definition_or_path
798
- end
799
- GraphQL::Schema::BuildFromDefinition.from_definition(
800
- definition,
801
- default_resolve: default_resolve,
802
- parser: parser,
803
- using: using,
804
- interpreter: interpreter,
805
- )
803
+ GraphQL::Schema::BuildFromDefinition.from_definition(
804
+ definition_or_path,
805
+ default_resolve: default_resolve,
806
+ parser: parser,
807
+ using: using,
808
+ interpreter: interpreter,
809
+ )
810
+ end
806
811
  end
807
812
 
808
813
  # Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
@@ -832,7 +837,7 @@ module GraphQL
832
837
  # @param except [<#call(member, ctx)>]
833
838
  # @return [Hash] GraphQL result
834
839
  def as_json(only: nil, except: nil, context: {})
835
- execute(Introspection::INTROSPECTION_QUERY, only: only, except: except, context: context).to_h
840
+ execute(Introspection.query(include_deprecated_args: true), only: only, except: except, context: context).to_h
836
841
  end
837
842
 
838
843
  # Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
@@ -880,7 +885,7 @@ module GraphQL
880
885
  # @param except [<#call(member, ctx)>]
881
886
  # @return [Hash] GraphQL result
882
887
  def as_json(only: nil, except: nil, context: {})
883
- execute(Introspection::INTROSPECTION_QUERY, only: only, except: except, context: context).to_h
888
+ execute(Introspection.query(include_deprecated_args: true), only: only, except: except, context: context).to_h
884
889
  end
885
890
 
886
891
  # Return the GraphQL IDL for the schema
@@ -945,6 +950,7 @@ module GraphQL
945
950
  schema_defn.query = query && query.graphql_definition
946
951
  schema_defn.mutation = mutation && mutation.graphql_definition
947
952
  schema_defn.subscription = subscription && subscription.graphql_definition
953
+ schema_defn.validate_timeout = validate_timeout
948
954
  schema_defn.max_complexity = max_complexity
949
955
  schema_defn.error_bubbling = error_bubbling
950
956
  schema_defn.max_depth = max_depth
@@ -1112,7 +1118,16 @@ module GraphQL
1112
1118
  if type.kind.union?
1113
1119
  type.possible_types(context: context)
1114
1120
  else
1115
- own_possible_types[type.graphql_name] ||
1121
+ stored_possible_types = own_possible_types[type.graphql_name]
1122
+ visible_possible_types = stored_possible_types.select do |possible_type|
1123
+ next true unless type.kind.interface?
1124
+ next true unless possible_type.kind.object?
1125
+
1126
+ # Use `.graphql_name` comparison to match legacy vs class-based types.
1127
+ # When we don't need to support legacy `.define` types, use `.include?(type)` instead.
1128
+ possible_type.interfaces(context).any? { |interface| interface.graphql_name == type.graphql_name }
1129
+ end if stored_possible_types
1130
+ visible_possible_types ||
1116
1131
  introspection_system.possible_types[type.graphql_name] ||
1117
1132
  (
1118
1133
  superclass.respond_to?(:possible_types) ?
@@ -1258,6 +1273,18 @@ module GraphQL
1258
1273
  end
1259
1274
  end
1260
1275
 
1276
+ attr_writer :validate_timeout
1277
+
1278
+ def validate_timeout(new_validate_timeout = nil)
1279
+ if new_validate_timeout
1280
+ @validate_timeout = new_validate_timeout
1281
+ elsif defined?(@validate_timeout)
1282
+ @validate_timeout
1283
+ else
1284
+ find_inherited_value(:validate_timeout)
1285
+ end
1286
+ end
1287
+
1261
1288
  attr_writer :max_complexity
1262
1289
 
1263
1290
  def max_complexity(max_complexity = nil)
@@ -1663,6 +1690,10 @@ module GraphQL
1663
1690
  end
1664
1691
  end
1665
1692
 
1693
+ def query_stack_error(query, err)
1694
+ query.context.errors.push(GraphQL::ExecutionError.new("This query is too large to execute."))
1695
+ end
1696
+
1666
1697
  private
1667
1698
 
1668
1699
  def lazy_methods