graphql 2.0.0 → 2.0.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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
  3. data/lib/graphql/dataloader/null_dataloader.rb +3 -1
  4. data/lib/graphql/execution/errors.rb +12 -74
  5. data/lib/graphql/execution/interpreter/runtime.rb +35 -38
  6. data/lib/graphql/query/context.rb +96 -9
  7. data/lib/graphql/query/input_validation_result.rb +10 -1
  8. data/lib/graphql/query/null_context.rb +0 -3
  9. data/lib/graphql/query.rb +2 -5
  10. data/lib/graphql/relay/range_add.rb +9 -16
  11. data/lib/graphql/schema/addition.rb +5 -0
  12. data/lib/graphql/schema/argument.rb +13 -4
  13. data/lib/graphql/schema/enum.rb +3 -5
  14. data/lib/graphql/schema/field.rb +164 -130
  15. data/lib/graphql/schema/input_object.rb +12 -12
  16. data/lib/graphql/schema/list.rb +2 -1
  17. data/lib/graphql/schema/member/has_arguments.rb +36 -6
  18. data/lib/graphql/schema/member/has_directives.rb +1 -1
  19. data/lib/graphql/schema/member/has_interfaces.rb +1 -1
  20. data/lib/graphql/schema/member/relay_shortcuts.rb +28 -2
  21. data/lib/graphql/schema/member/validates_input.rb +2 -2
  22. data/lib/graphql/schema/object.rb +14 -9
  23. data/lib/graphql/schema/relay_classic_mutation.rb +32 -14
  24. data/lib/graphql/schema/resolver/has_payload_type.rb +11 -1
  25. data/lib/graphql/schema/resolver.rb +23 -45
  26. data/lib/graphql/schema/scalar.rb +7 -7
  27. data/lib/graphql/schema/subscription.rb +0 -7
  28. data/lib/graphql/schema/warden.rb +1 -1
  29. data/lib/graphql/schema.rb +35 -6
  30. data/lib/graphql/subscriptions.rb +10 -3
  31. data/lib/graphql/tracing/data_dog_tracing.rb +3 -1
  32. data/lib/graphql/types/relay/connection_behaviors.rb +0 -16
  33. data/lib/graphql/version.rb +1 -1
  34. metadata +6 -7
  35. data/lib/graphql/query/literal_input.rb +0 -131
@@ -8,7 +8,15 @@ module GraphQL
8
8
  if new_edge_type_class
9
9
  @edge_type_class = new_edge_type_class
10
10
  else
11
- @edge_type_class || find_inherited_value(:edge_type_class, Types::Relay::BaseEdge)
11
+ # Don't call `ancestor.edge_type_class`
12
+ # because we don't want a fallback from any ancestors --
13
+ # only apply the fallback if _no_ ancestor has a configured value!
14
+ for ancestor in self.ancestors
15
+ if ancestor.respond_to?(:configured_edge_type_class, true) && (etc = ancestor.configured_edge_type_class)
16
+ return etc
17
+ end
18
+ end
19
+ Types::Relay::BaseEdge
12
20
  end
13
21
  end
14
22
 
@@ -16,7 +24,15 @@ module GraphQL
16
24
  if new_connection_type_class
17
25
  @connection_type_class = new_connection_type_class
18
26
  else
19
- @connection_type_class || find_inherited_value(:connection_type_class, Types::Relay::BaseConnection)
27
+ # Don't call `ancestor.connection_type_class`
28
+ # because we don't want a fallback from any ancestors --
29
+ # only apply the fallback if _no_ ancestor has a configured value!
30
+ for ancestor in self.ancestors
31
+ if ancestor.respond_to?(:configured_connection_type_class, true) && (ctc = ancestor.configured_connection_type_class)
32
+ return ctc
33
+ end
34
+ end
35
+ Types::Relay::BaseConnection
20
36
  end
21
37
  end
22
38
 
@@ -41,6 +57,16 @@ module GraphQL
41
57
  end
42
58
  end
43
59
  end
60
+
61
+ protected
62
+
63
+ def configured_connection_type_class
64
+ @connection_type_class
65
+ end
66
+
67
+ def configured_edge_type_class
68
+ @edge_type_class
69
+ end
44
70
  end
45
71
  end
46
72
  end
@@ -10,9 +10,9 @@ module GraphQL
10
10
 
11
11
  def validate_input(val, ctx)
12
12
  if val.nil?
13
- GraphQL::Query::InputValidationResult.new
13
+ Query::InputValidationResult::VALID
14
14
  else
