graphql 2.2.5 → 2.3.3

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/templates/schema.erb +3 -0
  3. data/lib/graphql/analysis/ast/field_usage.rb +36 -9
  4. data/lib/graphql/analysis/ast/query_complexity.rb +3 -0
  5. data/lib/graphql/analysis/ast/visitor.rb +8 -0
  6. data/lib/graphql/analysis/ast.rb +10 -1
  7. data/lib/graphql/backtrace/inspect_result.rb +0 -12
  8. data/lib/graphql/coercion_error.rb +1 -9
  9. data/lib/graphql/dataloader/request.rb +5 -0
  10. data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
  11. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +6 -4
  12. data/lib/graphql/execution/interpreter/runtime.rb +93 -106
  13. data/lib/graphql/execution/interpreter.rb +90 -150
  14. data/lib/graphql/introspection/entry_points.rb +9 -3
  15. data/lib/graphql/introspection/schema_type.rb +3 -1
  16. data/lib/graphql/language/document_from_schema_definition.rb +2 -3
  17. data/lib/graphql/language/lexer.rb +48 -30
  18. data/lib/graphql/language/nodes.rb +11 -16
  19. data/lib/graphql/language/parser.rb +94 -45
  20. data/lib/graphql/language/printer.rb +4 -0
  21. data/lib/graphql/language.rb +60 -0
  22. data/lib/graphql/pagination/array_connection.rb +6 -6
  23. data/lib/graphql/query/context.rb +30 -33
  24. data/lib/graphql/query/validation_pipeline.rb +2 -2
  25. data/lib/graphql/query/variables.rb +3 -3
  26. data/lib/graphql/query.rb +3 -3
  27. data/lib/graphql/schema/argument.rb +18 -2
  28. data/lib/graphql/schema/base_64_encoder.rb +3 -5
  29. data/lib/graphql/schema/build_from_definition.rb +9 -1
  30. data/lib/graphql/schema/field.rb +33 -30
  31. data/lib/graphql/schema/input_object.rb +1 -2
  32. data/lib/graphql/schema/interface.rb +5 -1
  33. data/lib/graphql/schema/loader.rb +2 -1
  34. data/lib/graphql/schema/member/has_arguments.rb +2 -2
  35. data/lib/graphql/schema/mutation.rb +7 -0
  36. data/lib/graphql/schema/resolver.rb +19 -10
  37. data/lib/graphql/schema/unique_within_type.rb +1 -1
  38. data/lib/graphql/schema.rb +129 -29
  39. data/lib/graphql/static_validation/literal_validator.rb +1 -2
  40. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +1 -1
  41. data/lib/graphql/static_validation/validator.rb +3 -0
  42. data/lib/graphql/subscriptions/serialize.rb +2 -0
  43. data/lib/graphql/subscriptions.rb +0 -3
  44. data/lib/graphql/testing/helpers.rb +32 -6
  45. data/lib/graphql/tracing/data_dog_trace.rb +21 -34
  46. data/lib/graphql/tracing/data_dog_tracing.rb +7 -21
  47. data/lib/graphql/tracing/legacy_hooks_trace.rb +74 -0
  48. data/lib/graphql/tracing/platform_tracing.rb +3 -1
  49. data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +3 -1
  50. data/lib/graphql/tracing/prometheus_trace.rb +2 -2
  51. data/lib/graphql/tracing/sentry_trace.rb +112 -0
  52. data/lib/graphql/tracing.rb +3 -1
  53. data/lib/graphql/version.rb +1 -1
  54. data/lib/graphql.rb +10 -2
  55. metadata +38 -23
  56. data/lib/graphql/schema/base_64_bp.rb +0 -26
  57. data/lib/graphql/subscriptions/instrumentation.rb +0 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 49aca16aba9ee96f9aa4229e07e5493b1e8c676a892a1fa1e9828323d44dc073
4
- data.tar.gz: 95eec1c3808a12b28bcc2732bb13baf9d52ddf3f34c4971abf92f6cff3333e93
3
+ metadata.gz: d1511256e7812b5c2de2a01ffa44f8a77f2e8959837344eaf1c8780d0b1bf700
4
+ data.tar.gz: 87a0734b541d8f2cbbd3fb293a63663cbc57c61e6ab39242449596c6ca759442
5
5
  SHA512:
