graphql 2.0.16 → 2.0.21

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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/analysis/ast/visitor.rb +42 -35
  3. data/lib/graphql/analysis/ast.rb +2 -2
  4. data/lib/graphql/backtrace/trace.rb +96 -0
  5. data/lib/graphql/backtrace/tracer.rb +1 -1
  6. data/lib/graphql/backtrace.rb +6 -1
  7. data/lib/graphql/execution/interpreter/arguments.rb +1 -1
  8. data/lib/graphql/execution/interpreter/arguments_cache.rb +2 -3
  9. data/lib/graphql/execution/interpreter/resolve.rb +19 -0
  10. data/lib/graphql/execution/interpreter/runtime.rb +264 -211
  11. data/lib/graphql/execution/interpreter.rb +15 -10
  12. data/lib/graphql/execution/lazy.rb +6 -12
  13. data/lib/graphql/execution/multiplex.rb +2 -1
  14. data/lib/graphql/filter.rb +7 -2
  15. data/lib/graphql/introspection/directive_type.rb +2 -2
  16. data/lib/graphql/introspection/field_type.rb +1 -1
  17. data/lib/graphql/introspection/schema_type.rb +2 -2
  18. data/lib/graphql/introspection/type_type.rb +5 -5
  19. data/lib/graphql/language/document_from_schema_definition.rb +25 -9
  20. data/lib/graphql/language/lexer.rb +216 -1505
  21. data/lib/graphql/language/nodes.rb +66 -40
  22. data/lib/graphql/language/parser.rb +509 -491
  23. data/lib/graphql/language/parser.y +43 -38
  24. data/lib/graphql/language/visitor.rb +191 -83
  25. data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
  26. data/lib/graphql/pagination/connection.rb +5 -5
  27. data/lib/graphql/query/context.rb +62 -31
  28. data/lib/graphql/query/null_context.rb +1 -1
  29. data/lib/graphql/query.rb +22 -5
  30. data/lib/graphql/schema/argument.rb +7 -13
  31. data/lib/graphql/schema/build_from_definition.rb +15 -3
  32. data/lib/graphql/schema/directive.rb +12 -2
  33. data/lib/graphql/schema/enum.rb +24 -17
  34. data/lib/graphql/schema/enum_value.rb +2 -3
  35. data/lib/graphql/schema/field.rb +68 -57
  36. data/lib/graphql/schema/field_extension.rb +1 -4
  37. data/lib/graphql/schema/find_inherited_value.rb +2 -7
  38. data/lib/graphql/schema/interface.rb +0 -10
  39. data/lib/graphql/schema/late_bound_type.rb +2 -0
  40. data/lib/graphql/schema/member/base_dsl_methods.rb +17 -14
  41. data/lib/graphql/schema/member/has_arguments.rb +105 -58
  42. data/lib/graphql/schema/member/has_ast_node.rb +12 -0
  43. data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
  44. data/lib/graphql/schema/member/has_directives.rb +15 -10
  45. data/lib/graphql/schema/member/has_fields.rb +95 -38
  46. data/lib/graphql/schema/member/has_interfaces.rb +49 -8
  47. data/lib/graphql/schema/member/has_validators.rb +32 -6
  48. data/lib/graphql/schema/member/relay_shortcuts.rb +19 -0
  49. data/lib/graphql/schema/member/type_system_helpers.rb +17 -0
  50. data/lib/graphql/schema/object.rb +2 -4
  51. data/lib/graphql/schema/resolver/has_payload_type.rb +9 -9
  52. data/lib/graphql/schema/resolver.rb +4 -4
  53. data/lib/graphql/schema/timeout.rb +24 -28
  54. data/lib/graphql/schema/validator.rb +1 -1
  55. data/lib/graphql/schema/warden.rb +29 -5
  56. data/lib/graphql/schema.rb +76 -25
  57. data/lib/graphql/static_validation/literal_validator.rb +15 -1
  58. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
  59. data/lib/graphql/static_validation/rules/fields_will_merge.rb +2 -2
  60. data/lib/graphql/static_validation/validator.rb +1 -1
  61. data/lib/graphql/subscriptions/event.rb +2 -7
  62. data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
  63. data/lib/graphql/tracing/appoptics_trace.rb +231 -0
  64. data/lib/graphql/tracing/appsignal_trace.rb +77 -0
  65. data/lib/graphql/tracing/data_dog_trace.rb +148 -0
  66. data/lib/graphql/tracing/legacy_trace.rb +65 -0
  67. data/lib/graphql/tracing/new_relic_trace.rb +75 -0
  68. data/lib/graphql/tracing/notifications_trace.rb +42 -0
  69. data/lib/graphql/tracing/platform_trace.rb +109 -0
  70. data/lib/graphql/tracing/platform_tracing.rb +15 -3
  71. data/lib/graphql/tracing/prometheus_trace.rb +89 -0
  72. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +1 -1
  73. data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
  74. data/lib/graphql/tracing/scout_trace.rb +72 -0
  75. data/lib/graphql/tracing/statsd_trace.rb +56 -0
  76. data/lib/graphql/tracing/trace.rb +75 -0
  77. data/lib/graphql/tracing.rb +16 -39
  78. data/lib/graphql/type_kinds.rb +6 -3
  79. data/lib/graphql/types/relay/base_connection.rb +1 -1
  80. data/lib/graphql/types/relay/connection_behaviors.rb +24 -6
  81. data/lib/graphql/types/relay/edge_behaviors.rb +16 -6
  82. data/lib/graphql/types/relay/node_behaviors.rb +7 -1
  83. data/lib/graphql/types/relay/page_info_behaviors.rb +7 -2
  84. data/lib/graphql/types/relay.rb +0 -1
  85. data/lib/graphql/types/string.rb +1 -1
  86. data/lib/graphql/version.rb +1 -1
  87. data/lib/graphql.rb +16 -9
  88. metadata +34 -9
  89. data/lib/graphql/language/lexer.rl +0 -280
  90. data/lib/graphql/types/relay/default_relay.rb +0 -27