15
- validate_non_null_input(val, ctx)
15
+ validate_non_null_input(val, ctx) || Query::InputValidationResult::VALID
16
16
  end
17
17
  end
18
18
 
@@ -51,12 +51,12 @@ module GraphQL
51
51
  trace_payload = { context: context, type: self, object: object, path: context[:current_path] }
52
52
 
53
53
  maybe_lazy_auth_val = context.query.trace("authorized", trace_payload) do
54
- context.query.with_error_handling do
55
- begin
56
- authorized?(object, context)
57
- rescue GraphQL::UnauthorizedError => err
58
- context.schema.unauthorized_object(err)
59
- end
54
+ begin
55
+ authorized?(object, context)
56
+ rescue GraphQL::UnauthorizedError => err
57
+ context.schema.unauthorized_object(err)
58
+ rescue StandardError => err
59
+ context.query.handle_or_reraise(err)
60
60
  end
61
61
  end
62
62
 
@@ -98,9 +98,14 @@ module GraphQL
98
98
  class << self
99
99
  # Set up a type-specific invalid null error to use when this object's non-null fields wrongly return `nil`.
100
100
  # It should help with debugging and bug tracker integrations.
101
- def inherited(child_class)
102
- child_class.const_set(:InvalidNullError, GraphQL::InvalidNullError.subclass_for(child_class))
103
- super
101
+ def const_missing(name)
102
+ if name == :InvalidNullError
103
+ custom_err_class = GraphQL::InvalidNullError.subclass_for(self)
104
+ const_set(:InvalidNullError, custom_err_class)
105
+ custom_err_class
106
+ else
107
+ super
108
+ end
104
109
  end
105
110
 
106
111
  def kind
@@ -70,11 +70,32 @@ module GraphQL
70
70
  end
71
71
 
72
72
  class << self
73
+ def dummy
74
+ @dummy ||= begin
75
+ d = Class.new(GraphQL::Schema::Resolver)
76
+ d.argument_class(self.argument_class)
77
+ # TODO make this lazier?
78
+ d.argument(:input, input_type, description: "Parameters for #{self.graphql_name}")
79
+ d
80
+ end
81
+ end
82
+
83
+ def field_arguments(context = GraphQL::Query::NullContext)
84
+ dummy.arguments(context)
85
+ end
86
+
87
+ def get_field_argument(name, context = GraphQL::Query::NullContext)
88
+ dummy.get_argument(name, context)
89
+ end
90
+
91
+ def own_field_arguments
92
+ dummy.own_arguments
93
+ end
73
94
 
74
95
  # Also apply this argument to the input type:
75
- def argument(*args, **kwargs, &block)
96
+ def argument(*args, own_argument: false, **kwargs, &block)
76
97
  it = input_type # make sure any inherited arguments are already added to it
77
- arg = super
98
+ arg = super(*args, **kwargs, &block)
78
99
 
79
100
  # This definition might be overriding something inherited;
80
101
  # if it is, remove the inherited definition so it's not confused at runtime as having multiple definitions
@@ -114,15 +135,6 @@ module GraphQL
114
135
  @input_type ||= generate_input_type
115
136
  end
116
137
 
117
- # Extend {Schema::Mutation.field_options} to add the `input` argument
118
- def field_options
119
- sig = super
120
- # Arguments were added at the root, but they should be nested
121
- sig[:arguments].clear
122
- sig[:arguments][:input] = { type: input_type, required: true, description: "Parameters for #{graphql_name}" }
123
- sig
124
- end
125
-
126
138
  private
127
139
 
128
140
  # Generate the input type for the `input:` argument
@@ -130,11 +142,17 @@ module GraphQL
130
142
  # @return [Class] a subclass of {.input_object_class}
131
143
  def generate_input_type
132
144
  mutation_args = all_argument_definitions
133
- mutation_name = graphql_name
134
145
  mutation_class = self
135
146
  Class.new(input_object_class) do
136
- graphql_name("#{mutation_name}Input")
137
- description("Autogenerated input type of #{mutation_name}")
147
+ class << self
148
+ def default_graphql_name
149
+ "#{self.mutation.graphql_name}Input"
150
+ end
151
+
152
+ def description(new_desc = nil)
153
+ super || "Autogenerated input type of #{self.mutation.graphql_name}"
154
+ end
155
+ end
138
156
  mutation(mutation_class)
139
157
  # these might be inherited:
140
158
  mutation_args.each do |arg|
@@ -20,7 +20,17 @@ module GraphQL
20
20
  @payload_type ||= generate_payload_type
21
21
  end
22
22
 
23
- alias :type :payload_type
23
+ def type(new_type = nil, null: nil)
24
+ if new_type
25
+ payload_type(new_type)
26
+ if !null.nil?
27
+ self.null(null)
28
+ end
29
+ else
30
+ super()
31
+ end
32
+ end
33
+
24
34
  alias :type_expr :payload_type
25
35
 
26
36
  def field_class(new_class = nil)
@@ -15,8 +15,6 @@ module GraphQL
15
15
  #
16
16
  # A resolver's configuration may be overridden with other keywords in the `field(...)` call.
17
17
  #
18
- # See the {.field_options} to see how a Resolver becomes a set of field configuration options.
19
- #
20
18
  # @see {GraphQL::Schema::Mutation} for a concrete subclass of `Resolver`.
21
19
  # @see {GraphQL::Function} `Resolver` is a replacement for `GraphQL::Function`
22
20
  class Resolver
@@ -210,6 +208,18 @@ module GraphQL
210
208
  end
211
209
 
212
210
  class << self
211
+ def field_arguments(context = GraphQL::Query::NullContext)
212
+ arguments(context)
213
+ end
214
+
215
+ def get_field_argument(name, context = GraphQL::Query::NullContext)
216
+ get_argument(name, context)
217
+ end
218
+
219
+ def own_field_arguments
220
+ own_arguments
221
+ end
222
+
213
223
  # Default `:resolve` set below.
214
224
  # @return [Symbol] The method to call on instances of this object to resolve the field
215
225
  def resolve_method(new_method = nil)
@@ -242,6 +252,14 @@ module GraphQL
242
252
  @null.nil? ? (superclass.respond_to?(:null) ? superclass.null : true) : @null
243
253
  end
244
254
 
255
+ def resolver_method(new_method_name = nil)
256
+ if new_method_name
257
+ @resolver_method = new_method_name
258
+ else
259
+ @resolver_method || :resolve_with_support
260
+ end
261
+ end
262
+
245
263
  # Call this method to get the return type of the field,
246
264
  # or use it as a configuration method to assign a return type
247
265
  # instead of generating one.
@@ -257,8 +275,8 @@ module GraphQL
257
275
  @type_expr = new_type
258
276
  @null = null
259
277
  else
260
- if @type_expr
261
- GraphQL::Schema::Member::BuildType.parse_type(@type_expr, null: @null)
278
+ if type_expr
279
+ GraphQL::Schema::Member::BuildType.parse_type(type_expr, null: self.null)
262
280
  elsif superclass.respond_to?(:type)
263
281
  superclass.type
264
282
  else
@@ -307,47 +325,7 @@ module GraphQL
307
325
 
308
326
  # @return [Boolean] `true` if this resolver or a superclass has an assigned `max_page_size`
309
327
  def has_max_page_size?
310
- defined?(@max_page_size) || (superclass.respond_to?(:has_max_page_size?) && superclass.has_max_page_size?)
311
- end
312
-
313
- def field_options
314
-
315
- all_args = {}
316
- all_argument_definitions.each do |arg|
317
- if (prev_entry = all_args[arg.graphql_name])
318
- if prev_entry.is_a?(Array)
319
- prev_entry << arg
320
- else
321
- all_args[arg.graphql_name] = [prev_entry, arg]
322
- end
323
- else
324
- all_args[arg.graphql_name] = arg
325
- end
326
- end
327
-
328
- field_opts = {
329
- type: type_expr,
330
- description: description,
331
- extras: extras,
332
- resolver_method: :resolve_with_support,
333
- resolver_class: self,
334
- arguments: all_args,
335
- null: null,
336
- complexity: complexity,
337
- broadcastable: broadcastable?,
338
- }
339
-
340
- # If there aren't any, then the returned array is `[].freeze`,
341
- # but passing that along breaks some user code.
342
- if (exts = extensions).any?
343
- field_opts[:extensions] = exts
344
- end
345
-
346
- if has_max_page_size?
347
- field_opts[:max_page_size] = max_page_size
348
- end
349
-
350
- field_opts
328
+ (!!defined?(@max_page_size)) || (superclass.respond_to?(:has_max_page_size?) && superclass.has_max_page_size?)
351
329
  end
352
330
 
353
331
  # A non-normalized type configuration, without `null` applied