6
- metadata.gz: 287acc2969a3b181d2d53dc94562335fac43de4cb8873844f063b63b604948e3edb7df318e53ec42906f678f7329efc5aa8d28bdbbfd4bc7f9d504a96f745df9
7
- data.tar.gz: 3ef6c000a5eeaddd295786e9baf147663556cc19c1bc46facf57b67233bf40780e42b4781f39ebd3966ca29bc6bab6b682e9bd475b4c2474f471841454cb3d3c
6
+ metadata.gz: fff5ef36d8e8dff310cac664178ebf0e902cd067a893fedd164902625751fe457a070f1daf2a2251d0dd2ec57fb16daccc81b54267048bbb71c027caf7905100
7
+ data.tar.gz: 5fc4e6c4a44398e9f77d99c5224d22128a9c80e64a17a156500337b4d658270da9aa7af71f8d06cc065939cc42b41de3e07d66cb7622704ad179424c312dd7a0
@@ -26,6 +26,9 @@ class <%= schema_name %> < GraphQL::Schema
26
26
  raise(GraphQL::RequiredImplementationMissingError)
27
27
  end
28
28
 
29
+ # Limit the size of incoming queries:
30
+ max_query_string_tokens(5000)
31
+
29
32
  # Stop validating when it encounters this many errors:
30
33
  validate_max_errors(100)
31
34
  end
@@ -8,6 +8,7 @@ module GraphQL
8
8
  @used_fields = Set.new
9
9
  @used_deprecated_fields = Set.new
10
10
  @used_deprecated_arguments = Set.new
11
+ @used_deprecated_enum_values = Set.new
11
12
  end
12
13
 
13
14
  def on_leave_field(node, parent, visitor)
@@ -15,7 +16,7 @@ module GraphQL
15
16
  field = "#{visitor.parent_type_definition.graphql_name}.#{field_defn.graphql_name}"
16
17
  @used_fields << field
17
18
  @used_deprecated_fields << field if field_defn.deprecation_reason
18
- arguments = visitor.query.arguments_for(node, visitor.field_definition)
19
+ arguments = visitor.query.arguments_for(node, field_defn)
19
20
  # If there was an error when preparing this argument object,
20
21
  # then this might be an error or something:
21
22
  if arguments.respond_to?(:argument_values)
@@ -28,6 +29,7 @@ module GraphQL
28
29
  used_fields: @used_fields.to_a,
29
30
  used_deprecated_fields: @used_deprecated_fields.to_a,
30
31
  used_deprecated_arguments: @used_deprecated_arguments.to_a,
32
+ used_deprecated_enum_values: @used_deprecated_enum_values.to_a,
31
33
  }
32
34
  end
33
35
 
@@ -39,18 +41,43 @@ module GraphQL
39
41
  @used_deprecated_arguments << argument.definition.path
40
42
  end
41
43
 
42
- next if argument.value.nil?
44
+ arg_val = argument.value
43
45
 
44
- if argument.definition.type.kind.input_object?
45
- extract_deprecated_arguments(argument.value.arguments.argument_values) # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
46
- elsif argument.definition.type.list?
47
- argument
48
- .value
49
- .select { |value| value.respond_to?(:arguments) }
50
- .each { |value| extract_deprecated_arguments(value.arguments.argument_values) } # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
46
+ next if arg_val.nil?
47
+
48
+ argument_type = argument.definition.type
49
+ if argument_type.non_null?
50
+ argument_type = argument_type.of_type
51
+ end
52
+
53
+ if argument_type.kind.input_object?
54
+ extract_deprecated_arguments(argument.original_value.arguments.argument_values) # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
55
+ elsif argument_type.kind.enum?
56
+ extract_deprecated_enum_value(argument_type, arg_val)
57
+ elsif argument_type.list?
58
+ inner_type = argument_type.unwrap
59
+ case inner_type.kind
60
+ when TypeKinds::INPUT_OBJECT
61
+ argument.original_value.each do |value|
62
+ extract_deprecated_arguments(value.arguments.argument_values) # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
63
+ end
64
+ when TypeKinds::ENUM
65
+ arg_val.each do |value|
66
+ extract_deprecated_enum_value(inner_type, value)
67
+ end
68
+ else
69
+ # Not a kind of input that we track
70
+ end
51
71
  end
