graphql 1.12.17 → 1.12.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/object_generator.rb +2 -1
  3. data/lib/generators/graphql/relay.rb +19 -11
  4. data/lib/generators/graphql/templates/schema.erb +14 -2
  5. data/lib/graphql/analysis/ast/field_usage.rb +1 -1
  6. data/lib/graphql/dataloader/source.rb +32 -2
  7. data/lib/graphql/dataloader.rb +13 -0
  8. data/lib/graphql/deprecated_dsl.rb +11 -3
  9. data/lib/graphql/deprecation.rb +1 -5
  10. data/lib/graphql/integer_encoding_error.rb +18 -2
  11. data/lib/graphql/pagination/connections.rb +35 -16
  12. data/lib/graphql/query/validation_pipeline.rb +1 -1
  13. data/lib/graphql/schema/argument.rb +55 -26
  14. data/lib/graphql/schema/field.rb +14 -4
  15. data/lib/graphql/schema/input_object.rb +1 -5
  16. data/lib/graphql/schema/member/has_arguments.rb +90 -44
  17. data/lib/graphql/schema/resolver.rb +20 -57
  18. data/lib/graphql/schema/subscription.rb +4 -4
  19. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  20. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  21. data/lib/graphql/schema/validator/exclusion_validator.rb +3 -1
  22. data/lib/graphql/schema/validator/format_validator.rb +4 -1
  23. data/lib/graphql/schema/validator/inclusion_validator.rb +3 -1
  24. data/lib/graphql/schema/validator/length_validator.rb +5 -3
  25. data/lib/graphql/schema/validator/numericality_validator.rb +7 -1
  26. data/lib/graphql/schema/validator.rb +36 -25
  27. data/lib/graphql/schema.rb +18 -5
  28. data/lib/graphql/static_validation/base_visitor.rb +3 -0
  29. data/lib/graphql/static_validation/error.rb +3 -1
  30. data/lib/graphql/static_validation/rules/fields_will_merge.rb +40 -21
  31. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  32. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  33. data/lib/graphql/static_validation/validation_context.rb +8 -2
  34. data/lib/graphql/static_validation/validator.rb +15 -12
  35. data/lib/graphql/string_encoding_error.rb +13 -3
  36. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -1
  37. data/lib/graphql/subscriptions/event.rb +47 -2
  38. data/lib/graphql/subscriptions/serialize.rb +1 -1
  39. data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
  40. data/lib/graphql/types/int.rb +1 -1
  41. data/lib/graphql/types/string.rb +1 -1
  42. data/lib/graphql/unauthorized_error.rb +1 -1
  43. data/lib/graphql/version.rb +1 -1
  44. metadata +5 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c9089e4578454f473996553a4771e4086e51b2b2db17fc31a579ab28019bd39
4
- data.tar.gz: f45a70c81394f35c86d1610491f106e39899bc2c927a6a6d13e9e6533bc3bc85
3
+ metadata.gz: 6fa9800286687f6236697bf1f3eed4f3342b40fbbbebc64c472a7d791442bce4
4
+ data.tar.gz: a74ed6cf70cf2f626c2339a8377ada5dea5491eb3e53a1e1783b4a7a8dd8bebc
5
5
  SHA512:
6
- metadata.gz: b7231b5e00a336439d15d469a383cd7e211e305961d4a4b431e8a97f5e483819bbd87de3d7cfffc9b6677b8175f700e012cd9ee4a0c92fa47005455a14893d3c
7
- data.tar.gz: 98495c2b24d65ef90d7f5e1036956349ea79d03ea192de6ed06e517657f49b4e0e9c748c8a28d54aac24e96b42f52eea5d4cbfbca801a4389b1515804296831a
6
+ metadata.gz: 41c6592dbd0cd27e82f036f271c71098a14c2b10d7cc700fc680caa1133b0a148a730b9e15d5a4d04c98f72bfd4a418d8ae63b09f327193f80af2220fc399fc0
7
+ data.tar.gz: cb35e9d298bc92431ae561e8c663c00fcf899c1cc1c1daca9730717ba6636f9eb177af40b1314e55f73a411d2a78eeaadc2d2c6b34b583cd3fbe7525d18a8139
@@ -12,7 +12,8 @@ module Graphql
12
12
  #
