graphql 1.12.17 → 1.12.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.
- checksums.yaml +4 -4
- data/lib/generators/graphql/object_generator.rb +2 -1
- data/lib/generators/graphql/relay.rb +19 -11
- data/lib/generators/graphql/templates/schema.erb +14 -2
- data/lib/graphql/analysis/ast/field_usage.rb +1 -1
- data/lib/graphql/dataloader/source.rb +32 -2
- data/lib/graphql/dataloader.rb +13 -0
- data/lib/graphql/deprecated_dsl.rb +11 -3
- data/lib/graphql/deprecation.rb +1 -5
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/pagination/connections.rb +35 -16
- data/lib/graphql/query/validation_pipeline.rb +1 -1
- data/lib/graphql/schema/argument.rb +55 -26
- data/lib/graphql/schema/field.rb +14 -4
- data/lib/graphql/schema/input_object.rb +1 -5
- data/lib/graphql/schema/member/has_arguments.rb +90 -44
- data/lib/graphql/schema/resolver.rb +20 -57
- data/lib/graphql/schema/subscription.rb +4 -4
- data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
- data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
- data/lib/graphql/schema/validator/exclusion_validator.rb +3 -1
- data/lib/graphql/schema/validator/format_validator.rb +4 -1
- data/lib/graphql/schema/validator/inclusion_validator.rb +3 -1
- data/lib/graphql/schema/validator/length_validator.rb +5 -3
- data/lib/graphql/schema/validator/numericality_validator.rb +7 -1
- data/lib/graphql/schema/validator.rb +36 -25
- data/lib/graphql/schema.rb +18 -5
- data/lib/graphql/static_validation/base_visitor.rb +3 -0
- data/lib/graphql/static_validation/error.rb +3 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +40 -21
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
- data/lib/graphql/static_validation/validation_context.rb +8 -2
- data/lib/graphql/static_validation/validator.rb +15 -12
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -1
- data/lib/graphql/subscriptions/event.rb +47 -2
- data/lib/graphql/subscriptions/serialize.rb +1 -1
- data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
- data/lib/graphql/types/int.rb +1 -1
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/unauthorized_error.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6fa9800286687f6236697bf1f3eed4f3342b40fbbbebc64c472a7d791442bce4
|
4
|
+
data.tar.gz: a74ed6cf70cf2f626c2339a8377ada5dea5491eb3e53a1e1783b4a7a8dd8bebc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
#
|
36
|
-
|
37
|
-
#
|
38
|
-
|
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(
|
43
|
-
# For example,
|
44
|
-
#
|
45
|
-
|
46
|
-
#
|
47
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
data/lib/graphql/dataloader.rb
CHANGED
@@ -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
|
-
|
42
|
-
|
43
|
-
|
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
|
data/lib/graphql/deprecation.rb
CHANGED
@@ -12,9 +12,25 @@ module GraphQL
|
|
12
12
|
# The value which couldn't be encoded
|
13
13
|
attr_reader :integer_value
|
14
14
|
|
15
|
-
|
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
|
-
|
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
|
74
|
-
|
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
|
-
#
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
context.
|
268
|
-
|
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
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
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
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
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
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
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
|
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -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
|
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
|
-
|
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 =
|
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
|