@@ -14,7 +14,7 @@ module GraphQL
14
14
  class << self
15
15
  # Used internally to signal that the query shouldn't be executed
16
16
  # @api private
17
- NO_OPERATION = {}.freeze
17
+ NO_OPERATION = GraphQL::EmptyObjects::EMPTY_HASH
18
18
 
19
19
  # @param schema [GraphQL::Schema]
20
20
  # @param queries [Array<GraphQL::Query, Hash>]
@@ -34,11 +34,12 @@ module GraphQL
34
34
  end
35
35
 
36
36
  multiplex = Execution::Multiplex.new(schema: schema, queries: queries, context: context, max_complexity: max_complexity)
37
- multiplex.trace("execute_multiplex", { multiplex: multiplex }) do
37
+ multiplex.current_trace.execute_multiplex(multiplex: multiplex) do
38
38
  schema = multiplex.schema
39
39
  queries = multiplex.queries
40
40
  query_instrumenters = schema.instrumenters[:query]
41
41
  multiplex_instrumenters = schema.instrumenters[:multiplex]
42
+ lazies_at_depth = Hash.new { |h, k| h[k] = [] }
42
43
 
43
44
  # First, run multiplex instrumentation, then query instrumentation for each query
44
45
  call_hooks(multiplex_instrumenters, multiplex, :before_multiplex, :after_multiplex) do
@@ -67,10 +68,10 @@ module GraphQL
67
68
  # Although queries in a multiplex _share_ an Interpreter instance,
68
69
  # they also have another item of state, which is private to that query
69
70
  # in particular, assign it here:
70
- runtime = Runtime.new(query: query)
71
+ runtime = Runtime.new(query: query, lazies_at_depth: lazies_at_depth)
71
72
  query.context.namespace(:interpreter_runtime)[:runtime] = runtime