13
13
  # Add the Node interface with `--node`.
14
14
  class ObjectGenerator < TypeGeneratorBase
15
- desc "Create a GraphQL::ObjectType with the given name and fields"
15
+ desc "Create a GraphQL::ObjectType with the given name and fields." \
16
+ "If the given type name matches an existing ActiveRecord model, the generated type will automatically include fields for the models database columns."
16
17
  source_root File.expand_path('../templates', __FILE__)
17
18
 
18
19
  argument :custom_fields,
@@ -32,20 +32,28 @@ module Graphql
32
32
 
33
33
  # Return a string UUID for `object`
34
34
  def self.id_from_object(object, type_definition, query_ctx)
35
- # Here's a simple implementation which:
36
- # - joins the type name & object.id
37
- # - encodes it with base64:
38
- # GraphQL::Schema::UniqueWithinType.encode(type_definition.name, object.id)
35
+ # For example, use Rails' GlobalID library (https://github.com/rails/globalid):
36
+ object_id = object.to_global_id.to_s
37
+ # Remove this redundant prefix to make IDs shorter:
38
+ object_id = object_id.sub("gid://\#{GlobalID.app}/", "")
39
+ encoded_id = Base64.urlsafe_encode64(object_id)
40
+ # Remove the "=" padding
41
+ encoded_id = encoded_id.sub(/=+/, "")
42
+ # Add a type hint
43
+ type_hint = type_definition.graphql_name.first
44
+ "\#{type_hint}_\#{encoded_id}"
39
45
  end
40
46
 
41
47
  # Given a string UUID, find the object
42
- def self.object_from_id(id, query_ctx)
43
- # For example, to decode the UUIDs generated above:
44
- # type_name, item_id = GraphQL::Schema::UniqueWithinType.decode(id)
45
- #
46
- # Then, based on `type_name` and `id`
47
- # find an object in your application
48
- # ...
48
+ def self.object_from_id(encoded_id_with_hint, query_ctx)
49
+ # For example, use Rails' GlobalID library (https://github.com/rails/globalid):
50
+ # Split off the type hint
51
+ _type_hint, encoded_id = encoded_id_with_hint.split("_", 2)
52
+ # Decode the ID
53
+ id = Base64.urlsafe_decode64(encoded_id)
54
+ # Rebuild it for Rails then find the object:
55
+ full_global_id = "gid://\#{GlobalID.app}/\#{id}"
56
+ GlobalID::Locator.locate(full_global_id)
49
57
  end
50
58
  RUBY
51
59
  inject_into_file schema_file_path, schema_code, before: /^end\n/m, force: false
@@ -4,11 +4,23 @@ class <%= schema_name %> < GraphQL::Schema
4
4
  <% if options[:batch] %>
5
5
  # GraphQL::Batch setup:
6
6
  use GraphQL::Batch
7
+ <% else %>
8
+ # For batch-loading (see https://graphql-ruby.org/dataloader/overview.html)
9
+ use GraphQL::Dataloader
7
10
  <% end %>
11
+ # GraphQL-Ruby calls this when something goes wrong while running a query:
12
+ def self.type_error(err, context)
13
+ # if err.is_a?(GraphQL::InvalidNullError)
14
+ # # report to your bug tracker here
15
+ # return nil
16
+ # end
17
+ super
18
+ end
19
+
8
20
  # Union and Interface Resolution
9
21
  def self.resolve_type(abstract_type, obj, ctx)
10
- # TODO: Implement this function
11
- # to return the correct object type for `obj`
22
+ # TODO: Implement this method
23
+ # to return the correct GraphQL object type for `obj`
12
24
  raise(GraphQL::RequiredImplementationMissingError)
13
25
  end
14
26
  end
@@ -37,7 +37,7 @@ module GraphQL
37
37
 
38
38
  if argument.definition.type.kind.input_object?
39
39
  extract_deprecated_arguments(argument.value.arguments.argument_values)
40
- elsif argument.definition.type.list?
40
+ elsif argument.definition.type.list? && !argument.value.nil?
41
41
  argument
42
42
  .value
43
43
  .select { |value| value.respond_to?(:arguments) }
