graphql 2.0.21 → 2.0.32
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.
- checksums.yaml +4 -4
- data/lib/generators/graphql/mutation_delete_generator.rb +1 -1
- data/lib/generators/graphql/mutation_update_generator.rb +1 -1
- data/lib/generators/graphql/relay.rb +18 -1
- data/lib/graphql/backtrace.rb +0 -4
- data/lib/graphql/dataloader/source.rb +69 -45
- data/lib/graphql/dataloader.rb +4 -4
- data/lib/graphql/execution/interpreter/arguments_cache.rb +31 -30
- data/lib/graphql/execution/interpreter/runtime.rb +122 -101
- data/lib/graphql/execution/interpreter.rb +1 -2
- data/lib/graphql/execution/lookahead.rb +1 -1
- data/lib/graphql/filter.rb +2 -1
- data/lib/graphql/introspection/entry_points.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +16 -9
- data/lib/graphql/language/lexer.rb +89 -57
- data/lib/graphql/language/nodes.rb +3 -0
- data/lib/graphql/language/parser.rb +706 -691
- data/lib/graphql/language/parser.y +1 -0
- data/lib/graphql/language/printer.rb +28 -14
- data/lib/graphql/language/visitor.rb +64 -61
- data/lib/graphql/query/context.rb +16 -7
- data/lib/graphql/query/null_context.rb +8 -18
- data/lib/graphql/query/validation_pipeline.rb +2 -1
- data/lib/graphql/query.rb +37 -12
- data/lib/graphql/schema/addition.rb +38 -12
- data/lib/graphql/schema/always_visible.rb +10 -0
- data/lib/graphql/schema/argument.rb +8 -10
- data/lib/graphql/schema/build_from_definition.rb +8 -7
- data/lib/graphql/schema/directive.rb +1 -1
- data/lib/graphql/schema/enum_value.rb +2 -2
- data/lib/graphql/schema/field/connection_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +26 -15
- data/lib/graphql/schema/input_object.rb +9 -7
- data/lib/graphql/schema/interface.rb +5 -1
- data/lib/graphql/schema/introspection_system.rb +1 -1
- data/lib/graphql/schema/member/build_type.rb +10 -2
- data/lib/graphql/schema/member/has_arguments.rb +9 -7
- data/lib/graphql/schema/member/has_directives.rb +1 -1
- data/lib/graphql/schema/member/has_fields.rb +1 -1
- data/lib/graphql/schema/member/has_interfaces.rb +1 -1
- data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
- data/lib/graphql/schema/object.rb +6 -1
- data/lib/graphql/schema/printer.rb +3 -1
- data/lib/graphql/schema/relay_classic_mutation.rb +1 -1
- data/lib/graphql/schema/resolver.rb +12 -10
- data/lib/graphql/schema/timeout.rb +1 -1
- data/lib/graphql/schema/validator.rb +1 -1
- data/lib/graphql/schema/warden.rb +37 -4
- data/lib/graphql/schema.rb +92 -23
- data/lib/graphql/tracing/appoptics_trace.rb +35 -11
- data/lib/graphql/tracing/appsignal_trace.rb +4 -0
- data/lib/graphql/tracing/data_dog_trace.rb +89 -50
- data/lib/graphql/tracing/data_dog_tracing.rb +7 -21
- data/lib/graphql/tracing/legacy_trace.rb +5 -1
- data/lib/graphql/tracing/notifications_trace.rb +7 -0
- data/lib/graphql/tracing/platform_trace.rb +26 -12
- data/lib/graphql/tracing/prometheus_trace.rb +4 -0
- data/lib/graphql/tracing/scout_trace.rb +3 -0
- data/lib/graphql/tracing/statsd_trace.rb +4 -0
- data/lib/graphql/tracing.rb +1 -0
- data/lib/graphql/types/relay/connection_behaviors.rb +1 -1
- data/lib/graphql/types/relay/edge_behaviors.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -1
- metadata +36 -24
@@ -53,6 +53,7 @@ module GraphQL
|
|
53
53
|
def initialize(arg_name = nil, type_expr = nil, desc = nil, required: true, type: nil, name: nil, loads: nil, description: nil, ast_node: nil, default_value: NOT_CONFIGURED, as: nil, from_resolver: false, camelize: true, prepare: nil, owner:, validates: nil, directives: nil, deprecation_reason: nil, replace_null_with_default: false, &definition_block)
|
54
54
|
arg_name ||= name
|
55
55
|
@name = -(camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s)
|
56
|
+
NameValidator.validate!(@name)
|
56
57
|
@type_expr = type_expr || type
|
57
58
|
@description = desc || description
|
58
59
|
@null = required != true
|
@@ -88,11 +89,8 @@ module GraphQL
|
|
88
89
|
end
|
89
90
|
|
90
91
|
if definition_block
|
91
|
-
|
92
|
-
|
93
|
-
else
|
94
|
-
instance_eval(&definition_block)
|
95
|
-
end
|
92
|
+
# `self` will still be self, it will also be the first argument to the block:
|
93
|
+
instance_exec(self, &definition_block)
|
96
94
|
end
|
97
95
|
end
|
98
96
|
|
@@ -198,8 +196,8 @@ module GraphQL
|
|
198
196
|
|
199
197
|
def statically_coercible?
|
200
198
|
return @statically_coercible if defined?(@statically_coercible)
|
201
|
-
|
202
|
-
@statically_coercible =
|
199
|
+
requires_parent_object = @prepare.is_a?(String) || @prepare.is_a?(Symbol) || @own_validators
|
200
|
+
@statically_coercible = !requires_parent_object
|
203
201
|
end
|
204
202
|
|
205
203
|
# Apply the {prepare} configuration to `value`, using methods from `obj`.
|
@@ -264,7 +262,7 @@ module GraphQL
|
|
264
262
|
|
265
263
|
# If this isn't lazy, then the block returns eagerly and assigns the result here
|
266
264
|
# If it _is_ lazy, then we write the lazy to the hash, then update it later
|
267
|
-
argument_values[arg_key] = context.
|
265
|
+
argument_values[arg_key] = context.query.after_lazy(coerced_value) do |resolved_coerced_value|
|
268
266
|
owner.validate_directive_argument(self, resolved_coerced_value)
|
269
267
|
prepared_value = begin
|
270
268
|
prepare_value(parent_object, resolved_coerced_value, context: context)
|
@@ -281,7 +279,7 @@ module GraphQL
|
|
281
279
|
end
|
282
280
|
|
283
281
|
maybe_loaded_value = loaded_value || prepared_value
|
284
|
-
context.
|
282
|
+
context.query.after_lazy(maybe_loaded_value) do |resolved_loaded_value|
|
285
283
|
# TODO code smell to access such a deeply-nested constant in a distant module
|
286
284
|
argument_values[arg_key] = GraphQL::Execution::Interpreter::ArgumentValue.new(
|
287
285
|
value: resolved_loaded_value,
|
@@ -303,7 +301,7 @@ module GraphQL
|
|
303
301
|
else
|
304
302
|
load_method_owner.public_send(arg_load_method, coerced_value)
|
305
303
|
end
|
306
|
-
context.
|
304
|
+
context.query.after_lazy(custom_loaded_value) do |custom_value|
|
307
305
|
if loads
|
308
306
|
if type.list?
|
309
307
|
loaded_values = custom_value.each_with_index.map { |custom_val, idx|
|
@@ -453,17 +453,18 @@ module GraphQL
|
|
453
453
|
|
454
454
|
# Don't do this for interfaces
|
455
455
|
if default_resolve
|
456
|
-
owner
|
457
|
-
# frozen_string_literal: true
|
458
|
-
def #{resolve_method_name}(**args)
|
459
|
-
field_instance = self.class.get_field("#{field_definition.name}")
|
460
|
-
context.schema.definition_default_resolve.call(self.class, field_instance, object, args, context)
|
461
|
-
end
|
462
|
-
RUBY
|
456
|
+
define_field_resolve_method(owner, resolve_method_name, field_definition.name)
|
463
457
|
end
|
464
458
|
end
|
465
459
|
end
|
466
460
|
|
461
|
+
def define_field_resolve_method(owner, method_name, field_name)
|
462
|
+
owner.define_method(method_name) { |**args|
|
463
|
+
field_instance = self.class.get_field(field_name)
|
464
|
+
context.schema.definition_default_resolve.call(self.class, field_instance, object, args, context)
|
465
|
+
}
|
466
|
+
end
|
467
|
+
|
467
468
|
def build_resolve_type(lookup_hash, directives, missing_type_handler)
|
468
469
|
resolve_type_proc = nil
|
469
470
|
resolve_type_proc = ->(ast_node) {
|
@@ -34,7 +34,7 @@ module GraphQL
|
|
34
34
|
@graphql_name = graphql_name.to_s
|
35
35
|
GraphQL::NameValidator.validate!(@graphql_name)
|
36
36
|
@description = desc || description
|
37
|
-
@value = value
|
37
|
+
@value = value == NOT_CONFIGURED ? @graphql_name : value
|
38
38
|
if deprecation_reason
|
39
39
|
self.deprecation_reason = deprecation_reason
|
40
40
|
end
|
@@ -47,7 +47,7 @@ module GraphQL
|
|
47
47
|
end
|
48
48
|
|
49
49
|
if block_given?
|
50
|
-
|
50
|
+
instance_exec(self, &block)
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
@@ -26,7 +26,7 @@ module GraphQL
|
|
26
26
|
# rename some inputs to avoid conflicts inside the block
|
27
27
|
maybe_lazy = value
|
28
28
|
value = nil
|
29
|
-
context.
|
29
|
+
context.query.after_lazy(maybe_lazy) do |resolved_value|
|
30
30
|
value = resolved_value
|
31
31
|
if value.is_a? GraphQL::ExecutionError
|
32
32
|
# This isn't even going to work because context doesn't have ast_node anymore
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -92,7 +92,7 @@ module GraphQL
|
|
92
92
|
# @param resolver [Class] A {GraphQL::Schema::Resolver} class to use for field configuration
|
93
93
|
# @param mutation [Class] A {GraphQL::Schema::Mutation} class to use for field configuration
|
94
94
|
# @param subscription [Class] A {GraphQL::Schema::Subscription} class to use for field configuration
|
95
|
-
# @return [GraphQL::Schema:Field] an instance of `self
|
95
|
+
# @return [GraphQL::Schema:Field] an instance of `self`
|
96
96
|
# @see {.initialize} for other options
|
97
97
|
def self.from_options(name = nil, type = nil, desc = nil, resolver: nil, mutation: nil, subscription: nil,**kwargs, &block)
|
98
98
|
if (resolver_class = resolver || mutation || subscription)
|
@@ -233,9 +233,9 @@ module GraphQL
|
|
233
233
|
|
234
234
|
@underscored_name = -Member::BuildType.underscore(name_s)
|
235
235
|
@name = -(camelize ? Member::BuildType.camelize(name_s) : name_s)
|
236
|
-
|
236
|
+
NameValidator.validate!(@name)
|
237
237
|
@description = description
|
238
|
-
@type = @owner_type = @own_validators = @own_directives = @own_arguments = nil # these will be prepared later if necessary
|
238
|
+
@type = @owner_type = @own_validators = @own_directives = @own_arguments = @arguments_statically_coercible = nil # these will be prepared later if necessary
|
239
239
|
|
240
240
|
self.deprecation_reason = deprecation_reason
|
241
241
|
|
@@ -339,7 +339,7 @@ module GraphQL
|
|
339
339
|
self.validates(validates)
|
340
340
|
end
|
341
341
|
|
342
|
-
if
|
342
|
+
if block_given?
|
343
343
|
if definition_block.arity == 1
|
344
344
|
yield self
|
345
345
|
else
|
@@ -661,7 +661,7 @@ module GraphQL
|
|
661
661
|
|
662
662
|
Schema::Validator.validate!(validators, application_object, query_ctx, args)
|
663
663
|
|
664
|
-
query_ctx.
|
664
|
+
query_ctx.query.after_lazy(self.authorized?(application_object, args, query_ctx)) do |is_authorized|
|
665
665
|
if is_authorized
|
666
666
|
with_extensions(object, args, query_ctx) do |obj, ruby_kwargs|
|
667
667
|
method_args = ruby_kwargs
|
@@ -810,6 +810,17 @@ ERR
|
|
810
810
|
end
|
811
811
|
end
|
812
812
|
|
813
|
+
class ExtendedState
|
814
|
+
def initialize(args, object)
|
815
|
+
@arguments = args
|
816
|
+
@object = object
|
817
|
+
@memos = nil
|
818
|
+
@added_extras = nil
|
819
|
+
end
|
820
|
+
|
821
|
+
attr_accessor :arguments, :object, :memos, :added_extras
|
822
|
+
end
|
823
|
+
|
813
824
|
# Wrap execution with hooks.
|
814
825
|
# Written iteratively to avoid big stack traces.
|
815
826
|
# @return [Object] Whatever the
|
@@ -820,20 +831,20 @@ ERR
|
|
820
831
|
# This is a hack to get the _last_ value for extended obj and args,
|
821
832
|
# in case one of the extensions doesn't `yield`.
|
822
833
|
# (There's another implementation that uses multiple-return, but I'm wary of the perf cost of the extra arrays)
|
823
|
-
extended =
|
834
|
+
extended = ExtendedState.new(args, obj)
|
824
835
|
value = run_extensions_before_resolve(obj, args, ctx, extended) do |obj, args|
|
825
|
-
if (added_extras = extended
|
836
|
+
if (added_extras = extended.added_extras)
|
826
837
|
args = args.dup
|
827
838
|
added_extras.each { |e| args.delete(e) }
|
828
839
|
end
|
829
840
|
yield(obj, args)
|
830
841
|
end
|
831
842
|
|
832
|
-
extended_obj = extended
|
833
|
-
extended_args = extended
|
834
|
-
memos = extended
|
843
|
+
extended_obj = extended.object
|
844
|
+
extended_args = extended.arguments # rubocop:disable Development/ContextIsPassedCop
|
845
|
+
memos = extended.memos || EMPTY_HASH
|
835
846
|
|
836
|
-
ctx.
|
847
|
+
ctx.query.after_lazy(value) do |resolved_value|
|
837
848
|
idx = 0
|
838
849
|
@extensions.each do |ext|
|
839
850
|
memo = memos[idx]
|
@@ -851,17 +862,17 @@ ERR
|
|
851
862
|
if extension
|
852
863
|
extension.resolve(object: obj, arguments: args, context: ctx) do |extended_obj, extended_args, memo|
|
853
864
|
if memo
|
854
|
-
memos = extended
|
865
|
+
memos = extended.memos ||= {}
|
855
866
|
memos[idx] = memo
|
856
867
|
end
|
857
868
|
|
858
869
|
if (extras = extension.added_extras)
|
859
|
-
ae = extended
|
870
|
+
ae = extended.added_extras ||= []
|
860
871
|
ae.concat(extras)
|
861
872
|
end
|
862
873
|
|
863
|
-
extended
|
864
|
-
extended
|
874
|
+
extended.object = extended_obj
|
875
|
+
extended.arguments = extended_args
|
865
876
|
run_extensions_before_resolve(extended_obj, extended_args, ctx, extended, idx: idx + 1) { |o, a| yield(o, a) }
|
866
877
|
end
|
867
878
|
else
|
@@ -131,12 +131,7 @@ module GraphQL
|
|
131
131
|
end
|
132
132
|
end
|
133
133
|
# Add a method access
|
134
|
-
|
135
|
-
class_eval <<-RUBY, __FILE__, __LINE__
|
136
|
-
def #{method_name}
|
137
|
-
self[#{method_name.inspect}]
|
138
|
-
end
|
139
|
-
RUBY
|
134
|
+
define_accessor_method(argument_defn.keyword)
|
140
135
|
argument_defn
|
141
136
|
end
|
142
137
|
|
@@ -211,7 +206,7 @@ module GraphQL
|
|
211
206
|
|
212
207
|
arguments = coerce_arguments(nil, value, ctx)
|
213
208
|
|
214
|
-
ctx.
|
209
|
+
ctx.query.after_lazy(arguments) do |resolved_arguments|
|
215
210
|
if resolved_arguments.is_a?(GraphQL::Error)
|
216
211
|
raise resolved_arguments
|
217
212
|
else
|
@@ -242,6 +237,13 @@ module GraphQL
|
|
242
237
|
|
243
238
|
result
|
244
239
|
end
|
240
|
+
|
241
|
+
private
|
242
|
+
|
243
|
+
def define_accessor_method(method_name)
|
244
|
+
define_method(method_name) { self[method_name] }
|
245
|
+
alias_method(method_name, method_name)
|
246
|
+
end
|
245
247
|
end
|
246
248
|
|
247
249
|
private
|
@@ -69,7 +69,11 @@ module GraphQL
|
|
69
69
|
end
|
70
70
|
elsif child_class < GraphQL::Schema::Object
|
71
71
|
# This is being included into an object type, make sure it's using `implements(...)`
|
72
|
-
backtrace_line =
|
72
|
+
backtrace_line = caller_locations(0, 10).find do |location|
|
73
|
+
location.base_label == "implements" &&
|
74
|
+
location.path.end_with?("schema/member/has_interfaces.rb")
|
75
|
+
end
|
76
|
+
|
73
77
|
if !backtrace_line
|
74
78
|
raise "Attach interfaces using `implements(#{self})`, not `include(#{self})`"
|
75
79
|
end
|
@@ -155,7 +155,7 @@ module GraphQL
|
|
155
155
|
if obj.is_a?(GraphQL::Schema::Object)
|
156
156
|
obj = obj.object
|
157
157
|
end
|
158
|
-
wrapped_object = @object_class.
|
158
|
+
wrapped_object = @object_class.wrap(obj, query_ctx)
|
159
159
|
@inner_resolve.call(wrapped_object, args, ctx)
|
160
160
|
end
|
161
161
|
end
|
@@ -109,7 +109,14 @@ module GraphQL
|
|
109
109
|
to_type_name(something.name)
|
110
110
|
end
|
111
111
|
when String
|
112
|
-
something.
|
112
|
+
if something.include?("]") ||
|
113
|
+
something.include?("[") ||
|
114
|
+
something.include?("!") ||
|
115
|
+
something.include?("::")
|
116
|
+
something.gsub(/\]\[\!/, "").split("::").last
|
117
|
+
else
|
118
|
+
something
|
119
|
+
end
|
113
120
|
when GraphQL::Schema::NonNull, GraphQL::Schema::List
|
114
121
|
to_type_name(something.unwrap)
|
115
122
|
else
|
@@ -122,7 +129,8 @@ module GraphQL
|
|
122
129
|
return string unless string.include?("_")
|
123
130
|
camelized = string.split('_').each(&:capitalize!).join
|
124
131
|
camelized[0] = camelized[0].downcase
|
125
|
-
if
|
132
|
+
if string.start_with?("_")
|
133
|
+
match_data = string.match(/\A(_+)/)
|
126
134
|
camelized = "#{match_data[0]}#{camelized}"
|
127
135
|
end
|
128
136
|
camelized
|
@@ -51,7 +51,7 @@ module GraphQL
|
|
51
51
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
52
52
|
def #{method_owner}load_#{arg_defn.keyword}(values, context = nil)
|
53
53
|
argument = get_argument("#{arg_defn.graphql_name}")
|
54
|
-
(context || self.context).
|
54
|
+
(context || self.context).query.after_lazy(values) do |values2|
|
55
55
|
GraphQL::Execution::Lazy.all(values2.map { |value| load_application_object(argument, value, context || self.context) })
|
56
56
|
end
|
57
57
|
end
|
@@ -320,9 +320,11 @@ module GraphQL
|
|
320
320
|
end
|
321
321
|
|
322
322
|
def arguments_statically_coercible?
|
323
|
-
|
324
|
-
|
325
|
-
|
323
|
+
if defined?(@arguments_statically_coercible) && !@arguments_statically_coercible.nil?
|
324
|
+
@arguments_statically_coercible
|
325
|
+
else
|
326
|
+
@arguments_statically_coercible = all_argument_definitions.all?(&:statically_coercible?)
|
327
|
+
end
|
326
328
|
end
|
327
329
|
|
328
330
|
module ArgumentClassAccessor
|
@@ -363,7 +365,7 @@ module GraphQL
|
|
363
365
|
end
|
364
366
|
|
365
367
|
def authorize_application_object(argument, id, context, loaded_application_object)
|
366
|
-
context.
|
368
|
+
context.query.after_lazy(loaded_application_object) do |application_object|
|
367
369
|
if application_object.nil?
|
368
370
|
err = GraphQL::LoadApplicationObjectFailedError.new(argument: argument, id: id, object: application_object)
|
369
371
|
load_application_object_failed(err)
|
@@ -371,7 +373,7 @@ module GraphQL
|
|
371
373
|
# Double-check that the located object is actually of this type
|
372
374
|
# (Don't want to allow arbitrary access to objects this way)
|
373
375
|
maybe_lazy_resolve_type = context.schema.resolve_type(argument.loads, application_object, context)
|
374
|
-
context.
|
376
|
+
context.query.after_lazy(maybe_lazy_resolve_type) do |resolve_type_result|
|
375
377
|
if resolve_type_result.is_a?(Array) && resolve_type_result.size == 2
|
376
378
|
application_object_type, application_object = resolve_type_result
|
377
379
|
else
|
@@ -386,7 +388,7 @@ module GraphQL
|
|
386
388
|
# This object was loaded successfully
|
387
389
|
# and resolved to the right type,
|
388
390
|
# now apply the `.authorized?` class method if there is one
|
389
|
-
context.
|
391
|
+
context.query.after_lazy(application_object_type.authorized?(application_object, context)) do |authed|
|
390
392
|
if authed
|
391
393
|
application_object
|
392
394
|
else
|
@@ -30,6 +30,11 @@ module GraphQL
|
|
30
30
|
# @see authorized_new to make instances
|
31
31
|
protected :new
|
32
32
|
|
33
|
+
# This is called by the runtime to return an object to call methods on.
|
34
|
+
def wrap(object, context)
|
35
|
+
authorized_new(object, context)
|
36
|
+
end
|
37
|
+
|
33
38
|
# Make a new instance of this type _if_ the auth check passes,
|
34
39
|
# otherwise, raise an error.
|
35
40
|
#
|
@@ -68,7 +73,7 @@ module GraphQL
|
|
68
73
|
maybe_lazy_auth_val
|
69
74
|
end
|
70
75
|
|
71
|
-
context.
|
76
|
+
context.query.after_lazy(auth_val) do |is_authorized|
|
72
77
|
if is_authorized
|
73
78
|
self.new(object, context)
|
74
79
|
else
|
@@ -57,12 +57,14 @@ module GraphQL
|
|
57
57
|
query_root = Class.new(GraphQL::Schema::Object) do
|
58
58
|
graphql_name "Root"
|
59
59
|
field :throwaway_field, String
|
60
|
+
def self.visible?(ctx)
|
61
|
+
false
|
62
|
+
end
|
60
63
|
end
|
61
64
|
schema = Class.new(GraphQL::Schema) { query(query_root) }
|
62
65
|
|
63
66
|
introspection_schema_ast = GraphQL::Language::DocumentFromSchemaDefinition.new(
|
64
67
|
schema,
|
65
|
-
except: ->(member, _) { member.graphql_name == "Root" },
|
66
68
|
include_introspection_types: true,
|
67
69
|
include_built_in_directives: true,
|
68
70
|
).document
|
@@ -60,7 +60,7 @@ module GraphQL
|
|
60
60
|
super()
|
61
61
|
end
|
62
62
|
|
63
|
-
context.
|
63
|
+
context.query.after_lazy(return_value) do |return_hash|
|
64
64
|
# It might be an error
|
65
65
|
if return_hash.is_a?(Hash)
|
66
66
|
return_hash[:client_mutation_id] = client_mutation_id
|
@@ -65,41 +65,43 @@ module GraphQL
|
|
65
65
|
# @api private
|
66
66
|
def resolve_with_support(**args)
|
67
67
|
# First call the ready? hook which may raise
|
68
|
-
|
68
|
+
raw_ready_val = if args.any?
|
69
69
|
ready?(**args)
|
70
70
|
else
|
71
71
|
ready?
|
72
72
|
end
|
73
|
-
context.
|
74
|
-
if
|
73
|
+
context.query.after_lazy(raw_ready_val) do |ready_val|
|
74
|
+
if ready_val.is_a?(Array)
|
75
|
+
is_ready, ready_early_return = ready_val
|
75
76
|
if is_ready != false
|
76
77
|
raise "Unexpected result from #ready? (expected `true`, `false` or `[false, {...}]`): [#{is_ready.inspect}, #{ready_early_return.inspect}]"
|
77
78
|
else
|
78
79
|
ready_early_return
|
79
80
|
end
|
80
|
-
elsif
|
81
|
+
elsif ready_val
|
81
82
|
# Then call each prepare hook, which may return a different value
|
82
83
|
# for that argument, or may return a lazy object
|
83
84
|
load_arguments_val = load_arguments(args)
|
84
|
-
context.
|
85
|
+
context.query.after_lazy(load_arguments_val) do |loaded_args|
|
85
86
|
@prepared_arguments = loaded_args
|
86
87
|
Schema::Validator.validate!(self.class.validators, object, context, loaded_args, as: @field)
|
87
88
|
# Then call `authorized?`, which may raise or may return a lazy object
|
88
|
-
|
89
|
+
raw_authorized_val = if loaded_args.any?
|
89
90
|
authorized?(**loaded_args)
|
90
91
|
else
|
91
92
|
authorized?
|
92
93
|
end
|
93
|
-
context.
|
94
|
+
context.query.after_lazy(raw_authorized_val) do |authorized_val|
|
94
95
|
# If the `authorized?` returned two values, `false, early_return`,
|
95
96
|
# then use the early return value instead of continuing
|
96
|
-
if
|
97
|
+
if authorized_val.is_a?(Array)
|
98
|
+
authorized_result, early_return = authorized_val
|
97
99
|
if authorized_result == false
|
98
100
|
early_return
|
99
101
|
else
|
100
102
|
raise "Unexpected result from #authorized? (expected `true`, `false` or `[false, {...}]`): [#{authorized_result.inspect}, #{early_return.inspect}]"
|
101
103
|
end
|
102
|
-
elsif
|
104
|
+
elsif authorized_val
|
103
105
|
# Finally, all the hooks have passed, so resolve it
|
104
106
|
if loaded_args.any?
|
105
107
|
public_send(self.class.resolve_method, **loaded_args)
|
@@ -185,7 +187,7 @@ module GraphQL
|
|
185
187
|
if arg_defn
|
186
188
|
prepped_value = prepared_args[key] = arg_defn.load_and_authorize_value(self, value, context)
|
187
189
|
if context.schema.lazy?(prepped_value)
|
188
|
-
prepare_lazies << context.
|
190
|
+
prepare_lazies << context.query.after_lazy(prepped_value) do |finished_prepped_value|
|
189
191
|
prepared_args[key] = finished_prepped_value
|
190
192
|
end
|
191
193
|
end
|
@@ -90,7 +90,7 @@ module GraphQL
|
|
90
90
|
# The default implementation returns the `max_seconds:` value from installing this plugin.
|
91
91
|
#
|
92
92
|
# @param query [GraphQL::Query] The query that's about to run
|
93
|
-
# @return [
|
93
|
+
# @return [Numeric, false] The number of seconds after which to interrupt query execution and call {#handle_error}, or `false` to bypass the timeout.
|
94
94
|
def max_seconds(query)
|
95
95
|
@max_seconds
|
96
96
|
end
|
@@ -133,7 +133,7 @@ module GraphQL
|
|
133
133
|
if all_errors.frozen? # It's empty
|
134
134
|
all_errors = []
|
135
135
|
end
|
136
|
-
interpolation_vars = { validated: validated.graphql_name }
|
136
|
+
interpolation_vars = { validated: validated.graphql_name, value: value.inspect }
|
137
137
|
if errors.is_a?(String)
|
138
138
|
all_errors << (errors % interpolation_vars)
|
139
139
|
else
|
@@ -38,8 +38,9 @@ module GraphQL
|
|
38
38
|
# @api private
|
39
39
|
class Warden
|
40
40
|
def self.from_context(context)
|
41
|
-
context.warden
|
42
|
-
rescue
|
41
|
+
context.warden || PassThruWarden
|
42
|
+
rescue NoMethodError
|
43
|
+
# this might be a hash which won't respond to #warden
|
43
44
|
PassThruWarden
|
44
45
|
end
|
45
46
|
|
@@ -87,17 +88,49 @@ module GraphQL
|
|
87
88
|
end
|
88
89
|
end
|
89
90
|
|
91
|
+
class NullWarden
|
92
|
+
def initialize(_filter = nil, context:, schema:)
|
93
|
+
@schema = schema
|
94
|
+
end
|
95
|
+
|
96
|
+
def visible_field?(field_defn, _ctx = nil, owner = nil); true; end
|
97
|
+
def visible_argument?(arg_defn, _ctx = nil); true; end
|
98
|
+
def visible_type?(type_defn, _ctx = nil); true; end
|
99
|
+
def visible_enum_value?(enum_value, _ctx = nil); true; end
|
100
|
+
def visible_type_membership?(type_membership, _ctx = nil); true; end
|
101
|
+
def interface_type_memberships(obj_type, _ctx = nil); obj_type.interface_type_memberships; end
|
102
|
+
def get_type(type_name); @schema.get_type(type_name); end # rubocop:disable Development/ContextIsPassedCop
|
103
|
+
def arguments(argument_owner, ctx = nil); argument_owner.all_argument_definitions; end
|
104
|
+
def enum_values(enum_defn); enum_defn.enum_values; end # rubocop:disable Development/ContextIsPassedCop
|
105
|
+
def get_argument(parent_type, argument_name); parent_type.get_argument(argument_name); end # rubocop:disable Development/ContextIsPassedCop
|
106
|
+
def types; @schema.types; end # rubocop:disable Development/ContextIsPassedCop
|
107
|
+
def root_type_for_operation(op_name); @schema.root_type_for_operation(op_name); end
|
108
|
+
def directives; @schema.directives.values; end
|
109
|
+
def fields(type_defn); type_defn.all_field_definitions; end # rubocop:disable Development/ContextIsPassedCop
|
110
|
+
def get_field(parent_type, field_name); @schema.get_field(parent_type, field_name); end
|
111
|
+
def reachable_type?(type_name); true; end
|
112
|
+
def reachable_types; @schema.types.values; end # rubocop:disable Development/ContextIsPassedCop
|
113
|
+
def possible_types(type_defn); @schema.possible_types(type_defn); end
|
114
|
+
def interfaces(obj_type); obj_type.interfaces; end
|
115
|
+
end
|
116
|
+
|
90
117
|
# @param filter [<#call(member)>] Objects are hidden when `.call(member, ctx)` returns true
|
91
118
|
# @param context [GraphQL::Query::Context]
|
92
119
|
# @param schema [GraphQL::Schema]
|
93
|
-
def initialize(filter, context:, schema:)
|
120
|
+
def initialize(filter = nil, context:, schema:)
|
94
121
|
@schema = schema
|
95
122
|
# Cache these to avoid repeated hits to the inheritance chain when one isn't present
|
96
123
|
@query = @schema.query
|
97
124
|
@mutation = @schema.mutation
|
98
125
|
@subscription = @schema.subscription
|
99
126
|
@context = context
|
100
|
-
@visibility_cache =
|
127
|
+
@visibility_cache = if filter
|
128
|
+
read_through { |m| filter.call(m, context) }
|
129
|
+
else
|
130
|
+
read_through { |m| schema.visible?(m, context) }
|
131
|
+
end
|
132
|
+
|
133
|
+
@visibility_cache.compare_by_identity
|
101
134
|
# Initialize all ivars to improve object shape consistency:
|
102
135
|
@types = @visible_types = @reachable_types = @visible_parent_fields =
|
103
136
|
@visible_possible_types = @visible_fields = @visible_arguments = @visible_enum_arrays =
|