@@ -41,13 +41,12 @@ module GraphQL
41
41
  end
42
42
 
43
43
  def validate_non_null_input(value, ctx)
44
- result = Query::InputValidationResult.new
45
44
  coerced_result = begin
46
- ctx.query.with_error_handling do
47
- coerce_input(value, ctx)
48
- end
45
+ coerce_input(value, ctx)
49
46
  rescue GraphQL::CoercionError => err
50
47
  err
48
+ rescue StandardError => err
49
+ ctx.query.handle_or_reraise(err)
51
50
  end
52
51
 
53
52
  if coerced_result.nil?
@@ -56,11 +55,12 @@ module GraphQL
56
55
  else
57
56
  " #{GraphQL::Language.serialize(value)}"
58
57
  end
59
- result.add_problem("Could not coerce value#{str_value} to #{graphql_name}")
58
+ Query::InputValidationResult.from_problem("Could not coerce value#{str_value} to #{graphql_name}")
60
59
  elsif coerced_result.is_a?(GraphQL::CoercionError)
61
- result.add_problem(coerced_result.message, message: coerced_result.message, extensions: coerced_result.extensions)
60
+ Query::InputValidationResult.from_problem(coerced_result.message, message: coerced_result.message, extensions: coerced_result.extensions)
61
+ else
62
+ nil
62
63
  end
63
- result
64
64
  end
65
65
  end
66
66
  end
@@ -143,13 +143,6 @@ module GraphQL
143
143
  def self.topic_for(arguments:, field:, scope:)
144
144
  Subscriptions::Serialize.dump_recursive([scope, field.graphql_name, arguments])
145
145
  end
146
-
147
- # Overriding Resolver#field_options to include subscription_scope
148
- def self.field_options
149
- super.merge(
150
- subscription_scope: subscription_scope
151
- )
152
- end
153
146
  end
154
147
  end
155
148
  end
@@ -10,7 +10,7 @@ module GraphQL
10
10
  # should go through a warden. If you access the schema directly,
11
11
  # you may show a client something that it shouldn't be allowed to see.
12
12
  #
13
- # @example Hidding private fields
13
+ # @example Hiding private fields
14
14
  # private_members = -> (member, ctx) { member.metadata[:private] }
15
15
  # result = Schema.execute(query_string, except: private_members)
16
16
  #
@@ -693,7 +693,41 @@ module GraphQL
693
693
 
694
694
  def rescue_from(*err_classes, &handler_block)
695
695
  err_classes.each do |err_class|
696
- error_handler.rescue_from(err_class, handler_block)
696
+ Execution::Errors.register_rescue_from(err_class, error_handlers[:subclass_handlers], handler_block)
697
+ end
698
+ end
699
+
700
+ NEW_HANDLER_HASH = ->(h, k) {
701
+ h[k] = {
702
+ class: k,
703
+ handler: nil,
704
+ subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
705
+ }
706
+ }
707
+
708
+ def error_handlers
709
+ @error_handlers ||= {
710
+ class: nil,
711
+ handler: nil,
712
+ subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
713
+ }
714
+ end
715
+
716
+ # @api private
717
+ def handle_or_reraise(context, err)
718
+ handler = Execution::Errors.find_handler_for(self, err.class)
719
+ if handler
720
+ runtime_info = context.namespace(:interpreter) || {}
721
+ obj = runtime_info[:current_object]
722
+ args = runtime_info[:current_arguments]
723
+ args = args && args.keyword_arguments
724
+ field = runtime_info[:current_field]
725
+ if obj.is_a?(GraphQL::Schema::Object)
726
+ obj = obj.object
727
+ end
728
+ handler[:handler].call(err, obj, args, context, field)
729
+ else
730
+ raise err
697
731
  end
698
732
  end
699
733
 
@@ -821,11 +855,6 @@ module GraphQL
821
855
  ctx.errors.push(parse_err)
822
856
  end
823
857
 
824
- # @return [GraphQL::Execution::Errors]
825
- def error_handler
826
- @error_handler ||= GraphQL::Execution::Errors.new(self)
827
- end
828
-
829
858
  def lazy_resolve(lazy_class, value_method)
830
859
  lazy_methods.set(lazy_class, value_method)
831
860
  end
@@ -56,17 +56,24 @@ module GraphQL
56
56
  # @param args [Hash<String, Symbol => Object]
57
57
  # @param object [Object]
58
58
  # @param scope [Symbol, String]
59
+ # @param context [Hash]
59
60
  # @return [void]