72
73
 
73
- query.trace("execute_query", {query: query}) do
74
+ query.current_trace.execute_query(query: query) do
74
75
  runtime.run_eager
75
76
  end
76
77
  rescue GraphQL::ExecutionError => err
@@ -95,16 +96,13 @@ module GraphQL
95
96
  runtime ? runtime.final_result : nil
96
97
  end
97
98
  final_values.compact!
98
- tracer.trace("execute_query_lazy", {multiplex: multiplex, query: query}) do
99
- Interpreter::Resolve.resolve_all(final_values, multiplex.dataloader)
99
+ tracer.current_trace.execute_query_lazy(multiplex: multiplex, query: query) do
100
+ Interpreter::Resolve.resolve_each_depth(lazies_at_depth, multiplex.dataloader)
100
101
  end
101
102
  queries.each do |query|
102
103
  runtime = query.context.namespace(:interpreter_runtime)[:runtime]
103
104
  if runtime
104
- runtime.delete_interpreter_context(:current_path)
105
- runtime.delete_interpreter_context(:current_field)
106
- runtime.delete_interpreter_context(:current_object)
107
- runtime.delete_interpreter_context(:current_arguments)
105
+ runtime.delete_all_interpreter_context
108
106
  end
109
107
  end
110
108
  }
@@ -146,6 +144,13 @@ module GraphQL
146
144
  # Assign values here so that the query's `@executed` becomes true
147
145
  queries.map { |q| q.result_values ||= {} }
148
146
  raise
147
+ ensure
148
+ queries.map { |query|
149
+ runtime = query.context.namespace(:interpreter_runtime)[:runtime]
150
+ if runtime
151
+ runtime.delete_all_interpreter_context
152
+ end
153
+ }
149
154
  end
150
155
  end
151
156
  end
@@ -12,16 +12,14 @@ module GraphQL
12
12
  # - It has no error-catching functionality
13
13
  # @api private
14
14
  class Lazy
15
- attr_reader :path, :field
15
+ attr_reader :field
16
16
 
17
17
  # Create a {Lazy} which will get its inner value by calling the block
18
- # @param path [Array<String, Integer>]
19
18
  # @param field [GraphQL::Schema::Field]
20
19
  # @param get_value_func [Proc] a block to get the inner value (later)
21
- def initialize(path: nil, field: nil, &get_value_func)
20
+ def initialize(field: nil, &get_value_func)
22
21
  @get_value_func = get_value_func
23
22
  @resolved = false
24
- @path = path
25
23
  @field = field
26
24
  end
27
25
 
@@ -29,15 +27,11 @@ module GraphQL
29
27
  def value
30
28
  if !@resolved
31
29
  @resolved = true
32
- @value = begin
33
- v = @get_value_func.call
34
- if v.is_a?(Lazy)
35
- v = v.value
36
- end
37
- v
38
- rescue GraphQL::ExecutionError => err
39
- err
30
+ v = @get_value_func.call
31
+ if v.is_a?(Lazy)
32
+ v = v.value
40
33
  end
34
+ @value = v
41
35
  end
42
36
 
43
37
  # `SKIP` was made into a subclass of `GraphQL::Error` to improve runtime performance
@@ -25,13 +25,14 @@ module GraphQL
25
25
  class Multiplex
26
26
  include Tracing::Traceable
27
27
 
28
- attr_reader :context, :queries, :schema, :max_complexity, :dataloader
28
+ attr_reader :context, :queries, :schema, :max_complexity, :dataloader, :current_trace
29
29
 
30
30
  def initialize(schema:, queries:, context:, max_complexity:)
31
31
  @schema = schema
32
32
  @queries = queries
33
33
  @queries.each { |q| q.multiplex = self }
34
34
  @context = context
