graphql 1.12.1 → 1.12.6

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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install_generator.rb +4 -1
  3. data/lib/generators/graphql/loader_generator.rb +1 -0
  4. data/lib/generators/graphql/mutation_generator.rb +1 -0
  5. data/lib/generators/graphql/relay.rb +55 -0
  6. data/lib/generators/graphql/relay_generator.rb +4 -46
  7. data/lib/generators/graphql/type_generator.rb +1 -0
  8. data/lib/graphql.rb +5 -3
  9. data/lib/graphql/analysis/analyze_query.rb +1 -1
  10. data/lib/graphql/analysis/ast.rb +1 -1
  11. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  12. data/lib/graphql/backtrace/table.rb +0 -1
  13. data/lib/graphql/backtrace/traced_error.rb +0 -1
  14. data/lib/graphql/backtrace/tracer.rb +4 -8
  15. data/lib/graphql/backwards_compatibility.rb +1 -1
  16. data/lib/graphql/base_type.rb +1 -1
  17. data/lib/graphql/compatibility/execution_specification.rb +1 -1
  18. data/lib/graphql/compatibility/lazy_execution_specification.rb +1 -1
  19. data/lib/graphql/compatibility/query_parser_specification.rb +1 -1
  20. data/lib/graphql/compatibility/schema_parser_specification.rb +1 -1
  21. data/lib/graphql/dataloader.rb +102 -92
  22. data/lib/graphql/dataloader/null_dataloader.rb +5 -5
  23. data/lib/graphql/dataloader/request.rb +1 -6
  24. data/lib/graphql/dataloader/request_all.rb +1 -4
  25. data/lib/graphql/dataloader/source.rb +20 -6
  26. data/lib/graphql/define/instance_definable.rb +1 -1
  27. data/lib/graphql/deprecated_dsl.rb +4 -4
  28. data/lib/graphql/deprecation.rb +13 -0
  29. data/lib/graphql/execution/errors.rb +1 -1
  30. data/lib/graphql/execution/execute.rb +1 -1
  31. data/lib/graphql/execution/interpreter.rb +3 -3
  32. data/lib/graphql/execution/interpreter/arguments_cache.rb +37 -14
  33. data/lib/graphql/execution/interpreter/resolve.rb +33 -25
  34. data/lib/graphql/execution/interpreter/runtime.rb +36 -74
  35. data/lib/graphql/execution/multiplex.rb +22 -23
  36. data/lib/graphql/function.rb +1 -1
  37. data/lib/graphql/internal_representation/document.rb +2 -2
  38. data/lib/graphql/internal_representation/rewrite.rb +1 -1
  39. data/lib/graphql/language.rb +1 -0
  40. data/lib/graphql/language/cache.rb +37 -0
  41. data/lib/graphql/language/parser.rb +15 -5
  42. data/lib/graphql/language/parser.y +15 -5
  43. data/lib/graphql/object_type.rb +0 -2
  44. data/lib/graphql/pagination/connection.rb +15 -1
  45. data/lib/graphql/pagination/connections.rb +2 -1
  46. data/lib/graphql/pagination/relation_connection.rb +5 -1
  47. data/lib/graphql/parse_error.rb +0 -1
  48. data/lib/graphql/query.rb +8 -2
  49. data/lib/graphql/query/arguments.rb +1 -1
  50. data/lib/graphql/query/arguments_cache.rb +0 -1
  51. data/lib/graphql/query/context.rb +1 -3
  52. data/lib/graphql/query/executor.rb +0 -1
  53. data/lib/graphql/query/null_context.rb +3 -2
  54. data/lib/graphql/query/serial_execution.rb +1 -1
  55. data/lib/graphql/query/variable_validation_error.rb +1 -1
  56. data/lib/graphql/railtie.rb +9 -1
  57. data/lib/graphql/relay/base_connection.rb +2 -2
  58. data/lib/graphql/relay/mutation.rb +1 -1
  59. data/lib/graphql/relay/node.rb +3 -3
  60. data/lib/graphql/relay/range_add.rb +10 -5
  61. data/lib/graphql/relay/type_extensions.rb +2 -2
  62. data/lib/graphql/schema.rb +14 -13
  63. data/lib/graphql/schema/argument.rb +61 -0
  64. data/lib/graphql/schema/field.rb +12 -7
  65. data/lib/graphql/schema/field/connection_extension.rb +1 -0
  66. data/lib/graphql/schema/find_inherited_value.rb +3 -1
  67. data/lib/graphql/schema/input_object.rb +6 -2
  68. data/lib/graphql/schema/member/has_arguments.rb +43 -56
  69. data/lib/graphql/schema/member/has_fields.rb +1 -4
  70. data/lib/graphql/schema/member/instrumentation.rb +0 -1
  71. data/lib/graphql/schema/middleware_chain.rb +1 -1
  72. data/lib/graphql/schema/resolver.rb +28 -1
  73. data/lib/graphql/schema/timeout_middleware.rb +1 -1
  74. data/lib/graphql/schema/validation.rb +2 -2
  75. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
  76. data/lib/graphql/static_validation/validator.rb +2 -2
  77. data/lib/graphql/subscriptions/event.rb +0 -1
  78. data/lib/graphql/subscriptions/instrumentation.rb +0 -1
  79. data/lib/graphql/subscriptions/serialize.rb +0 -1
  80. data/lib/graphql/subscriptions/subscription_root.rb +1 -1
  81. data/lib/graphql/tracing/active_support_notifications_tracing.rb +2 -1
  82. data/lib/graphql/tracing/skylight_tracing.rb +1 -1
  83. data/lib/graphql/types/relay/connection_behaviors.rb +25 -3
  84. data/lib/graphql/upgrader/member.rb +1 -1
  85. data/lib/graphql/upgrader/schema.rb +1 -1
  86. data/lib/graphql/version.rb +1 -1
  87. data/readme.md +1 -1
  88. metadata +6 -87