60
- def trigger(event_name, args, object, scope: nil)
61
+ def trigger(event_name, args, object, scope: nil, context: {})
62
+ # Make something as context-like as possible, even though there isn't a current query:
63
+ context = @schema.context_class.new(
64
+ query: GraphQL::Query.new(@schema, "", validate: false),
65
+ object: nil,
66
+ values: context
67
+ )
61
68
  event_name = event_name.to_s
62
69
 
63
70
  # Try with the verbatim input first:
64
- field = @schema.get_field(@schema.subscription, event_name)
71
+ field = @schema.get_field(@schema.subscription, event_name, context)
65
72
 
66
73
  if field.nil?
67
74
  # And if it wasn't found, normalize it:
68
75
  normalized_event_name = normalize_name(event_name)
69
- field = @schema.get_field(@schema.subscription, normalized_event_name)
76
+ field = @schema.get_field(@schema.subscription, normalized_event_name, context)
70
77
  if field.nil?
71
78
  raise InvalidTriggerError, "No subscription matching trigger: #{event_name} (looked for #{@schema.subscription.graphql_name}.#{normalized_event_name})"
72
79
  end
@@ -48,7 +48,9 @@ module GraphQL
48
48
  end
49
49
 
50
50
  def tracer
51
- options.fetch(:tracer, Datadog.tracer)
51
+ default_tracer = defined?(Datadog::Tracing) ? Datadog::Tracing : Datadog.tracer
52
+
53
+ options.fetch(:tracer, default_tracer)
52
54
  end
53
55
 
54
56
  def analytics_available?
@@ -148,22 +148,6 @@ module GraphQL
148
148
  obj_type.field :page_info, GraphQL::Types::Relay::PageInfo, null: false, description: "Information to aid in pagination."
149
149
  end
150
150
  end
151
-
152
- # By default this calls through to the ConnectionWrapper's edge nodes method,
153
- # but sometimes you need to override it to support the `nodes` field
154
- def nodes
155
- @object.edge_nodes
156
- end
157
-
158
- def edges
159
- if @object.is_a?(GraphQL::Pagination::Connection)
160
- @object.edges
161
- else
162
- context.schema.after_lazy(object.edge_nodes) do |nodes|
163
- nodes.map { |n| self.class.edge_class.new(n, object) }
164
- end
165
- end
166
- end
167
151
  end
168
152
  end
169
153
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.0.0"
3
+ VERSION = "2.0.3"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-09 00:00:00.000000000 Z
11
+ date: 2022-03-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ips
@@ -366,7 +366,6 @@ files:
366
366
  - lib/graphql/query/context.rb
367
367
  - lib/graphql/query/fingerprint.rb
368
368
  - lib/graphql/query/input_validation_result.rb
369
- - lib/graphql/query/literal_input.rb
370
369
  - lib/graphql/query/null_context.rb
371
370
  - lib/graphql/query/result.rb
372
371
  - lib/graphql/query/validation_pipeline.rb
@@ -582,7 +581,7 @@ metadata:
582
581
  source_code_uri: https://github.com/rmosolgo/graphql-ruby
583
582
  bug_tracker_uri: https://github.com/rmosolgo/graphql-ruby/issues
584
583
  mailing_list_uri: https://tinyletter.com/graphql-ruby
585
- post_install_message:
584
+ post_install_message:
586
585
  rdoc_options: []
587
586
  require_paths:
588
587
  - lib
@@ -597,8 +596,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
597
596
  - !ruby/object:Gem::Version
598
597
  version: '0'
599
598
  requirements: []
600
- rubygems_version: 3.1.6
601
- signing_key:
599
+ rubygems_version: 3.3.3
600
+ signing_key:
602
601
  specification_version: 4
603
602
  summary: A GraphQL language and runtime for Ruby
604
603
  test_files: []