@@ -6,7 +6,11 @@ module GraphQL
6
6
  # Called by {Dataloader} to prepare the {Source}'s internal state
7
7
  # @api private
8
8
  def setup(dataloader)
9
+ # These keys have been requested but haven't been fetched yet
9
10
  @pending_keys = []
11
+ # These keys have been passed to `fetch` but haven't been finished yet
12
+ @fetching_keys = []
13
+ # { key => result }
10
14
  @results = {}
11
15
  @dataloader = dataloader
12
16
  end
@@ -64,29 +68,46 @@ module GraphQL
64
68
  # Then run the batch and update the cache.
65
69
  # @return [void]
66
70
  def sync
71
+ pending_keys = @pending_keys.dup
67
72
  @dataloader.yield
73
+ iterations = 0
74
+ while pending_keys.any? { |k| !@results.key?(k) }
75
+ iterations += 1
76
+ if iterations > 1000
77
+ raise "#{self.class}#sync tried 1000 times to load pending keys (#{pending_keys}), but they still weren't loaded. There is likely a circular dependency."
78
+ end
79
+ @dataloader.yield
80
+ end
81
+ nil
68
82
  end
69
83
 
70
84
  # @return [Boolean] True if this source has any pending requests for data.
71
85
  def pending?
72
- @pending_keys.any?
86
+ !@pending_keys.empty?
73
87
  end
74
88
 
75
89
  # Called by {GraphQL::Dataloader} to resolve and pending requests to this source.
76
90
  # @api private
77
91
  # @return [void]
78
92
  def run_pending_keys
93
+ if !@fetching_keys.empty?
94
+ @pending_keys -= @fetching_keys
95
+ end
79
96
  return if @pending_keys.empty?
80
97
  fetch_keys = @pending_keys.uniq
98
+ @fetching_keys.concat(fetch_keys)
81
99
  @pending_keys = []
82
100
  results = fetch(fetch_keys)
83
101
  fetch_keys.each_with_index do |key, idx|
84
102
  @results[key] = results[idx]
85
103
  end
104
+ nil
86
105
  rescue StandardError => error
87
106
  fetch_keys.each { |key| @results[key] = error }
88
107
  ensure
89
- nil
108
+ if fetch_keys
109
+ @fetching_keys -= fetch_keys
110
+ end
90
111
  end
91
112
 
92
113
  # These arguments are given to `dataloader.with(source_class, ...)`. The object
@@ -107,6 +128,8 @@ module GraphQL
107
128
  [*batch_args, **batch_kwargs]
108
129
  end
109
130
 
131
+ attr_reader :pending_keys
132
+
110
133
  private
111
134
 
112
135
  # Reads and returns the result for the key from the internal cache, or raises an error if the result was an error
@@ -114,6 +137,13 @@ module GraphQL
114
137
  # @return [Object] The result from {#fetch} for `key`.
115
138
  # @api private
116
139
  def result_for(key)
140
+ if !@results.key?(key)
141
+ raise <<-ERR
142
+ Invariant: fetching result for a key on #{self.class} that hasn't been loaded yet (#{key.inspect}, loaded: #{@results.keys})
143
+
144
+ This key should have been loaded already. This is a bug in GraphQL::Dataloader, please report it on GitHub: https://github.com/rmosolgo/graphql-ruby/issues/new.
145
+ ERR
146
+ end
117
147
  result = @results[key]
118
148
 
119
149
  raise result if result.class <= StandardError
@@ -90,6 +90,16 @@ module GraphQL
90
90
  # Use a self-contained queue for the work in the block.
91
91
  def run_isolated
92
92
  prev_queue = @pending_jobs
93
+ prev_pending_keys = {}
94
+ @source_cache.each do |source_class, batched_sources|
95
+ batched_sources.each do |batch_args, batched_source_instance|
96
+ if batched_source_instance.pending?
97
+ prev_pending_keys[batched_source_instance] = batched_source_instance.pending_keys.dup
98
+ batched_source_instance.pending_keys.clear
99
+ end
100
+ end
101
+ end
102
+
93
103
  @pending_jobs = []
94
104
  res = nil
95
105
  # Make sure the block is inside a Fiber, so it can `Fiber.yield`