@@ -30,7 +30,7 @@ module GraphQL
30
30
  alias :input_fields :arguments
31
31
 
32
32
  def initialize
33
- warn "GraphQL::Relay::Mutation will be removed from GraphQL-Ruby 2.0, use GraphQL::Schema::RelayClassicMutation instead: https://graphql-ruby.org/mutations/mutation_classes"
33
+ GraphQL::Deprecation.warn "GraphQL::Relay::Mutation will be removed from GraphQL-Ruby 2.0, use GraphQL::Schema::RelayClassicMutation instead: https://graphql-ruby.org/mutations/mutation_classes"
34
34
  @fields = {}
35
35
  @arguments = {}
36
36
  @has_generated_return_type = false
@@ -5,7 +5,7 @@ module GraphQL
5
5
  module Node
6
6
  # @return [GraphQL::Field] a field for finding objects by their global ID.
7
7
  def self.field(**kwargs, &block)
8
- warn "GraphQL::Relay::Node.field will be removed from GraphQL-Ruby 2.0, use GraphQL::Types::Relay::NodeField instead"
8
+ GraphQL::Deprecation.warn "GraphQL::Relay::Node.field will be removed from GraphQL-Ruby 2.0, use GraphQL::Types::Relay::NodeField instead"
9
9
  # We have to define it fresh each time because
10
10
  # its name will be modified and its description
11
11
  # _may_ be modified.
@@ -19,7 +19,7 @@ module GraphQL
19
19
  end
20
20
 
21
21
  def self.plural_field(**kwargs, &block)
22
- warn "GraphQL::Relay::Nodes.field will be removed from GraphQL-Ruby 2.0, use GraphQL::Types::Relay::NodesField instead"
22
+ GraphQL::Deprecation.warn "GraphQL::Relay::Nodes.field will be removed from GraphQL-Ruby 2.0, use GraphQL::Types::Relay::NodesField instead"
23
23
  field = GraphQL::Types::Relay::NodesField.graphql_definition
24
24
 
25
25
  if kwargs.any? || block
@@ -31,7 +31,7 @@ module GraphQL
31
31
 