@@ -1,131 +0,0 @@
1
- # frozen_string_literal: true
2
- module GraphQL
3
- class Query
4
- # Turn query string values into something useful for query execution
5
- class LiteralInput
6
- def self.coerce(type, ast_node, variables)
7
- case ast_node
8
- when nil
9
- nil
10
- when Language::Nodes::NullValue
11
- nil
12
- when Language::Nodes::VariableIdentifier
13
- variables[ast_node.name]
14
- else
15
- case type.kind.name
16
- when "SCALAR"
17
- # TODO smell
18
- # This gets used for plain values during subscriber.trigger
19
- if variables
20
- type.coerce_input(ast_node, variables.context)
21
- else
22
- type.coerce_isolated_input(ast_node)
23
- end
24
- when "ENUM"
25
- # TODO smell
26
- # This gets used for plain values sometimes
27
- v = ast_node.is_a?(GraphQL::Language::Nodes::Enum) ? ast_node.name : ast_node
28
- if variables
29
- type.coerce_input(v, variables.context)
30
- else
31
- type.coerce_isolated_input(v)
32
- end
33
- when "NON_NULL"
34
- LiteralInput.coerce(type.of_type, ast_node, variables)
35
- when "LIST"
36
- if ast_node.is_a?(Array)
37
- ast_node.map { |element_ast| LiteralInput.coerce(type.of_type, element_ast, variables) }
38
- else
39
- [LiteralInput.coerce(type.of_type, ast_node, variables)]
40
- end
41
- when "INPUT_OBJECT"
42
- # TODO smell: handling AST vs handling plain Ruby
43
- next_args = ast_node.is_a?(Hash) ? ast_node : ast_node.arguments
44
- from_arguments(next_args, type, variables)
45
- else
46
- raise "Invariant: unexpected type to coerce to: #{type}"
47
- end
48
- end
49
- end
50
-
51
- def self.from_arguments(ast_arguments, argument_owner, variables)
52
- context = variables ? variables.context : nil
53
- values_hash = {}
54
- defaults_used = Set.new
55
-
56
- indexed_arguments = case ast_arguments
57
- when Hash
58
- ast_arguments
59
- when Array
60
- ast_arguments.each_with_object({}) { |a, memo| memo[a.name] = a }
61
- else
62
- raise ArgumentError, "Unexpected ast_arguments: #{ast_arguments}"
63
- end
64
-
65
- argument_defns = argument_owner.arguments(context || GraphQL::Query::NullContext)
66
- argument_defns.each do |arg_name, arg_defn|
67
- ast_arg = indexed_arguments[arg_name]
68
- # First, check the argument in the AST.
69
- # If the value is a variable,
70
- # only add a value if the variable is actually present.
71
- # Otherwise, coerce the value in the AST, prepare the value and add it.
72
- #
73
- # TODO: since indexed_arguments can come from a plain Ruby hash,
74
- # have to check for `false` or `nil` as hash values. This is getting smelly :S
75
- if indexed_arguments.key?(arg_name)
76
- arg_value = ast_arg.is_a?(GraphQL::Language::Nodes::Argument) ? ast_arg.value : ast_arg
77
-
78
- value_is_a_variable = arg_value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
79
-
80
- if (!value_is_a_variable || (value_is_a_variable && variables.key?(arg_value.name)))
81
-
82
- value = coerce(arg_defn.type, arg_value, variables)
83
- # Legacy `prepare` application
84
- if arg_defn.is_a?(GraphQL::Argument)
85
- value = arg_defn.prepare(value, context)
86
- end
87
-
88
- if value.is_a?(GraphQL::ExecutionError)
89
- value.ast_node = ast_arg
90
- raise value
91
- end
92
-
93
- values_hash[arg_name] = value
94
- end
95
- end
96
-
97
- # Then, the definition for a default value.
98
- # If the definition has a default value and
99
- # a value wasn't provided from the AST,
100
- # then add the default value.
101
- if arg_defn.default_value? && !values_hash.key?(arg_name)
102
- value = arg_defn.default_value
103
- defaults_used << arg_name
104
- # `context` isn't present when pre-calculating defaults
105
- if context
106
- if arg_defn.is_a?(GraphQL::Argument)
107
- value = arg_defn.prepare(value, context)
108
- end
109
- if value.is_a?(GraphQL::ExecutionError)
110
- value.ast_node = ast_arg
111
- raise value
112
- end
113
- end
114
- values_hash[arg_name] = value
115
- end
116
- end
117
-
118
- # A Schema::InputObject, Schema::GraphQL::Field, Schema::Directive, logic from Interpreter::Arguments
119
- ruby_kwargs = {}
120
- values_hash.each do |key, value|
121
- ruby_kwargs[Schema::Member::BuildType.underscore(key).to_sym] = value
122
- end
123
- if argument_owner.is_a?(Class) && argument_owner < GraphQL::Schema::InputObject
124
- argument_owner.new(ruby_kwargs: ruby_kwargs, context: context, defaults_used: defaults_used)
125
- else
126
- ruby_kwargs
127
- end
128
- end
129
- end
130
- end
131
- end