52
72
  end
53
73
  end
74
+
75
+ def extract_deprecated_enum_value(enum_type, value)
76
+ enum_value = @query.warden.enum_values(enum_type).find { |ev| ev.value == value }
77
+ if enum_value&.deprecation_reason
78
+ @used_deprecated_enum_values << enum_value.path
79
+ end
80
+ end
54
81
  end
55
82
  end
56
83
  end
@@ -8,6 +8,7 @@ module GraphQL
8
8
  # - `complexities_on_type` holds complexity scores for each type
9
9
  def initialize(query)
10
10
  super
11
+ @skip_introspection_fields = !query.schema.max_complexity_count_introspection_fields
11
12
  @complexities_on_type_by_query = {}
12
13
  end
13
14
 
@@ -51,6 +52,7 @@ module GraphQL
51
52
  # we'll visit them when we hit the spreads instead
52
53
  return if visitor.visiting_fragment_definition?
53
54
  return if visitor.skipping?
55
+ return if @skip_introspection_fields && visitor.field_definition.introspection?
54
56
  parent_type = visitor.parent_type_definition
55
57
  field_key = node.alias || node.name
56
58
 
@@ -68,6 +70,7 @@ module GraphQL
68
70
  # we'll visit them when we hit the spreads instead
69
71
  return if visitor.visiting_fragment_definition?
70
72
  return if visitor.skipping?
73
+ return if @skip_introspection_fields && visitor.field_definition.introspection?
71
74
  scopes_stack = @complexities_on_type_by_query[visitor.query]
72
75
  scopes_stack.pop
73
76
  end
@@ -118,8 +118,12 @@ module GraphQL
118
118
  def on_inline_fragment(node, parent)
119
119
  on_fragment_with_type(node) do
120
120
  @path.push("...#{node.type ? " on #{node.type.name}" : ""}")
121
+ @skipping = @skip_stack.last || skip?(node)
122
+ @skip_stack << @skipping
123
+
121
124
  call_on_enter_inline_fragment(node, parent)
122
125
  super
126
+ @skipping = @skip_stack.pop
123
127
  call_on_leave_inline_fragment(node, parent)
124
128
  end
125
129
  end
@@ -187,9 +191,13 @@ module GraphQL
187
191
 
188
192
  def on_fragment_spread(node, parent)
189
193
  @path.push("... #{node.name}")
194
+ @skipping = @skip_stack.last || skip?(node)
195
+ @skip_stack << @skipping
196
+
190
197
  call_on_enter_fragment_spread(node, parent)
191
198
  enter_fragment_spread_inline(node)
192
199
  super
200
+ @skipping = @skip_stack.pop
193
201
  leave_fragment_spread_inline(node)
194
202
  call_on_leave_fragment_spread(node, parent)
195
203
  @path.pop
@@ -6,6 +6,7 @@ require "graphql/analysis/ast/query_complexity"
6
6
  require "graphql/analysis/ast/max_query_complexity"
7
7
  require "graphql/analysis/ast/query_depth"
8
8
  require "graphql/analysis/ast/max_query_depth"
9
+ require "timeout"
9
10
 
10
11
  module GraphQL
11
12
  module Analysis
@@ -63,7 +64,10 @@ module GraphQL
63
64
  analyzers: analyzers_to_run
64
65
  )
65
66
 
66
- visitor.visit
67
+ # `nil` or `0` causes no timeout
68
+ Timeout::timeout(query.validate_timeout_remaining) do
69
+ visitor.visit
70
+ end
67
71
 
68
72
  if visitor.rescued_errors.any?
69
73
  return visitor.rescued_errors
@@ -75,6 +79,11 @@ module GraphQL
75
79
  []
76
80
  end
77
81
  end
82
+ rescue Timeout::Error
83
+ [GraphQL::AnalysisError.new("Timeout on validation of query")]
84
+ rescue GraphQL::UnauthorizedError
85
+ # This error was raised during analysis and will be returned the client before execution
86
+ []
78
87
  end
79
88
 
80
89
  def analysis_errors(results)
@@ -16,12 +16,6 @@ module GraphQL
16
16
  "[" +
17
17
  obj.map { |v| inspect_truncated(v) }.join(", ") +
18
18
  "]"