35
+ @current_trace = @context[:trace] || schema.new_trace(multiplex: self)
35
36
  @dataloader = @context[:dataloader] ||= @schema.dataloader_class.new
36
37
  @tracers = schema.tracers + (context[:tracers] || [])
37
38
  # Support `context: {backtrace: true}`
@@ -1,8 +1,13 @@
1
1
  # frozen_string_literal: true
2
+ require "graphql/deprecation"
3
+
2
4
  module GraphQL
3
5
  # @api private
4
6
  class Filter
5
- def initialize(only: nil, except: nil)
7
+ def initialize(only: nil, except: nil, silence_deprecation_warning: false)
8
+ if !silence_deprecation_warning
9
+ GraphQL::Deprecation.warn("GraphQL::Filter is deprecated and will be removed in v2.1.0. Implement `visible?` on your schema members instead (https://graphql-ruby.org/authorization/visibility.html).")
10
+ end
6
11
  @only = only
7
12
  @except = except
8
13
  end
@@ -17,7 +22,7 @@ module GraphQL
17
22
  onlies = [self].concat(Array(only))
18
23
  merged_only = MergedOnly.build(onlies)
19
24
  merged_except = MergedExcept.build(Array(except))
20
- self.class.new(only: merged_only, except: merged_except)
25
+ self.class.new(only: merged_only, except: merged_except, silence_deprecation_warning: true)
21
26
  end
22
27
 
23
28
  private
@@ -11,8 +11,8 @@ module GraphQL
11
11
  "to the executor."
12
12
  field :name, String, null: false, method: :graphql_name
13
13
  field :description, String
14
- field :locations, [GraphQL::Schema::LateBoundType.new("__DirectiveLocation")], null: false
15
- field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
14
+ field :locations, [GraphQL::Schema::LateBoundType.new("__DirectiveLocation")], null: false, scope: false
15
+ field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false, scope: false do
16
16
  argument :include_deprecated, Boolean, required: false, default_value: false
17
17
  end
18
18
  field :on_operation, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_operation?
@@ -7,7 +7,7 @@ module GraphQL
7
7
  "a name, potentially a list of arguments, and a return type."
8
8
  field :name, String, null: false
9
9
  field :description, String
10
- field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
10
+ field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false, scope: false do
11
11
  argument :include_deprecated, Boolean, required: false, default_value: false
12
12
  end
13
13
  field :type, GraphQL::Schema::LateBoundType.new("__Type"), null: false
@@ -8,11 +8,11 @@ module GraphQL
8
8
  "available types and directives on the server, as well as the entry points for "\
9
9
  "query, mutation, and subscription operations."
10
10
 
11
- field :types, [GraphQL::Schema::LateBoundType.new("__Type")], "A list of all types supported by this server.", null: false
11
+ field :types, [GraphQL::Schema::LateBoundType.new("__Type")], "A list of all types supported by this server.", null: false, scope: false
12
12
  field :query_type, GraphQL::Schema::LateBoundType.new("__Type"), "The type that query operations will be rooted at.", null: false
13
13
  field :mutation_type, GraphQL::Schema::LateBoundType.new("__Type"), "If this server supports mutation, the type that mutation operations will be rooted at."
14
14
  field :subscription_type, GraphQL::Schema::LateBoundType.new("__Type"), "If this server support subscription, the type that subscription operations will be rooted at."
15
- field :directives, [GraphQL::Schema::LateBoundType.new("__Directive")], "A list of all directives supported by this server.", null: false
15
+ field :directives, [GraphQL::Schema::LateBoundType.new("__Directive")], "A list of all directives supported by this server.", null: false, scope: false
16
16
  field :description, String, resolver_method: :schema_description
17
17
 
18
18
  def schema_description
@@ -14,15 +14,15 @@ module GraphQL
14
14
  field :kind, GraphQL::Schema::LateBoundType.new("__TypeKind"), null: false
15
15
  field :name, String, method: :graphql_name
16
16
  field :description, String