@@ -100,6 +110,9 @@ module GraphQL
100
110
  res
101
111
  ensure
102
112
  @pending_jobs = prev_queue
113
+ prev_pending_keys.each do |source_instance, pending_keys|
114
+ source_instance.pending_keys.concat(pending_keys)
115
+ end
103
116
  end
104
117
 
105
118
  # @api private Move along, move along
@@ -38,9 +38,17 @@ module GraphQL
38
38
  end
39
39
  end
40
40
 
41
- TYPE_CLASSES.each do |type_class|
42
- refine type_class.singleton_class do
43
- include Methods
41
+ if defined?(::Refinement) && Refinement.private_method_defined?(:import_methods)
42
+ TYPE_CLASSES.each do |type_class|
43
+ refine type_class.singleton_class do
44
+ import_methods Methods
45
+ end
46
+ end
47
+ else
48
+ TYPE_CLASSES.each do |type_class|
49
+ refine type_class.singleton_class do
50
+ include Methods
51
+ end
44
52
  end
45
53
  end
46
54
  end
@@ -3,11 +3,7 @@
3
3
  module GraphQL
4
4
  module Deprecation
5
5
  def self.warn(message)
6
- if defined?(ActiveSupport::Deprecation)
7
- ActiveSupport::Deprecation.warn(message)
8
- else
9
- Kernel.warn(message)
10
- end
6
+ Kernel.warn(message)
11
7
  end
12
8
  end
13
9
  end
@@ -12,9 +12,25 @@ module GraphQL
12
12
  # The value which couldn't be encoded
13
13
  attr_reader :integer_value
14
14
 
15
- def initialize(value)
15
+ # @return [GraphQL::Schema::Field] The field that returned a too-big integer
16
+ attr_reader :field
17
+
18
+ # @return [Array<String, Integer>] Where the field appeared in the GraphQL response
19
+ attr_reader :path
20
+
21
+ def initialize(value, context:)
16
22
  @integer_value = value
17
- super("Integer out of bounds: #{value}. \nConsider using ID or GraphQL::Types::BigInt instead.")
23
+ @field = context[:current_field]
24
+ @path = context[:current_path]
25
+ message = "Integer out of bounds: #{value}".dup
26
+ if @path
27
+ message << " @ #{@path.join(".")}"
28
+ end
29
+ if @field
30
+ message << " (#{@field.path})"
31
+ end
32
+ message << ". Consider using ID or GraphQL::Types::BigInt instead."
33
+ super(message)
18
34
  end
19
35
  end
20
36
  end
@@ -70,23 +70,42 @@ module GraphQL
70
70
  wrappers = context ? context.namespace(:connections)[:all_wrappers] : all_wrappers
71
71
  impl = wrapper_for(items, wrappers: wrappers)
72
72
 
73
- if impl.nil?
74
- raise ImplementationMissingError, "Couldn't find a connection wrapper for #{items.class} during #{field.path} (#{items.inspect})"
73
+ if impl
74
+ impl.new(
75
+ items,
76
+ context: context,
77
+ parent: parent,
78
+ field: field,
79
+ max_page_size: field.has_max_page_size? ? field.max_page_size : context.schema.default_max_page_size,
80
+ first: arguments[:first],
81
+ after: arguments[:after],
82
+ last: arguments[:last],
83
+ before: arguments[:before],
84
+ arguments: arguments,
85
+ edge_class: edge_class_for_field(field),
86
+ )
87
+ else
88
+ begin
89
+ connection_class = GraphQL::Relay::BaseConnection.connection_for_nodes(items)
90
+ if parent.is_a?(GraphQL::Schema::Object)
91
+ parent = parent.object
92
+ end
93
+ connection_class.new(
94
+ items,
95
+ arguments,
96
+ field: field,
97
+ max_page_size: field.max_page_size,
98
+ parent: parent,
99
+ context: context,
100
+ )
101
+ rescue RuntimeError => err
102
+ if err.message.include?("No connection implementation to wrap")
103
+ raise ImplementationMissingError, "Couldn't find a connection wrapper for #{items.class} during #{field.path} (#{items.inspect})"
104
+ else
105
+ raise err
106
+ end
107
+ end
75
108
  end
