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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d626d72a5ae0bfb10f8fcdb9cbd781f04b5bb38b3f90b20de062a78679c254a8
4
- data.tar.gz: 6793ba627f3f59a43426258e187567f391a44f8973816fb0b1e1eb7784ae19b0
3
+ metadata.gz: 43f1cc3ef36a54a31f8afa03ee3109b34f046e26c427acfb80599a2dd245cf14
4
+ data.tar.gz: 4e4a15c766650e36004175de15cfcb9f67c6b4e7d24e2f91712a6ad3f8681453
5
5
  SHA512:
6
- metadata.gz: 5958721b08e45d886036f8afe0a5942e443117d9aa71d94450b727ec20d13b63a945a97c247f8605d4eb1ae8631ba301599e95b938355f18dc7c5bf64e2b1b44
7
- data.tar.gz: 9d029e7d0288c87cc9c09e627538b5e93b3d1ec7e785914b135088ec7bafcf8172458fa1d68a95a6385786d472c7260f6bc82b719e86743b5dac1f2a87501f7c
6
+ metadata.gz: 908f3790bcc773bb6c7fe3db1f5e2ccabf361ece7b462b80fc4e59911167eabb8baf544739f31ac425579bca61b56b46937ac60e7a54a03827228016457388de
7
+ data.tar.gz: 62fb9dc90ab55aff66d3d1621fc28b18c0c9599e2f8a7f8521d372a6f549c85ac0a2e50a0d43cb77bde728cb44f85b178bb37388c6bd3d2aed5f8e91723a79ef
@@ -65,14 +65,41 @@ module GraphQL
65
65
  end
66
66
 
67
67
  # Visitor Hooks
68
+ [
69
+ :operation_definition, :fragment_definition,
70
+ :inline_fragment, :field, :directive, :argument, :fragment_spread
71
+ ].each do |node_type|
72
+ module_eval <<-RUBY, __FILE__, __LINE__
73
+ def call_on_enter_#{node_type}(node, parent)
74
+ @analyzers.each do |a|
75
+ begin
76
+ a.on_enter_#{node_type}(node, parent, self)
77
+ rescue AnalysisError => err
78
+ @rescued_errors << err
79
+ end
80
+ end
81
+ end
82
+
83
+ def call_on_leave_#{node_type}(node, parent)
84
+ @analyzers.each do |a|
85
+ begin
86
+ a.on_leave_#{node_type}(node, parent, self)
87
+ rescue AnalysisError => err
88
+ @rescued_errors << err
89
+ end
90
+ end
91
+ end
92
+
93
+ RUBY
94
+ end
68
95
 
69
96
  def on_operation_definition(node, parent)
70
97
  object_type = @schema.root_type_for_operation(node.operation_type)
71
98
  @object_types.push(object_type)
