graphql 2.0.21 → 2.0.23
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/graphql/backtrace.rb +0 -4
- data/lib/graphql/execution/interpreter/arguments_cache.rb +31 -30
- data/lib/graphql/execution/interpreter/runtime.rb +101 -83
- 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/language/document_from_schema_definition.rb +16 -9
- data/lib/graphql/language/lexer.rb +5 -3
- data/lib/graphql/language/printer.rb +28 -14
- data/lib/graphql/query/context.rb +16 -7
- data/lib/graphql/query/null_context.rb +8 -18
- data/lib/graphql/query.rb +21 -11
- data/lib/graphql/schema/always_visible.rb +10 -0
- data/lib/graphql/schema/argument.rb +5 -5
- data/lib/graphql/schema/enum_value.rb +1 -1
- data/lib/graphql/schema/field/connection_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +23 -12
- data/lib/graphql/schema/input_object.rb +1 -1
- data/lib/graphql/schema/member/has_arguments.rb +9 -7
- data/lib/graphql/schema/object.rb +1 -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 +4 -4
- data/lib/graphql/schema/timeout.rb +1 -1
- data/lib/graphql/schema/warden.rb +37 -4
- data/lib/graphql/schema.rb +29 -14
- data/lib/graphql/tracing/legacy_trace.rb +5 -1
- data/lib/graphql/tracing/notifications_trace.rb +3 -0
- data/lib/graphql/tracing.rb +1 -0
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -1
- metadata +4 -3
@@ -95,12 +95,14 @@ module GraphQL
|
|
95
95
|
previous_token: nil,
|
96
96
|
}
|
97
97
|
|
98
|
-
|
99
|
-
|
98
|
+
value = string.dup.force_encoding(Encoding::UTF_8)
|
99
|
+
|
100
|
+
unless value.valid_encoding?
|
101
|
+
emit(:BAD_UNICODE_ESCAPE, 0, 0, meta, value)
|
100
102
|
return meta[:tokens]
|
101
103
|
end
|
102
104
|
|
103
|
-
scan = StringScanner.new
|
105
|
+
scan = StringScanner.new value
|
104
106
|
|
105
107
|
while !scan.eos?
|
106
108
|
pos = scan.pos
|
@@ -131,7 +131,7 @@ module GraphQL
|
|
131
131
|
"$#{variable_identifier.name}".dup
|
132
132
|
end
|
133
133
|
|
134
|
-
def print_schema_definition(schema)
|
134
|
+
def print_schema_definition(schema, extension: false)
|
135
135
|
has_conventional_names = (schema.query.nil? || schema.query == 'Query') &&
|
136
136
|
(schema.mutation.nil? || schema.mutation == 'Mutation') &&
|
137
137
|
(schema.subscription.nil? || schema.subscription == 'Subscription')
|
@@ -140,7 +140,7 @@ module GraphQL
|
|
140
140
|
return
|
141
141
|
end
|
142
142
|
|
143
|
-
out = "schema".dup
|
143
|
+
out = extension ? "extend schema".dup : "schema".dup
|
144
144
|
if schema.directives.any?
|
145
145
|
schema.directives.each do |dir|
|
146
146
|
out << "\n "
|
@@ -164,14 +164,14 @@ module GraphQL
|
|
164
164
|
out
|
165
165
|
end
|
166
166
|
|
167
|
-
def print_scalar_type_definition(scalar_type)
|
168
|
-
out = print_description(scalar_type)
|
167
|
+
def print_scalar_type_definition(scalar_type, extension: false)
|
168
|
+
out = extension ? "extend ".dup : print_description(scalar_type)
|
169
169
|
out << "scalar #{scalar_type.name}"
|
170
170
|
out << print_directives(scalar_type.directives)
|
171
171
|
end
|
172
172
|
|
173
|
-
def print_object_type_definition(object_type)
|
174
|
-
out = print_description(object_type)
|
173
|
+
def print_object_type_definition(object_type, extension: false)
|
174
|
+
out = extension ? "extend ".dup : print_description(object_type)
|
175
175
|
out << "type #{object_type.name}"
|
176
176
|
out << print_implements(object_type) unless object_type.interfaces.empty?
|
177
177
|
out << print_directives(object_type.directives)
|
@@ -210,23 +210,23 @@ module GraphQL
|
|
210
210
|
out << print_directives(field.directives)
|
211
211
|
end
|
212
212
|
|
213
|
-
def print_interface_type_definition(interface_type)
|
214
|
-
out = print_description(interface_type)
|
213
|
+
def print_interface_type_definition(interface_type, extension: false)
|
214
|
+
out = extension ? "extend ".dup : print_description(interface_type)
|
215
215
|
out << "interface #{interface_type.name}"
|
216
216
|
out << print_implements(interface_type) if interface_type.interfaces.any?
|
217
217
|
out << print_directives(interface_type.directives)
|
218
218
|
out << print_field_definitions(interface_type.fields)
|
219
219
|
end
|
220
220
|
|
221
|
-
def print_union_type_definition(union_type)
|
222
|
-
out = print_description(union_type)
|
221
|
+
def print_union_type_definition(union_type, extension: false)
|
222
|
+
out = extension ? "extend ".dup : print_description(union_type)
|
223
223
|
out << "union #{union_type.name}"
|
224
224
|
out << print_directives(union_type.directives)
|
225
225
|
out << " = " + union_type.types.map(&:name).join(" | ")
|
226
226
|
end
|
227
227
|
|
228
|
-
def print_enum_type_definition(enum_type)
|
229
|
-
out = print_description(enum_type)
|
228
|
+
def print_enum_type_definition(enum_type, extension: false)
|
229
|
+
out = extension ? "extend ".dup : print_description(enum_type)
|
230
230
|
out << "enum #{enum_type.name}#{print_directives(enum_type.directives)} {\n"
|
231
231
|
enum_type.values.each.with_index do |value, i|
|
232
232
|
out << print_description(value, indent: ' ', first_in_block: i == 0)
|
@@ -241,8 +241,8 @@ module GraphQL
|
|
241
241
|
out << "\n"
|
242
242
|
end
|
243
243
|
|
244
|
-
def print_input_object_type_definition(input_object_type)
|
245
|
-
out = print_description(input_object_type)
|
244
|
+
def print_input_object_type_definition(input_object_type, extension: false)
|
245
|
+
out = extension ? "extend ".dup : print_description(input_object_type)
|
246
246
|
out << "input #{input_object_type.name}"
|
247
247
|
out << print_directives(input_object_type.directives)
|
248
248
|
if !input_object_type.fields.empty?
|
@@ -347,24 +347,38 @@ module GraphQL
|
|
347
347
|
print_variable_identifier(node)
|
348
348
|
when Nodes::SchemaDefinition
|
349
349
|
print_schema_definition(node)
|
350
|
+
when Nodes::SchemaExtension
|
351
|
+
print_schema_definition(node, extension: true)
|
350
352
|
when Nodes::ScalarTypeDefinition
|
351
353
|
print_scalar_type_definition(node)
|
354
|
+
when Nodes::ScalarTypeExtension
|
355
|
+
print_scalar_type_definition(node, extension: true)
|
352
356
|
when Nodes::ObjectTypeDefinition
|
353
357
|
print_object_type_definition(node)
|
358
|
+
when Nodes::ObjectTypeExtension
|
359
|
+
print_object_type_definition(node, extension: true)
|
354
360
|
when Nodes::InputValueDefinition
|
355
361
|
print_input_value_definition(node)
|
356
362
|
when Nodes::FieldDefinition
|
357
363
|
print_field_definition(node)
|
358
364
|
when Nodes::InterfaceTypeDefinition
|
359
365
|
print_interface_type_definition(node)
|
366
|
+
when Nodes::InterfaceTypeExtension
|
367
|
+
print_interface_type_definition(node, extension: true)
|
360
368
|
when Nodes::UnionTypeDefinition
|
361
369
|
print_union_type_definition(node)
|
370
|
+
when Nodes::UnionTypeExtension
|
371
|
+
print_union_type_definition(node, extension: true)
|
362
372
|
when Nodes::EnumTypeDefinition
|
363
373
|
print_enum_type_definition(node)
|
374
|
+
when Nodes::EnumTypeExtension
|
375
|
+
print_enum_type_definition(node, extension: true)
|
364
376
|
when Nodes::EnumValueDefinition
|
365
377
|
print_enum_value_definition(node)
|
366
378
|
when Nodes::InputObjectTypeDefinition
|
367
379
|
print_input_object_type_definition(node)
|
380
|
+
when Nodes::InputObjectTypeExtension
|
381
|
+
print_input_object_type_definition(node, extension: true)
|
368
382
|
when Nodes::DirectiveDefinition
|
369
383
|
print_directive_definition(node)
|
370
384
|
when FalseClass, Float, Integer, NilClass, String, TrueClass, Symbol
|
@@ -227,7 +227,8 @@ module GraphQL
|
|
227
227
|
current_path
|
228
228
|
else
|
229
229
|
(current_runtime_state = Thread.current[:__graphql_runtime_info]) &&
|
230
|
-
(current_runtime_state
|
230
|
+
(query_runtime_state = current_runtime_state[@query]) &&
|
231
|
+
(query_runtime_state.public_send(key))
|
231
232
|
end
|
232
233
|
else
|
233
234
|
# not found
|
@@ -237,10 +238,12 @@ module GraphQL
|
|
237
238
|
|
238
239
|
def current_path
|
239
240
|
current_runtime_state = Thread.current[:__graphql_runtime_info]
|
240
|
-
|
241
|
-
|
241
|
+
query_runtime_state = current_runtime_state && current_runtime_state[@query]
|
242
|
+
|
243
|
+
path = query_runtime_state &&
|
244
|
+
(result = query_runtime_state.current_result) &&
|
242
245
|
(result.path)
|
243
|
-
if path && (rn =
|
246
|
+
if path && (rn = query_runtime_state.current_result_name)
|
244
247
|
path = path.dup
|
245
248
|
path.push(rn)
|
246
249
|
end
|
@@ -260,7 +263,8 @@ module GraphQL
|
|
260
263
|
def fetch(key, default = UNSPECIFIED_FETCH_DEFAULT)
|
261
264
|
if RUNTIME_METADATA_KEYS.include?(key)
|
262
265
|
(runtime = Thread.current[:__graphql_runtime_info]) &&
|
263
|
-
(runtime
|
266
|
+
(query_runtime_state = runtime[@query]) &&
|
267
|
+
(query_runtime_state.public_send(key))
|
264
268
|
elsif @scoped_context.key?(key)
|
265
269
|
scoped_context[key]
|
266
270
|
elsif @provided_values.key?(key)
|
@@ -277,8 +281,13 @@ module GraphQL
|
|
277
281
|
def dig(key, *other_keys)
|
278
282
|
if RUNTIME_METADATA_KEYS.include?(key)
|
279
283
|
(current_runtime_state = Thread.current[:__graphql_runtime_info]) &&
|
280
|
-
(
|
281
|
-
obj.
|
284
|
+
(query_runtime_state = current_runtime_state[@query]) &&
|
285
|
+
(obj = query_runtime_state.public_send(key)) &&
|
286
|
+
if other_keys.empty?
|
287
|
+
obj
|
288
|
+
else
|
289
|
+
obj.dig(*other_keys)
|
290
|
+
end
|
282
291
|
elsif @scoped_context.key?(key)
|
283
292
|
@scoped_context.dig(key, *other_keys)
|
284
293
|
else
|
@@ -3,35 +3,27 @@ module GraphQL
|
|
3
3
|
class Query
|
4
4
|
# This object can be `ctx` in places where there is no query
|
5
5
|
class NullContext
|
6
|
-
class NullWarden < GraphQL::Schema::Warden
|
7
|
-
def visible_field?(field, ctx); true; end
|
8
|
-
def visible_argument?(arg, ctx); true; end
|
9
|
-
def visible_type?(type, ctx); true; end
|
10
|
-
def visible_enum_value?(ev, ctx); true; end
|
11
|
-
def visible_type_membership?(tm, ctx); true; end
|
12
|
-
end
|
13
|
-
|
14
6
|
class NullQuery
|
7
|
+
def after_lazy(value)
|
8
|
+
yield(value)
|
9
|
+
end
|
15
10
|
end
|
16
11
|
|
17
12
|
class NullSchema < GraphQL::Schema
|
18
13
|
end
|
19
14
|
|
15
|
+
extend Forwardable
|
16
|
+
|
20
17
|
attr_reader :schema, :query, :warden, :dataloader
|
18
|
+
def_delegators GraphQL::EmptyObjects::EMPTY_HASH, :[], :fetch, :dig, :key?
|
21
19
|
|
22
20
|
def initialize
|
23
21
|
@query = NullQuery.new
|
24
22
|
@dataloader = GraphQL::Dataloader::NullDataloader.new
|
25
23
|
@schema = NullSchema
|
26
|
-
@warden = NullWarden.new(
|
27
|
-
GraphQL::Filter.new(silence_deprecation_warning: true),
|
28
|
-
context: self,
|
29
|
-
schema: @schema,
|
30
|
-
)
|
24
|
+
@warden = Schema::Warden::NullWarden.new(context: self, schema: @schema)
|
31
25
|
end
|
32
26
|
|
33
|
-
def [](key); end
|
34
|
-
|
35
27
|
def interpreter?
|
36
28
|
true
|
37
29
|
end
|
@@ -39,13 +31,11 @@ module GraphQL
|
|
39
31
|
class << self
|
40
32
|
extend Forwardable
|
41
33
|
|
42
|
-
def [](key); end
|
43
|
-
|
44
34
|
def instance
|
45
35
|
@instance ||= self.new
|
46
36
|
end
|
47
37
|
|
48
|
-
def_delegators :instance, :query, :warden, :schema, :interpreter?, :dataloader
|
38
|
+
def_delegators :instance, :query, :warden, :schema, :interpreter?, :dataloader, :[], :fetch, :dig, :key?
|
49
39
|
end
|
50
40
|
end
|
51
41
|
end
|
data/lib/graphql/query.rb
CHANGED
@@ -87,7 +87,9 @@ module GraphQL
|
|
87
87
|
# Even if `variables: nil` is passed, use an empty hash for simpler logic
|
88
88
|
variables ||= {}
|
89
89
|
@schema = schema
|
90
|
-
|
90
|
+
if only || except
|
91
|
+
merge_filters(except: except, only: only)
|
92
|
+
end
|
91
93
|
@context = schema.context_class.new(query: self, object: root_value, values: context)
|
92
94
|
@warden = warden
|
93
95
|
@subscription_topic = subscription_topic
|
@@ -100,7 +102,7 @@ module GraphQL
|
|
100
102
|
|
101
103
|
# Support `ctx[:backtrace] = true` for wrapping backtraces
|
102
104
|
if context && context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
|
103
|
-
if schema.trace_class <= GraphQL::Tracing::
|
105
|
+
if schema.trace_class <= GraphQL::Tracing::CallLegacyTracers
|
104
106
|
context_tracers += [GraphQL::Backtrace::Tracer]
|
105
107
|
@tracers << GraphQL::Backtrace::Tracer
|
106
108
|
elsif !(current_trace.class <= GraphQL::Backtrace::Trace)
|
@@ -108,8 +110,8 @@ module GraphQL
|
|
108
110
|
end
|
109
111
|
end
|
110
112
|
|
111
|
-
if context_tracers.any? && !(schema.trace_class <= GraphQL::Tracing::
|
112
|
-
raise ArgumentError, "context[:tracers] are not supported without `
|
113
|
+
if context_tracers.any? && !(schema.trace_class <= GraphQL::Tracing::CallLegacyTracers)
|
114
|
+
raise ArgumentError, "context[:tracers] are not supported without `trace_with(GraphQL::Tracing::CallLegacyTracers)` in the schema configuration, please add it."
|
113
115
|
end
|
114
116
|
|
115
117
|
|
@@ -151,11 +153,6 @@ module GraphQL
|
|
151
153
|
|
152
154
|
@result_values = nil
|
153
155
|
@executed = false
|
154
|
-
|
155
|
-
# TODO add a general way to define schema-level filters
|
156
|
-
if @schema.respond_to?(:visible?)
|
157
|
-
merge_filters(only: @schema.method(:visible?))
|
158
|
-
end
|
159
156
|
end
|
160
157
|
|
161
158
|
# If a document was provided to `GraphQL::Schema#execute` instead of the raw query string, we will need to get it from the document
|
@@ -171,7 +168,7 @@ module GraphQL
|
|
171
168
|
|
172
169
|
# @return [GraphQL::Tracing::Trace]
|
173
170
|
def current_trace
|
174
|
-
@current_trace ||= multiplex ? multiplex.current_trace : schema.new_trace(multiplex: multiplex, query: self)
|
171
|
+
@current_trace ||= context[:trace] || (multiplex ? multiplex.current_trace : schema.new_trace(multiplex: multiplex, query: self))
|
175
172
|
end
|
176
173
|
|
177
174
|
def subscription_update?
|
@@ -347,6 +344,7 @@ module GraphQL
|
|
347
344
|
if @prepared_ast
|
348
345
|
raise "Can't add filters after preparing the query"
|
349
346
|
else
|
347
|
+
@filter ||= @schema.default_filter
|
350
348
|
@filter = @filter.merge(only: only, except: except)
|
351
349
|
end
|
352
350
|
nil
|
@@ -361,6 +359,18 @@ module GraphQL
|
|
361
359
|
schema.handle_or_reraise(context, err)
|
362
360
|
end
|
363
361
|
|
362
|
+
def after_lazy(value, &block)
|
363
|
+
if !defined?(@runtime_instance)
|
364
|
+
@runtime_instance = context.namespace(:interpreter_runtime)[:runtime]
|
365
|
+
end
|
366
|
+
|
367
|
+
if @runtime_instance
|
368
|
+
@runtime_instance.minimal_after_lazy(value, &block)
|
369
|
+
else
|
370
|
+
@schema.after_lazy(value, &block)
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
364
374
|
private
|
365
375
|
|
366
376
|
def find_operation(operations, operation_name)
|
@@ -375,7 +385,7 @@ module GraphQL
|
|
375
385
|
|
376
386
|
def prepare_ast
|
377
387
|
@prepared_ast = true
|
378
|
-
@warden ||=
|
388
|
+
@warden ||= @schema.warden_class.new(@filter, schema: @schema, context: @context)
|
379
389
|
parse_error = nil
|
380
390
|
@document ||= begin
|
381
391
|
if query_string
|
@@ -198,8 +198,8 @@ module GraphQL
|
|
198
198
|
|
199
199
|
def statically_coercible?
|
200
200
|
return @statically_coercible if defined?(@statically_coercible)
|
201
|
-
|
202
|
-
@statically_coercible =
|
201
|
+
requires_parent_object = @prepare.is_a?(String) || @prepare.is_a?(Symbol) || @own_validators
|
202
|
+
@statically_coercible = !requires_parent_object
|
203
203
|
end
|
204
204
|
|
205
205
|
# Apply the {prepare} configuration to `value`, using methods from `obj`.
|
@@ -264,7 +264,7 @@ module GraphQL
|
|
264
264
|
|
265
265
|
# If this isn't lazy, then the block returns eagerly and assigns the result here
|
266
266
|
# If it _is_ lazy, then we write the lazy to the hash, then update it later
|
267
|
-
argument_values[arg_key] = context.
|
267
|
+
argument_values[arg_key] = context.query.after_lazy(coerced_value) do |resolved_coerced_value|
|
268
268
|
owner.validate_directive_argument(self, resolved_coerced_value)
|
269
269
|
prepared_value = begin
|
270
270
|
prepare_value(parent_object, resolved_coerced_value, context: context)
|
@@ -281,7 +281,7 @@ module GraphQL
|
|
281
281
|
end
|
282
282
|
|
283
283
|
maybe_loaded_value = loaded_value || prepared_value
|
284
|
-
context.
|
284
|
+
context.query.after_lazy(maybe_loaded_value) do |resolved_loaded_value|
|
285
285
|
# TODO code smell to access such a deeply-nested constant in a distant module
|
286
286
|
argument_values[arg_key] = GraphQL::Execution::Interpreter::ArgumentValue.new(
|
287
287
|
value: resolved_loaded_value,
|
@@ -303,7 +303,7 @@ module GraphQL
|
|
303
303
|
else
|
304
304
|
load_method_owner.public_send(arg_load_method, coerced_value)
|
305
305
|
end
|
306
|
-
context.
|
306
|
+
context.query.after_lazy(custom_loaded_value) do |custom_value|
|
307
307
|
if loads
|
308
308
|
if type.list?
|
309
309
|
loaded_values = custom_value.each_with_index.map { |custom_val, idx|
|
@@ -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
|
@@ -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
@@ -235,7 +235,7 @@ module GraphQL
|
|
235
235
|
@name = -(camelize ? Member::BuildType.camelize(name_s) : name_s)
|
236
236
|
|
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
|
|
@@ -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
|
@@ -211,7 +211,7 @@ module GraphQL
|
|
211
211
|
|
212
212
|
arguments = coerce_arguments(nil, value, ctx)
|
213
213
|
|
214
|
-
ctx.
|
214
|
+
ctx.query.after_lazy(arguments) do |resolved_arguments|
|
215
215
|
if resolved_arguments.is_a?(GraphQL::Error)
|
216
216
|
raise resolved_arguments
|
217
217
|
else
|
@@ -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
|
@@ -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
|
@@ -70,7 +70,7 @@ module GraphQL
|
|
70
70
|
else
|
71
71
|
ready?
|
72
72
|
end
|
73
|
-
context.
|
73
|
+
context.query.after_lazy(ready_val) do |is_ready, ready_early_return|
|
74
74
|
if ready_early_return
|
75
75
|
if is_ready != false
|
76
76
|
raise "Unexpected result from #ready? (expected `true`, `false` or `[false, {...}]`): [#{is_ready.inspect}, #{ready_early_return.inspect}]"
|
@@ -81,7 +81,7 @@ module GraphQL
|
|
81
81
|
# Then call each prepare hook, which may return a different value
|
82
82
|
# for that argument, or may return a lazy object
|
83
83
|
load_arguments_val = load_arguments(args)
|
84
|
-
context.
|
84
|
+
context.query.after_lazy(load_arguments_val) do |loaded_args|
|
85
85
|
@prepared_arguments = loaded_args
|
86
86
|
Schema::Validator.validate!(self.class.validators, object, context, loaded_args, as: @field)
|
87
87
|
# Then call `authorized?`, which may raise or may return a lazy object
|
@@ -90,7 +90,7 @@ module GraphQL
|
|
90
90
|
else
|
91
91
|
authorized?
|
92
92
|
end
|
93
|
-
context.
|
93
|
+
context.query.after_lazy(authorized_val) do |(authorized_result, early_return)|
|
94
94
|
# If the `authorized?` returned two values, `false, early_return`,
|
95
95
|
# then use the early return value instead of continuing
|
96
96
|
if early_return
|
@@ -185,7 +185,7 @@ module GraphQL
|
|
185
185
|
if arg_defn
|
186
186
|
prepped_value = prepared_args[key] = arg_defn.load_and_authorize_value(self, value, context)
|
187
187
|
if context.schema.lazy?(prepped_value)
|
188
|
-
prepare_lazies << context.
|
188
|
+
prepare_lazies << context.query.after_lazy(prepped_value) do |finished_prepped_value|
|
189
189
|
prepared_args[key] = finished_prepped_value
|
190
190
|
end
|
191
191
|
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
|