76
-
77
- impl.new(
78
- items,
79
- context: context,
80
- parent: parent,
81
- field: field,
82
- max_page_size: field.has_max_page_size? ? field.max_page_size : context.schema.default_max_page_size,
83
- first: arguments[:first],
84
- after: arguments[:after],
85
- last: arguments[:last],
86
- before: arguments[:before],
87
- arguments: arguments,
88
- edge_class: edge_class_for_field(field),
89
- )
90
109
  end
91
110
 
92
111
  # use an override if there is one
@@ -72,7 +72,7 @@ module GraphQL
72
72
  elsif @operation_name_error
73
73
  @validation_errors << @operation_name_error
74
74
  else
75
- validation_result = @schema.static_validator.validate(@query, validate: @validate, timeout: @schema.validate_timeout)
75
+ validation_result = @schema.static_validator.validate(@query, validate: @validate, timeout: @schema.validate_timeout, max_errors: @schema.validate_max_errors)
76
76
  @validation_errors.concat(validation_result[:errors])
77
77
  @internal_representation = validation_result[:irep]
78
78
 
@@ -260,38 +260,67 @@ module GraphQL
260
260
  type.coerce_input(value, context)
261
261
  end
262
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
- context.query.with_error_handling do
270
- owner.load_application_object(self, loads, coerced_value, context)
263
+ # If this isn't lazy, then the block returns eagerly and assigns the result here
264
+ # If it _is_ lazy, then we write the lazy to the hash, then update it later
265
+ argument_values[arg_key] = context.schema.after_lazy(coerced_value) do |resolved_coerced_value|
266
+ if loads && !from_resolver?
267
+ loaded_value = context.query.with_error_handling do
268
+ load_and_authorize_value(owner, coerced_value, context)
271
269
  end
272
270
  end
273
- end
274
271
 
275
- coerced_value = if loaded_value
276
- loaded_value
277
- else
278
- coerced_value
279
- end
272
+ maybe_loaded_value = loaded_value || resolved_coerced_value
273
+ context.schema.after_lazy(maybe_loaded_value) do |resolved_loaded_value|
274
+ owner.validate_directive_argument(self, resolved_loaded_value)
275
+ prepared_value = context.schema.error_handler.with_error_handling(context) do
276
+ prepare_value(parent_object, resolved_loaded_value, context: context)
277
+ end
280
278
 
281
- # If this isn't lazy, then the block returns eagerly and assigns the result here
282
- # If it _is_ lazy, then we write the lazy to the hash, then update it later
283
- argument_values[arg_key] = context.schema.after_lazy(coerced_value) do |coerced_value|
284
- owner.validate_directive_argument(self, coerced_value)
285
- prepared_value = context.schema.error_handler.with_error_handling(context) do
286
- prepare_value(parent_object, coerced_value, context: context)
279
+ # TODO code smell to access such a deeply-nested constant in a distant module
280
+ argument_values[arg_key] = GraphQL::Execution::Interpreter::ArgumentValue.new(
281
+ value: prepared_value,
282
+ definition: self,
283
+ default_used: default_used,
284
+ )
287
285
  end
286
+ end
287
+ end
288
288
 
289
- # TODO code smell to access such a deeply-nested constant in a distant module
290
- argument_values[arg_key] = GraphQL::Execution::Interpreter::ArgumentValue.new(
291
- value: prepared_value,
292
- definition: self,
293
- default_used: default_used,
294
- )
289
+ def load_and_authorize_value(load_method_owner, coerced_value, context)
290
+ if coerced_value.nil?
291
+ return nil
292
+ end
293
+ arg_load_method = "load_#{keyword}"
294
+ if load_method_owner.respond_to?(arg_load_method)
295
+ custom_loaded_value = if load_method_owner.is_a?(Class)
296
+ load_method_owner.public_send(arg_load_method, coerced_value, context)
297
+ else
298
+ load_method_owner.public_send(arg_load_method, coerced_value)
299
+ end
300
+ context.schema.after_lazy(custom_loaded_value) do |custom_value|
301
+ if loads
302
+ if type.list?
303
+ loaded_values = custom_value.each_with_index.map { |custom_val, idx|
304
+ id = coerced_value[idx]
305
+ load_method_owner.authorize_application_object(self, id, context, custom_val)
306
+ }
307
+ context.schema.after_any_lazies(loaded_values, &:itself)
308
+ else
309
+ load_method_owner.authorize_application_object(self, coerced_value, context, custom_loaded_value)
310
+ end
311
+ else
312
+ custom_value
313
+ end
314
+ end
315
+ elsif loads
316
+ if type.list?
317
+ loaded_values = coerced_value.map { |val| load_method_owner.load_and_authorize_application_object(self, val, context) }
318
+ context.schema.after_any_lazies(loaded_values, &:itself)
319
+ else
320
+ load_method_owner.load_and_authorize_application_object(self, coerced_value, context)
321
+ end
322
+ else
323
+ coerced_value
295
324
  end