19
- when Query::Context::SharedMethods
20
- if obj.invalid_null?
21
- "nil"
22
- else
23
- inspect_truncated(obj.value)
24
- end
25
19
  else
26
20
  inspect_truncated(obj)
27
21
  end
@@ -33,12 +27,6 @@ module GraphQL
33
27
  "{...}"
34
28
  when Array
35
29
  "[...]"
36
- when Query::Context::SharedMethods
37
- if obj.invalid_null?
38
- "nil"
39
- else
40
- inspect_truncated(obj.value)
41
- end
42
30
  when GraphQL::Execution::Lazy
43
31
  "(unresolved)"
44
32
  else
@@ -1,13 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- class CoercionError < GraphQL::Error
4
- # @return [Hash] Optional custom data for error objects which will be added
5
- # under the `extensions` key.
6
- attr_accessor :extensions
7
-
8
- def initialize(message, extensions: nil)
9
- @extensions = extensions
10
- super(message)
11
- end
3
+ class CoercionError < GraphQL::ExecutionError
12
4
  end
13
5
  end
@@ -14,6 +14,11 @@ module GraphQL
14
14
  def load
15
15
  @source.load(@key)
16
16
  end
17
+
18
+ def load_with_deprecation_warning
19
+ warn("Returning `.request(...)` from GraphQL::Dataloader is deprecated, use `.load(...)` instead. (See usage of #{@source} with #{@key.inspect}).")
20
+ load
21
+ end
17
22
  end
18
23
  end
19
24
  end
@@ -6,15 +6,19 @@ module GraphQL
6
6
  # A container for metadata regarding arguments present in a GraphQL query.
7
7
  # @see Interpreter::Arguments#argument_values for a hash of these objects.
8
8
  class ArgumentValue
9
- def initialize(definition:, value:, default_used:)
9
+ def initialize(definition:, value:, original_value:, default_used:)
10
10
  @definition = definition
11
11
  @value = value
12
+ @original_value = original_value
12
13
  @default_used = default_used
13
14
  end
14
15
 
15
16
  # @return [Object] The Ruby-ready value for this Argument
16
17
  attr_reader :value
17
18
 
19
+ # @return [Object] The value of this argument _before_ `prepare` is applied.
20
+ attr_reader :original_value
21
+
18
22
  # @return [GraphQL::Schema::Argument] The definition instance for this argument
19
23
  attr_reader :definition
20
24
 
@@ -5,8 +5,10 @@ module GraphQL
5
5
  class Interpreter
6
6
  class Runtime
7
7
  module GraphQLResult
8
- def initialize(result_name, parent_result, is_non_null_in_parent)
8
+ def initialize(result_name, result_type, application_value, parent_result, is_non_null_in_parent)
9
9
  @graphql_parent = parent_result
10
+ @graphql_application_value = application_value
11
+ @graphql_result_type = result_type
10
12
  if parent_result && parent_result.graphql_dead
11
13
  @graphql_dead = true
12
14
  end
@@ -26,14 +28,14 @@ module GraphQL
26
28
  end
27
29
 
28
30
  attr_accessor :graphql_dead
29
- attr_reader :graphql_parent, :graphql_result_name, :graphql_is_non_null_in_parent
31
+ attr_reader :graphql_parent, :graphql_result_name, :graphql_is_non_null_in_parent, :graphql_application_value, :graphql_result_type
30
32
 
31
33
  # @return [Hash] Plain-Ruby result data (`@graphql_metadata` contains Result wrapper objects)
32
34
  attr_accessor :graphql_result_data
33
35
  end
34
36
 
35
37
  class GraphQLResultHash
36
- def initialize(_result_name, _parent_result, _is_non_null_in_parent)
38
+ def initialize(_result_name, _result_type, _application_value, _parent_result, _is_non_null_in_parent)
37
39
  super
38
40
  @graphql_result_data = {}
39
41
  end
@@ -121,7 +123,7 @@ module GraphQL
121
123
  class GraphQLResultArray
122
124
  include GraphQLResult
123
125
 
124
- def initialize(_result_name, _parent_result, _is_non_null_in_parent)
126
+ def initialize(_result_name, _result_type, _application_value, _parent_result, _is_non_null_in_parent)
125
127
  super
126
128
  @graphql_result_data = []
127
129
  end