72
99
  @path.push("#{node.operation_type}#{node.name ? " #{node.name}" : ""}")
73
- call_analyzers(:on_enter_operation_definition, node, parent)
100
+ call_on_enter_operation_definition(node, parent)
74
101
  super
75
- call_analyzers(:on_leave_operation_definition, node, parent)
102
+ call_on_leave_operation_definition(node, parent)
76
103
  @object_types.pop
77
104
  @path.pop
78
105
  end
@@ -81,19 +108,19 @@ module GraphQL
81
108
  on_fragment_with_type(node) do
82
109
  @path.push("fragment #{node.name}")
83
110
  @in_fragment_def = false
84
- call_analyzers(:on_enter_fragment_definition, node, parent)
111
+ call_on_enter_fragment_definition(node, parent)
85
112
  super
86
113
  @in_fragment_def = false
87
- call_analyzers(:on_leave_fragment_definition, node, parent)
114
+ call_on_leave_fragment_definition(node, parent)
88
115
  end
89
116
  end
90
117
 
91
118
  def on_inline_fragment(node, parent)
92
119
  on_fragment_with_type(node) do
93
120
  @path.push("...#{node.type ? " on #{node.type.name}" : ""}")
94
- call_analyzers(:on_enter_inline_fragment, node, parent)
121
+ call_on_enter_inline_fragment(node, parent)
95
122
  super
96
- call_analyzers(:on_leave_inline_fragment, node, parent)
123
+ call_on_leave_inline_fragment(node, parent)
97
124
  end
98
125
  end
99
126
 
@@ -114,12 +141,10 @@ module GraphQL
114
141
  @skipping = @skip_stack.last || skip?(node)
115
142
  @skip_stack << @skipping
116
143
 
117
- call_analyzers(:on_enter_field, node, parent)
144
+ call_on_enter_field(node, parent)
118
145
  super
119
-
120
146
  @skipping = @skip_stack.pop
121
-
122
- call_analyzers(:on_leave_field, node, parent)
147
+ call_on_leave_field(node, parent)
123
148
  @response_path.pop
124
149
  @field_definitions.pop
125
150
  @object_types.pop
@@ -129,9 +154,9 @@ module GraphQL
129
154
  def on_directive(node, parent)
130
155
  directive_defn = @schema.directives[node.name]
131
156
  @directive_definitions.push(directive_defn)
132
- call_analyzers(:on_enter_directive, node, parent)
157
+ call_on_enter_directive(node, parent)
133
158
  super
134
- call_analyzers(:on_leave_directive, node, parent)
159
+ call_on_leave_directive(node, parent)
135
160
  @directive_definitions.pop
136
161
  end
137
162
 
@@ -153,29 +178,23 @@ module GraphQL
153
178
 
154
179
  @argument_definitions.push(argument_defn)
155
180
  @path.push(node.name)
156
- call_analyzers(:on_enter_argument, node, parent)
181
+ call_on_enter_argument(node, parent)
157
182
  super
158
- call_analyzers(:on_leave_argument, node, parent)
183
+ call_on_leave_argument(node, parent)
159
184
  @argument_definitions.pop
160
185
  @path.pop
161
186
  end
162
187
 
163
188
  def on_fragment_spread(node, parent)
164
189
  @path.push("... #{node.name}")
165
- call_analyzers(:on_enter_fragment_spread, node, parent)
190
+ call_on_enter_fragment_spread(node, parent)
166
191
  enter_fragment_spread_inline(node)
167
192
  super
168
193
  leave_fragment_spread_inline(node)
169
- call_analyzers(:on_leave_fragment_spread, node, parent)
194
+ call_on_leave_fragment_spread(node, parent)
170
195
  @path.pop
171
196
  end
172
197
 
173
- def on_abstract_node(node, parent)
174
- call_analyzers(:on_enter_abstract_node, node, parent)
175
- super
176
- call_analyzers(:on_leave_abstract_node, node, parent)
177
- end
178
-
179
198
  # @return [GraphQL::BaseType] The current object type
180
199
  def type_definition
181
200
  @object_types.last
@@ -226,9 +245,7 @@ module GraphQL
226
245
 
227
246
  object_types << object_type
228
247
 
229
- fragment_def.selections.each do |selection|
230
- visit_node(selection, fragment_def)
231
- end
248
+ on_fragment_definition_children(fragment_def)
232
249
  end
233
250
 
234
251
  # Visit a fragment spread inline instead of visiting the definition
@@ -242,16 +259,6 @@ module GraphQL
242
259
  dir.any? && !GraphQL::Execution::DirectiveChecks.include?(dir, query)
243
260
  end
244
261
 
245
- def call_analyzers(method, node, parent)
246
- @analyzers.each do |analyzer|
247
- begin
248
- analyzer.public_send(method, node, parent, self)
249
- rescue AnalysisError => err
250
- @rescued_errors << err
251
- end
252
- end
253
- end
254
-
255
262
  def on_fragment_with_type(node)
256
263
  object_type = if node.type
257
264
  @query.warden.get_type(node.type.name)
@@ -21,7 +21,7 @@ module GraphQL
21
21
  def analyze_multiplex(multiplex, analyzers)
22
22
  multiplex_analyzers = analyzers.map { |analyzer| analyzer.new(multiplex) }
23
23
 
24
- multiplex.trace("analyze_multiplex", { multiplex: multiplex }) do
24
+ multiplex.current_trace.analyze_multiplex(multiplex: multiplex) do
25
25
  query_results = multiplex.queries.map do |query|
26
26
  if query.valid?
27
27
  analyze_query(
@@ -48,7 +48,7 @@ module GraphQL
48
48
  # @param analyzers [Array<GraphQL::Analysis::AST::Analyzer>]
49
49
  # @return [Array<Any>] Results from those analyzers
50
50
  def analyze_query(query, analyzers, multiplex_analyzers: [])
51
- query.trace("analyze_query", { query: query }) do
51
+ query.current_trace.analyze_query(query: query) do
52
52
  query_analyzers = analyzers
53
53
  .map { |analyzer| analyzer.new(query) }
54
54
  .select { |analyzer| analyzer.analyze? }
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Backtrace
4
+ module Trace
5
+ def validate(query:, validate:)
6
+ if query.multiplex
7
+ push_query_backtrace_context(query)
8
+ end
9
+ super
10
+ end
11
+
12
+ def analyze_query(query:)
13
+ if query.multiplex # missing for stand-alone static validation
14
+ push_query_backtrace_context(query)
15
+ end
16
+ super
17
+ end
18
+
19
+ def execute_query(query:)
20
+ push_query_backtrace_context(query)
21
+ super
22
+ end
23
+
24
+ def execute_query_lazy(query:, multiplex:)
25
+ query ||= multiplex.queries.first
26
+ push_query_backtrace_context(query)
27
+ super
28
+ end
29
+
30
+ def execute_field(field:, query:, ast_node:, arguments:, object:)
31
+ push_field_backtrace_context(field, query, ast_node, arguments, object)
32
+ super
33
+ end
34
+
35
+ def execute_field_lazy(field:, query:, ast_node:, arguments:, object:)
36
+ push_field_backtrace_context(field, query, ast_node, arguments, object)
37
+ super
38
+ end
39
+
40
+ def execute_multiplex(multiplex:)
41
+ super
42
+ rescue StandardError => err
43
+ # This is an unhandled error from execution,
44
+ # Re-raise it with a GraphQL trace.
45
+ multiplex_context = multiplex.context
46
+ potential_context = multiplex_context[:last_graphql_backtrace_context]
47
+
48
+ if potential_context.is_a?(GraphQL::Query::Context) ||
49
+ potential_context.is_a?(Backtrace::Frame)
50
+ raise TracedError.new(err, potential_context)
51
+ else
52
+ raise
53
+ end
54
+ ensure
55
+ multiplex_context = multiplex.context
56
+ multiplex_context.delete(:graphql_backtrace_contexts)
57
+ multiplex_context.delete(:last_graphql_backtrace_context)
58
+ end
59
+
60
+ private
61
+
62
+ def push_query_backtrace_context(query)
63
+ push_data = query
64
+ multiplex = query.multiplex
65
+ push_key = []
66
+ push_storage = multiplex.context[:graphql_backtrace_contexts] ||= {}
67
+ push_storage[push_key] = push_data
68
+ multiplex.context[:last_graphql_backtrace_context] = push_data
69
+ end
70
+
71
+ def push_field_backtrace_context(field, query, ast_node, arguments, object)
72
+ multiplex = query.multiplex
73
+ push_key = query.context[:current_path]
74
+ push_storage = multiplex.context[:graphql_backtrace_contexts]
75
+ parent_frame = push_storage[push_key[0..-2]]
76
+
77
+ if parent_frame.is_a?(GraphQL::Query)
78
+ parent_frame = parent_frame.context
79
+ end
80
+
81
+ push_data = Frame.new(
82
+ query: query,
83
+ path: push_key,
84
+ ast_node: ast_node,
85
+ field: field,
86
+ object: object,
87
+ arguments: arguments,
88
+ parent_frame: parent_frame,
89
+ )
90
+
91
+ push_storage[push_key] = push_data
92
+ multiplex.context[:last_graphql_backtrace_context] = push_data
93
+ end
94
+ end
95
+ end
96
+ end
@@ -25,7 +25,7 @@ module GraphQL
25
25
  when "execute_field", "execute_field_lazy"
26
26
  query = metadata[:query]
27
27
  multiplex = query.multiplex
28
- push_key = metadata[:path]
28
+ push_key = query.context[:current_path]
29
29
  parent_frame = multiplex.context[:graphql_backtrace_contexts][push_key[0..-2]]
30
30
 
31
31
  if parent_frame.is_a?(GraphQL::Query)
@@ -3,6 +3,7 @@ require "graphql/backtrace/inspect_result"
3
3
  require "graphql/backtrace/table"
4
4
  require "graphql/backtrace/traced_error"
5
5
  require "graphql/backtrace/tracer"
6
+ require "graphql/backtrace/trace"
6
7
  module GraphQL
7
8
  # Wrap unhandled errors with {TracedError}.
8
9
  #
@@ -23,7 +24,7 @@ module GraphQL
23
24
  def_delegators :to_a, :each, :[]
24
25
 
25
26
  def self.use(schema_defn)
26
- schema_defn.tracer(self::Tracer)
27
+ schema_defn.trace_with(self::Trace)
27
28
  end
28
29
 
29
30
  def initialize(context, value: nil)
@@ -54,5 +55,9 @@ module GraphQL
54
55
  @parent_frame = parent_frame
55
56
  end
56
57
  end
58
+
59
+ class DefaultBacktraceTrace < GraphQL::Tracing::Trace
60
+ include GraphQL::Backtrace::Trace
61
+ end
57
62
  end
58
63
  end
@@ -80,7 +80,7 @@ module GraphQL
80
80
  )
81
81
  end
82
82
 
83
- NO_ARGS = {}.freeze
83
+ NO_ARGS = GraphQL::EmptyObjects::EMPTY_HASH
84
84
  EMPTY = self.new(argument_values: nil, keyword_arguments: NO_ARGS).freeze
85
85
  end
86
86
  end
@@ -55,9 +55,8 @@ module GraphQL
55
55
 
56
56
  private
57
57
 
58
- NO_ARGUMENTS = {}.freeze
59
-
60
- NO_VALUE_GIVEN = Object.new
58
+ NO_ARGUMENTS = GraphQL::EmptyObjects::EMPTY_HASH
59
+ NO_VALUE_GIVEN = NOT_CONFIGURED
61
60
 
62
61
  def self.prepare_args_hash(query, ast_arg_or_hash_or_value)
63
62
  case ast_arg_or_hash_or_value
@@ -11,6 +11,25 @@ module GraphQL
11
11
  nil
12
12
  end
13
13
 
14
+ def self.resolve_each_depth(lazies_at_depth, dataloader)
15
+ depths = lazies_at_depth.keys
16
+ depths.sort!
17
+ next_depth = depths.first
18
+ if next_depth
19
+ lazies = lazies_at_depth[next_depth]
20
+ lazies_at_depth.delete(next_depth)
21
+ if lazies.any?
22
+ dataloader.append_job {
23
+ lazies.each(&:value) # resolve these Lazy instances
24
+ }
25
+ # Run lazies _and_ dataloader, see if more are enqueued
26
+ dataloader.run
27
+ resolve_each_depth(lazies_at_depth, dataloader)
28
+ end
29
+ end
30
+ nil
31
+ end
32
+
14
33
  # After getting `results` back from an interpreter evaluation,
15
34
  # continue it until you get a response-ready Ruby value.
16
35
  #