32
32
  # @return [GraphQL::InterfaceType] The interface which all Relay types must implement
33
33
  def self.interface
34
- warn "GraphQL::Relay::Node.interface will be removed from GraphQL-Ruby 2.0, use GraphQL::Types::Relay::Node instead"
34
+ GraphQL::Deprecation.warn "GraphQL::Relay::Node.interface will be removed from GraphQL-Ruby 2.0, use GraphQL::Types::Relay::Node instead"
35
35
  @interface ||= GraphQL::Types::Relay::Node.graphql_definition
36
36
  end
37
37
  end
@@ -9,7 +9,7 @@ module GraphQL
9
9
  # should be ordered and paginated before providing it here.
10
10
  #
11
11
  # @example Adding a comment to list of comments
12
- # post = Post.find(args[:postId])
12
+ # post = Post.find(args[:post_id])
13
13
  # comments = post.comments
14
14
  # new_comment = comments.build(body: args[:body])
15
15
  # new_comment.save!
@@ -18,13 +18,13 @@ module GraphQL
18
18
  # parent: post,
19
19
  # collection: comments,
20
20
  # item: new_comment,
21
- # context: ctx,
21
+ # context: context,
22
22
  # )
23
23
  #
24
24
  # response = {
25
25
  # post: post,
26
- # commentsConnection: range_add.connection,
27
- # newCommentEdge: range_add.edge,
26
+ # comments_connection: range_add.connection,
27
+ # new_comment_edge: range_add.edge,
28
28
  # }
29
29
  class RangeAdd
30
30
  attr_reader :edge, :connection, :parent
@@ -39,7 +39,12 @@ module GraphQL
39
39
  conn_class = context.schema.connections.wrapper_for(collection)
40
40
  # The rest will be added by ConnectionExtension
41
41
  @connection = conn_class.new(collection, parent: parent, context: context, edge_class: edge_class)
42
- @edge = @connection.edge_class.new(item, @connection)
42
+ # Check if this connection supports it, to support old versions of GraphQL-Pro
43
+ @edge = if @connection.respond_to?(:range_add_edge)
44
+ @connection.range_add_edge(item)
45
+ else
46
+ @connection.edge_class.new(item, @connection)
47
+ end
43
48
  else
44
49
  connection_class = BaseConnection.connection_for_nodes(collection)
45
50
  @connection = connection_class.new(collection, {}, parent: parent, context: context)
@@ -12,7 +12,7 @@ module GraphQL
12
12
  # Define a custom connection type for this object type
13
13
  # @return [GraphQL::ObjectType]
14
14
  def define_connection(**kwargs, &block)
15
- warn ".connection_type and .define_connection will be removed from GraphQL-Ruby 2.0, use class-based type definitions instead: https://graphql-ruby.org/schema/class_based_api.html"
15
+ GraphQL::Deprecation.warn ".connection_type and .define_connection will be removed from GraphQL-Ruby 2.0, use class-based type definitions instead: https://graphql-ruby.org/schema/class_based_api.html"
16
16
  GraphQL::Relay::ConnectionType.create_type(self, **kwargs, &block)
17
17
  end
18
18
 
@@ -24,7 +24,7 @@ module GraphQL
24
24
  # Define a custom edge type for this object type
25
25
  # @return [GraphQL::ObjectType]
26
26
  def define_edge(**kwargs, &block)
27
- warn ".edge_type and .define_edge will be removed from GraphQL-Ruby 2.0, use class-based type definitions instead: https://graphql-ruby.org/schema/class_based_api.html"
27
+ GraphQL::Deprecation.warn ".edge_type and .define_edge will be removed from GraphQL-Ruby 2.0, use class-based type definitions instead: https://graphql-ruby.org/schema/class_based_api.html"
28
28
  GraphQL::Relay::EdgeType.create_type(self, **kwargs, &block)
29
29
  end
30
30
  end
@@ -184,7 +184,7 @@ module GraphQL
184
184
  },
185
185
  query_analyzer: ->(schema, analyzer) {
186
186
  if analyzer == GraphQL::Authorization::Analyzer
187
- warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
187
+ GraphQL::Deprecation.warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
188
188
  end
189
189
  schema.query_analyzers << analyzer
190
190
  },