17
- field :fields, [GraphQL::Schema::LateBoundType.new("__Field")] do
17
+ field :fields, [GraphQL::Schema::LateBoundType.new("__Field")], scope: false do
18
18
  argument :include_deprecated, Boolean, required: false, default_value: false
19
19
  end
20
- field :interfaces, [GraphQL::Schema::LateBoundType.new("__Type")]
21
- field :possible_types, [GraphQL::Schema::LateBoundType.new("__Type")]
22
- field :enum_values, [GraphQL::Schema::LateBoundType.new("__EnumValue")] do
20
+ field :interfaces, [GraphQL::Schema::LateBoundType.new("__Type")], scope: false
21
+ field :possible_types, [GraphQL::Schema::LateBoundType.new("__Type")], scope: false
22
+ field :enum_values, [GraphQL::Schema::LateBoundType.new("__EnumValue")], scope: false do
23
23
  argument :include_deprecated, Boolean, required: false, default_value: false
24
24
  end
25
- field :input_fields, [GraphQL::Schema::LateBoundType.new("__InputValue")] do
25
+ field :input_fields, [GraphQL::Schema::LateBoundType.new("__InputValue")], scope: false do
26
26
  argument :include_deprecated, Boolean, required: false, default_value: false
27
27
  end
28
28
  field :of_type, GraphQL::Schema::LateBoundType.new("__Type")
@@ -22,8 +22,9 @@ module GraphQL
22
22
  @include_introspection_types = include_introspection_types
23
23
  @include_built_in_scalars = include_built_in_scalars
24
24
  @include_built_in_directives = include_built_in_directives
25
+ @include_one_of = false
25
26
 
26
- filter = GraphQL::Filter.new(only: only, except: except)
27
+ filter = GraphQL::Filter.new(only: only, except: except, silence_deprecation_warning: true)
27
28
  if @schema.respond_to?(:visible?)
28
29
  filter = filter.merge(only: @schema.method(:visible?))
29
30
  end
@@ -245,20 +246,30 @@ module GraphQL
245
246
  end
246
247
 
247
248
  def build_directive_nodes(directives)
248
- if !include_built_in_directives
249
- directives = directives.reject { |directive| directive.default_directive? }
250
- end
251
-
252
249
  directives
253
250
  .map { |directive| build_directive_node(directive) }
254
251
  .sort_by(&:name)
255
252
  end
256
253
 
257
254
  def build_definition_nodes
258
- definitions = []
259
- definitions << build_schema_node if include_schema_node?
260
- definitions += build_directive_nodes(warden.directives)
261
- definitions += build_type_definition_nodes(warden.reachable_types)
255
+ dirs_to_build = warden.directives
256
+ if !include_built_in_directives
257
+ dirs_to_build = dirs_to_build.reject { |directive| directive.default_directive? }
258
+ end
259
+ dir_nodes = build_directive_nodes(dirs_to_build)
260
+
261
+ type_nodes = build_type_definition_nodes(warden.reachable_types)
262
+
263
+ if @include_one_of
264
+ # This may have been set to true when iterating over all types
265
+ dir_nodes.concat(build_directive_nodes([GraphQL::Schema::Directive::OneOf]))
266
+ end
267
+
268
+ definitions = [*dir_nodes, *type_nodes]
269
+ if include_schema_node?
270
+ definitions.unshift(build_schema_node)
271
+ end
272
+
262
273
  definitions
263
274
  end
264
275
 
@@ -318,6 +329,11 @@ module GraphQL
318
329
  )
319
330
  end
320
331
  end
332
+
333
+ # If this schema uses this built-in directive definition,
334
+ # include it in the print-out since it's not part of the spec yet.
335
+ @include_one_of ||= dir.class == GraphQL::Schema::Directive::OneOf
336
+
321
337
  GraphQL::Language::Nodes::Directive.new(
322
338
  name: dir.class.graphql_name,
323
339
  arguments: args