296
325
  end
297
326
 
@@ -122,6 +122,9 @@ module GraphQL
122
122
  else
123
123
  kwargs[:type] = type
124
124
  end
125
+ if type.is_a?(Class) && type < GraphQL::Schema::Mutation
126
+ raise ArgumentError, "Use `field #{name.inspect}, mutation: Mutation, ...` to provide a mutation to this field instead"
127
+ end
125
128
  end
126
129
  new(**kwargs, &block)
127
130
  end
@@ -510,6 +513,7 @@ module GraphQL
510
513
  field_defn
511
514
  end
512
515
 
516
+ class MissingReturnTypeError < GraphQL::Error; end
513
517
  attr_writer :type
514
518
 
515
519
  def type
@@ -517,14 +521,21 @@ module GraphQL
517
521
  Member::BuildType.parse_type(@function.type, null: false)
518
522
  elsif @field
519
523
  Member::BuildType.parse_type(@field.type, null: false)
524
+ elsif @return_type_expr.nil?
525
+ # Not enough info to determine type
526
+ message = "Can't determine the return type for #{self.path}"
527
+ if @resolver_class
528
+ message += " (it has `resolver: #{@resolver_class}`, consider configuration a `type ...` for that class)"
529
+ end
530
+ raise MissingReturnTypeError, message
520
531
  else
521
532
  Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
522
533
  end
523
- rescue GraphQL::Schema::InvalidDocumentError => err
534
+ rescue GraphQL::Schema::InvalidDocumentError, MissingReturnTypeError => err
524
535
  # Let this propagate up
525
536
  raise err
526
537
  rescue StandardError => err
527
- raise ArgumentError, "Failed to build return type for #{@owner.graphql_name}.#{name} from #{@return_type_expr.inspect}: (#{err.class}) #{err.message}", err.backtrace
538
+ raise MissingReturnTypeError, "Failed to build return type for #{@owner.graphql_name}.#{name} from #{@return_type_expr.inspect}: (#{err.class}) #{err.message}", err.backtrace
528
539
  end
529
540
 
530
541
  def visible?(context)
@@ -608,8 +619,7 @@ module GraphQL
608
619
  if is_authorized
609
620
  public_send_field(object, args, ctx)
610
621
  else
611
- err = GraphQL::UnauthorizedFieldError.new(object: application_object, type: object.class, context: ctx, field: self)
612
- ctx.schema.unauthorized_field(err)
622
+ raise GraphQL::UnauthorizedFieldError.new(object: application_object, type: object.class, context: ctx, field: self)
613
623
  end
614
624
  end
615
625
  rescue GraphQL::UnauthorizedFieldError => err
@@ -40,11 +40,7 @@ module GraphQL
40
40
  # With the interpreter, it's done during `coerce_arguments`
41
41
  if loads && !arg_defn.from_resolver? && !context.interpreter?
42
42
  value = @ruby_style_hash[ruby_kwargs_key]
43
- loaded_value = if arg_defn.type.list?
44
- value.map { |val| load_application_object(arg_defn, loads, val, context) }
45
- else
46
- load_application_object(arg_defn, loads, value, context)
47
- end
43
+ loaded_value = arg_defn.load_and_authorize_value(self, value, context)
48
44
  maybe_lazies << context.schema.after_lazy(loaded_value) do |loaded_value|
49
45
  overwrite_argument(ruby_kwargs_key, loaded_value)
50
46
  end