@@ -1118,14 +1118,15 @@ module GraphQL
1118
1118
  type.possible_types(context: context)
1119
1119
  else
1120
1120
  stored_possible_types = own_possible_types[type.graphql_name]
1121
- visible_possible_types = stored_possible_types.select do |possible_type|
1122
- next true unless type.kind.interface?
1123
- next true unless possible_type.kind.object?
1124
-
1125
- # Use `.graphql_name` comparison to match legacy vs class-based types.
1126
- # When we don't need to support legacy `.define` types, use `.include?(type)` instead.
1127
- possible_type.interfaces(context).any? { |interface| interface.graphql_name == type.graphql_name }
1128
- end if stored_possible_types
1121
+ visible_possible_types = if stored_possible_types && type.kind.interface?
1122
+ stored_possible_types.select do |possible_type|
1123
+ # Use `.graphql_name` comparison to match legacy vs class-based types.
1124
+ # When we don't need to support legacy `.define` types, use `.include?(type)` instead.
1125
+ possible_type.interfaces(context).any? { |interface| interface.graphql_name == type.graphql_name }
1126
+ end
1127
+ else
1128
+ stored_possible_types
1129
+ end
1129
1130
  visible_possible_types ||
1130
1131
  introspection_system.possible_types[type.graphql_name] ||
1131
1132
  (
@@ -1564,7 +1565,7 @@ module GraphQL
1564
1565
 
1565
1566
  def instrument(instrument_step, instrumenter, options = {})
1566
1567
  if instrument_step == :field
1567
- warn "Field instrumentation (#{instrumenter.inspect}) will be removed in GraphQL-Ruby 2.0, please upgrade to field extensions: https://graphql-ruby.org/type_definitions/field_extensions.html"
1568
+ GraphQL::Deprecation.warn "Field instrumentation (#{instrumenter.inspect}) will be removed in GraphQL-Ruby 2.0, please upgrade to field extensions: https://graphql-ruby.org/type_definitions/field_extensions.html"
1568
1569
  end
1569
1570
 
1570
1571
  step = if instrument_step == :field && options[:after_built_ins]
@@ -1614,7 +1615,7 @@ module GraphQL
1614
1615
 
1615
1616
  def query_analyzer(new_analyzer)
1616
1617
  if new_analyzer == GraphQL::Authorization::Analyzer
1617
- warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
1618
+ GraphQL::Deprecation.warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
1618
1619
  end
1619
1620
  own_query_analyzers << new_analyzer
1620
1621
  end
@@ -1625,7 +1626,7 @@ module GraphQL
1625
1626
 
1626
1627
  def middleware(new_middleware = nil)
1627
1628
  if new_middleware
1628
- warn "Middleware will be removed in GraphQL-Ruby 2.0, please upgrade to Field Extensions: https://graphql-ruby.org/type_definitions/field_extensions.html"
1629
+ GraphQL::Deprecation.warn "Middleware will be removed in GraphQL-Ruby 2.0, please upgrade to Field Extensions: https://graphql-ruby.org/type_definitions/field_extensions.html"
1629
1630
  own_middleware << new_middleware
1630
1631
  else
1631
1632
  # TODO make sure this is cached when running a query
@@ -1702,7 +1703,7 @@ module GraphQL
1702
1703
  if interpreter? && !defined?(@subscription_extension_added) && subscription && self.subscriptions
1703
1704
  @subscription_extension_added = true
1704
1705
  if subscription.singleton_class.ancestors.include?(Subscriptions::SubscriptionRoot)
1705
- warn("`extend Subscriptions::SubscriptionRoot` is no longer required; you may remove it from #{self}'s `subscription` root type (#{subscription}).")
1706
+ GraphQL::Deprecation.warn("`extend Subscriptions::SubscriptionRoot` is no longer required; you may remove it from #{self}'s `subscription` root type (#{subscription}).")
1706
1707
  else
1707
1708
  subscription.fields.each do |name, field|
1708
1709
  field.extension(Subscriptions::DefaultSubscriptionResolveExtension)
@@ -236,6 +236,67 @@ module GraphQL
236
236
  end
237
237
  end
238
238
 
239
+ # @api private
240
+ def coerce_into_values(parent_object, values, context, argument_values)
241
+ arg_name = graphql_name
242
+ arg_key = keyword
243
+ has_value = false
244
+ default_used = false
245
+ if values.key?(arg_name)
246
+ has_value = true
247
+ value = values[arg_name]
248
+ elsif values.key?(arg_key)
249
+ has_value = true
250
+ value = values[arg_key]
251
+ elsif default_value?
252
+ has_value = true
253
+ value = default_value
254
+ default_used = true
255
+ end
256
+
257
+ if has_value
258
+ loaded_value = nil
259
+ coerced_value = context.schema.error_handler.with_error_handling(context) do
260
+ type.coerce_input(value, context)
261
+ end
262
+
263
+ # TODO this should probably be inside after_lazy
264
+ if loads && !from_resolver?
265
+ loaded_value = if type.list?
266
+ loaded_values = coerced_value.map { |val| owner.load_application_object(self, loads, val, context) }
267
+ context.schema.after_any_lazies(loaded_values) { |result| result }
268
+ else
269
+ owner.load_application_object(self, loads, coerced_value, context)
270
+ end
271
+ end
272
+
273
+ coerced_value = if loaded_value
274
+ loaded_value
275
+ else
276
+ coerced_value
277
+ end
278
+
279
+ # If this isn't lazy, then the block returns eagerly and assigns the result here
280
+ # If it _is_ lazy, then we write the lazy to the hash, then update it later
281
+ argument_values[arg_key] = context.schema.after_lazy(coerced_value) do |coerced_value|
282
+ owner.validate_directive_argument(self, coerced_value)
283
+ prepared_value = context.schema.error_handler.with_error_handling(context) do
284
+ prepare_value(parent_object, coerced_value, context: context)
285
+ end
286
+
287
+ # TODO code smell to access such a deeply-nested constant in a distant module
288
+ argument_values[arg_key] = GraphQL::Execution::Interpreter::ArgumentValue.new(
289
+ value: prepared_value,
290
+ definition: self,
291
+ default_used: default_used,
292
+ )
293
+ end
294
+ else
295
+ # has_value is false
296
+ owner.validate_directive_argument(self, nil)
297
+ end
298
+ end
299
+
239
300
  private
240
301
 
241
302
  def validate_input_type(input_type)
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # test_via: ../object.rb
3
2
  require "graphql/schema/field/connection_extension"
4
3
  require "graphql/schema/field/scope_extension"
5
4
 
@@ -61,6 +60,10 @@ module GraphQL
61
60
  @introspection
62
61
  end
63
62
 
63
+ def inspect
64
+ "#<#{self.class} #{path}#{arguments.any? ? "(...)" : ""}: #{type.to_type_signature}>"
65
+ end
66
+
64
67
  alias :mutation :resolver
65
68
 
66
69
  # @return [Boolean] Apply tracing to this field? (Default: skip scalars, this is the override value)
@@ -83,10 +86,10 @@ module GraphQL
83
86
  def self.from_options(name = nil, type = nil, desc = nil, resolver: nil, mutation: nil, subscription: nil,**kwargs, &block)
84
87
  if kwargs[:field]
85
88
  if kwargs[:field].is_a?(GraphQL::Field) && kwargs[:field] == GraphQL::Types::Relay::NodeField.graphql_definition
86
- warn("Legacy-style `GraphQL::Relay::Node.field` is being added to a class-based type. See `GraphQL::Types::Relay::NodeField` for a replacement.")
89
+ GraphQL::Deprecation.warn("Legacy-style `GraphQL::Relay::Node.field` is being added to a class-based type. See `GraphQL::Types::Relay::NodeField` for a replacement.")
87
90
  return GraphQL::Types::Relay::NodeField
88
91
  elsif kwargs[:field].is_a?(GraphQL::Field) && kwargs[:field] == GraphQL::Types::Relay::NodesField.graphql_definition
89
- warn("Legacy-style `GraphQL::Relay::Node.plural_field` is being added to a class-based type. See `GraphQL::Types::Relay::NodesField` for a replacement.")
92
+ GraphQL::Deprecation.warn("Legacy-style `GraphQL::Relay::Node.plural_field` is being added to a class-based type. See `GraphQL::Types::Relay::NodesField` for a replacement.")
90
93
  return GraphQL::Types::Relay::NodesField
91
94
  end
92
95
  end
@@ -285,22 +288,24 @@ module GraphQL
285
288
  @owner = owner
286
289
  @subscription_scope = subscription_scope
287
290
 
288
- # Do this last so we have as much context as possible when initializing them:
289
291
  @extensions = EMPTY_ARRAY
290
- if extensions.any?
291
- self.extensions(extensions)
292
- end
293
292
  # This should run before connection extension,
294
293
  # but should it run after the definition block?
295
294
  if scoped?
296
295
  self.extension(ScopeExtension)
297
296
  end
297
+
298
298
  # The problem with putting this after the definition_block
299
299
  # is that it would override arguments
300
300
  if connection? && connection_extension
301
301
  self.extension(connection_extension)
302
302
  end
303
303
 
304
+ # Do this last so we have as much context as possible when initializing them:
305
+ if extensions.any?
306
+ self.extensions(extensions)
307
+ end
308
+
304
309
  if directives.any?
305
310
  directives.each do |(dir_class, options)|
306
311
  self.directive(dir_class, **options)
@@ -42,6 +42,7 @@ module GraphQL
42
42
  value.after_value ||= original_arguments[:after]
43
43
  value.last_value ||= original_arguments[:last]
44
44
  value.before_value ||= original_arguments[:before]
45
+ value.arguments ||= original_arguments
45
46
  value.field ||= field
46
47
  if field.has_max_page_size? && !value.has_max_page_size_override?
47
48
  value.max_page_size = field.max_page_size
@@ -20,7 +20,9 @@ module GraphQL
20
20
  if self.is_a?(Class)
21
21
  superclass.respond_to?(method_name, true) ? superclass.send(method_name) : default_value
22
22
  else
23
- ancestors[1..-1].each do |ancestor|
23
+ ancestors_except_self = ancestors
24
+ ancestors_except_self.delete(self)
25
+ ancestors_except_self.each do |ancestor|
24
26
  if ancestor.respond_to?(method_name, true)
25
27
  return ancestor.send(method_name)
26
28
  end
@@ -214,8 +214,12 @@ module GraphQL
214
214
  arguments = coerce_arguments(nil, value, ctx)
215
215
 
216
216
  ctx.schema.after_lazy(arguments) do |resolved_arguments|
217
- input_obj_instance = self.new(resolved_arguments, ruby_kwargs: resolved_arguments.keyword_arguments, context: ctx, defaults_used: nil)
218
- input_obj_instance.prepare
217
+ if resolved_arguments.is_a?(GraphQL::Error)
218
+ raise resolved_arguments
219
+ else
220
+ input_obj_instance = self.new(resolved_arguments, ruby_kwargs: resolved_arguments.keyword_arguments, context: ctx, defaults_used: nil)
221
+ input_obj_instance.prepare
222
+ end
219
223
  end
220
224
  end
221
225
 
@@ -81,79 +81,66 @@ module GraphQL
81
81
  end
82
82
 
83
83
  # @api private
84
+ # If given a block, it will eventually yield the loaded args to the block.
85
+ #
86
+ # If no block is given, it will immediately dataload (but might return a Lazy).
87
+ #
84
88
  # @param values [Hash<String, Object>]
85
89
  # @param context [GraphQL::Query::Context]
86
- # @return [Hash<Symbol, Object>, Execution::Lazy<Hash>]
87
- def coerce_arguments(parent_object, values, context)
90
+ # @yield [Interpreter::Arguments, Execution::Lazy<Interpeter::Arguments>]
91
+ # @return [Interpreter::Arguments, Execution::Lazy<Interpeter::Arguments>]
92
+ def coerce_arguments(parent_object, values, context, &block)
88
93
  # Cache this hash to avoid re-merging it
89
94
  arg_defns = self.arguments
95
+ total_args_count = arg_defns.size
90
96
 
91
- if arg_defns.empty?
92
- GraphQL::Execution::Interpreter::Arguments::EMPTY
97
+ if total_args_count == 0
98
+ final_args = GraphQL::Execution::Interpreter::Arguments::EMPTY
99
+ if block_given?
100
+ block.call(final_args)
101
+ nil
102
+ else
103
+ final_args
104
+ end
93
105
  else
106
+ finished_args = nil
94
107
  argument_values = {}
95
- arg_lazies = arg_defns.map do |arg_name, arg_defn|
96
- arg_key = arg_defn.keyword
97
- has_value = false
98
- default_used = false
99
- if values.key?(arg_name)
100
- has_value = true
101
- value = values[arg_name]
102
- elsif values.key?(arg_key)
103
- has_value = true
104
- value = values[arg_key]
105
- elsif arg_defn.default_value?
106
- has_value = true
107
- value = arg_defn.default_value
108
- default_used = true
109
- end
110
-
111
- if has_value
112
- loads = arg_defn.loads
113
- loaded_value = nil
114
- coerced_value = context.schema.error_handler.with_error_handling(context) do
115
- arg_defn.type.coerce_input(value, context)
116
- end
117
-
118
- # TODO this should probably be inside after_lazy
119
- if loads && !arg_defn.from_resolver?
120
- loaded_value = if arg_defn.type.list?
121
- loaded_values = coerced_value.map { |val| load_application_object(arg_defn, loads, val, context) }
122
- context.schema.after_any_lazies(loaded_values) { |result| result }
108
+ resolved_args_count = 0
109
+ raised_error = false
110
+ arg_defns.each do |arg_name, arg_defn|
111
+ context.dataloader.append_job do
112
+ begin
113
+ arg_defn.coerce_into_values(parent_object, values, context, argument_values)
114
+ rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => err
115
+ raised_error = true
116
+ if block_given?
117
+ block.call(err)
123
118
  else
124
- load_application_object(arg_defn, loads, coerced_value, context)
119
+ finished_args = err
125
120
  end
126
121
  end
127
122
 
128
- coerced_value = if loaded_value
129
- loaded_value
130
- else
131
- coerced_value
132
- end
123
+ resolved_args_count += 1
124
+ if resolved_args_count == total_args_count && !raised_error
125
+ finished_args = context.schema.after_any_lazies(argument_values.values) {
126
+ GraphQL::Execution::Interpreter::Arguments.new(
127
+ argument_values: argument_values,
128
+ )
129
+ }
133
130
 
134
- context.schema.after_lazy(coerced_value) do |coerced_value|
135
- validate_directive_argument(arg_defn, coerced_value)
136
- prepared_value = context.schema.error_handler.with_error_handling(context) do
137
- arg_defn.prepare_value(parent_object, coerced_value, context: context)
131
+ if block_given?
132
+ block.call(finished_args)
138
133
  end
139
-
140
- # TODO code smell to access such a deeply-nested constant in a distant module
141
- argument_values[arg_key] = GraphQL::Execution::Interpreter::ArgumentValue.new(
142
- value: prepared_value,
143
- definition: arg_defn,
144
- default_used: default_used,
145
- )
146
134
  end
147
- else
148
- # has_value is false
149
- validate_directive_argument(arg_defn, nil)
150
135
  end
151
136
  end
152
137
 
153
- context.schema.after_any_lazies(arg_lazies) do
154
- GraphQL::Execution::Interpreter::Arguments.new(
155
- argument_values: argument_values,
156
- )
138
+ if block_given?
139
+ nil
140
+ else
141
+ # This API returns eagerly, gotta run it now
142
+ context.dataloader.run
143
+ finished_args
157
144
  end
158
145
  end
159
146
  end