graphql 2.0.4 → 2.0.7
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/install_generator.rb +1 -1
- data/lib/graphql/execution/interpreter/resolve.rb +7 -0
- data/lib/graphql/execution/lazy.rb +0 -1
- data/lib/graphql/introspection/type_type.rb +1 -1
- data/lib/graphql/introspection.rb +1 -1
- data/lib/graphql/language/printer.rb +9 -5
- data/lib/graphql/pagination/array_connection.rb +4 -2
- data/lib/graphql/schema/field.rb +25 -22
- data/lib/graphql/schema/loader.rb +1 -1
- data/lib/graphql/schema/member/has_arguments.rb +13 -1
- data/lib/graphql/schema/member/has_fields.rb +1 -1
- data/lib/graphql/schema/relay_classic_mutation.rb +4 -0
- data/lib/graphql/schema/resolver.rb +3 -3
- data/lib/graphql/schema/warden.rb +6 -2
- data/lib/graphql/schema.rb +17 -8
- data/lib/graphql/subscriptions.rb +15 -3
- data/lib/graphql/tracing/data_dog_tracing.rb +7 -1
- data/lib/graphql/types/iso_8601_date.rb +4 -1
- data/lib/graphql/types/iso_8601_date_time.rb +1 -0
- data/lib/graphql/types/relay/base_connection.rb +16 -6
- data/lib/graphql/version.rb +1 -1
- metadata +2 -3
- data/lib/graphql/execution/lazy/resolve.rb +0 -91
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b34cec1ffb7358b467f2fb7c00134db084793d9eb1ebe22f38f351435607c9b
|
4
|
+
data.tar.gz: d15754c440968f51715c0a71f3c23ef1c5fd075793c0de11aae6477976b5aa14
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2ef024af0f5e1e261fe7b998e27d664df5f92127ffb2874135a6d7b1662763a4e2661634dd46cc67dd624b9fc8291ce1bd3488a460566bc346f9cd6edc86b43
|
7
|
+
data.tar.gz: 635165d9129c2c49510fd481a2161cf425f91ff016bcdb28b8955d1c818d66885a6f7d90c5210e4433ada541d6e116b3137cb12dbdcc44c32229ac564d266b64
|
@@ -47,7 +47,7 @@ module Graphql
|
|
47
47
|
#
|
48
48
|
# Accept a `--batch` option which adds `GraphQL::Batch` setup.
|
49
49
|
#
|
50
|
-
# Use `--
|
50
|
+
# Use `--skip-graphiql` to skip `graphiql-rails` installation.
|
51
51
|
#
|
52
52
|
# TODO: also add base classes
|
53
53
|
class InstallGenerator < Rails::Generators::Base
|
@@ -59,6 +59,13 @@ module GraphQL
|
|
59
59
|
end
|
60
60
|
|
61
61
|
if next_results.any?
|
62
|
+
# Any pending data loader jobs may populate the
|
63
|
+
# resutl arrays or result hashes accumulated in
|
64
|
+
# `next_results``. Run those **to completion**
|
65
|
+
# before continuing to resolve `next_results`.
|
66
|
+
# (Just `.append_job` doesn't work if any pending
|
67
|
+
# jobs require multiple passes.)
|
68
|
+
dataloader.run
|
62
69
|
dataloader.append_job { resolve(next_results, dataloader) }
|
63
70
|
end
|
64
71
|
|
@@ -267,12 +267,16 @@ module GraphQL
|
|
267
267
|
end
|
268
268
|
|
269
269
|
def print_field_definitions(fields)
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
out
|
270
|
+
if fields.empty?
|
271
|
+
""
|
272
|
+
else
|
273
|
+
out = " {\n".dup
|
274
|
+
fields.each.with_index do |field, i|
|
275
|
+
out << print_description(field, indent: ' ', first_in_block: i == 0)
|
276
|
+
out << " #{print_field_definition(field)}\n"
|
277
|
+
end
|
278
|
+
out << "}"
|
274
279
|
end
|
275
|
-
out << "}"
|
276
280
|
end
|
277
281
|
|
278
282
|
def print_directives(directives)
|
@@ -35,9 +35,11 @@ module GraphQL
|
|
35
35
|
def load_nodes
|
36
36
|
@nodes ||= begin
|
37
37
|
sliced_nodes = if before && after
|
38
|
-
|
38
|
+
end_idx = index_from_cursor(before)-1
|
39
|
+
end_idx < 0 ? [] : items[index_from_cursor(after)..end_idx] || []
|
39
40
|
elsif before
|
40
|
-
|
41
|
+
end_idx = index_from_cursor(before)-2
|
42
|
+
end_idx < 0 ? [] : items[0..end_idx] || []
|
41
43
|
elsif after
|
42
44
|
items[index_from_cursor(after)..-1] || []
|
43
45
|
else
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -28,6 +28,9 @@ module GraphQL
|
|
28
28
|
# @return [String] Method or hash key on the underlying object to look up
|
29
29
|
attr_reader :method_str
|
30
30
|
|
31
|
+
attr_reader :hash_key
|
32
|
+
attr_reader :dig_keys
|
33
|
+
|
31
34
|
# @return [Symbol] The method on the type to look up
|
32
35
|
def resolver_method
|
33
36
|
if @resolver_class
|
@@ -243,14 +246,16 @@ module GraphQL
|
|
243
246
|
end
|
244
247
|
end
|
245
248
|
|
246
|
-
|
247
|
-
method_name = method || hash_key || name_s
|
249
|
+
method_name = method || name_s
|
248
250
|
@dig_keys = dig
|
249
|
-
|
251
|
+
if hash_key
|
252
|
+
@hash_key = hash_key
|
253
|
+
@hash_key_str = hash_key.to_s
|
254
|
+
end
|
250
255
|
|
251
256
|
@method_str = -method_name.to_s
|
252
257
|
@method_sym = method_name.to_sym
|
253
|
-
@resolver_method = resolver_method
|
258
|
+
@resolver_method = (resolver_method || name_s).to_sym
|
254
259
|
@complexity = complexity
|
255
260
|
@return_type_expr = type
|
256
261
|
@return_type_null = if !null.nil?
|
@@ -635,14 +640,15 @@ module GraphQL
|
|
635
640
|
obj = @resolver_class.new(object: obj, context: query_ctx, field: self)
|
636
641
|
end
|
637
642
|
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
643
|
+
inner_object = obj.object
|
644
|
+
|
645
|
+
if defined?(@hash_key)
|
646
|
+
inner_object.fetch(@hash_key) {
|
647
|
+
inner_object[@hash_key_str]
|
648
|
+
}
|
649
|
+
elsif @dig_keys
|
650
|
+
inner_object.dig(*@dig_keys)
|
651
|
+
elsif obj.respond_to?(resolver_method)
|
646
652
|
method_to_call = resolver_method
|
647
653
|
method_receiver = obj
|
648
654
|
# Call the method with kwargs, if there are any
|
@@ -651,30 +657,27 @@ module GraphQL
|
|
651
657
|
else
|
652
658
|
obj.public_send(resolver_method)
|
653
659
|
end
|
654
|
-
elsif
|
655
|
-
inner_object
|
656
|
-
if @dig_keys
|
657
|
-
inner_object.dig(*@dig_keys)
|
658
|
-
elsif inner_object.key?(@method_sym)
|
660
|
+
elsif inner_object.is_a?(Hash)
|
661
|
+
if inner_object.key?(@method_sym)
|
659
662
|
inner_object[@method_sym]
|
660
663
|
else
|
661
664
|
inner_object[@method_str]
|
662
665
|
end
|
663
|
-
elsif
|
666
|
+
elsif inner_object.respond_to?(@method_sym)
|
664
667
|
method_to_call = @method_sym
|
665
668
|
method_receiver = obj.object
|
666
669
|
if ruby_kwargs.any?
|
667
|
-
|
670
|
+
inner_object.public_send(@method_sym, **ruby_kwargs)
|
668
671
|
else
|
669
|
-
|
672
|
+
inner_object.public_send(@method_sym)
|
670
673
|
end
|
671
674
|
else
|
672
675
|
raise <<-ERR
|
673
676
|
Failed to implement #{@owner.graphql_name}.#{@name}, tried:
|
674
677
|
|
675
678
|
- `#{obj.class}##{resolver_method}`, which did not exist
|
676
|
-
- `#{
|
677
|
-
- Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{
|
679
|
+
- `#{inner_object.class}##{@method_sym}`, which did not exist
|
680
|
+
- Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{inner_object}`, but it wasn't a Hash
|
678
681
|
|
679
682
|
To implement this field, define one of the methods above (and check for typos)
|
680
683
|
ERR
|
@@ -148,7 +148,19 @@ module GraphQL
|
|
148
148
|
end
|
149
149
|
elsif defined?(@resolver_class) && @resolver_class
|
150
150
|
all_defns = {}
|
151
|
-
|
151
|
+
@resolver_class.all_field_argument_definitions.each do |arg_defn|
|
152
|
+
key = arg_defn.graphql_name
|
153
|
+
case (current_value = all_defns[key])
|
154
|
+
when nil
|
155
|
+
all_defns[key] = arg_defn
|
156
|
+
when Array
|
157
|
+
current_value << arg_defn
|
158
|
+
when GraphQL::Schema::Argument
|
159
|
+
all_defns[key] = [current_value, arg_defn]
|
160
|
+
else
|
161
|
+
raise "Invariant: Unexpected argument definition, #{current_value.class}: #{current_value.inspect}"
|
162
|
+
end
|
163
|
+
end
|
152
164
|
all_defns.merge!(own_arguments)
|
153
165
|
else
|
154
166
|
all_defns = own_arguments
|
@@ -72,7 +72,7 @@ module GraphQL
|
|
72
72
|
def add_field(field_defn, method_conflict_warning: field_defn.method_conflict_warning?)
|
73
73
|
# Check that `field_defn.original_name` equals `resolver_method` and `method_sym` --
|
74
74
|
# that shows that no override value was given manually.
|
75
|
-
if method_conflict_warning && CONFLICT_FIELD_NAMES.include?(field_defn.resolver_method) && field_defn.original_name == field_defn.resolver_method && field_defn.original_name == field_defn.method_sym
|
75
|
+
if method_conflict_warning && CONFLICT_FIELD_NAMES.include?(field_defn.resolver_method) && field_defn.original_name == field_defn.resolver_method && field_defn.original_name == field_defn.method_sym && field_defn.hash_key.nil? && field_defn.dig_keys.nil?
|
76
76
|
warn(conflict_field_name_warning(field_defn))
|
77
77
|
end
|
78
78
|
prev_defn = own_fields[field_defn.name]
|
@@ -92,6 +92,10 @@ module GraphQL
|
|
92
92
|
dummy.own_arguments
|
93
93
|
end
|
94
94
|
|
95
|
+
def all_field_argument_definitions
|
96
|
+
dummy.all_argument_definitions
|
97
|
+
end
|
98
|
+
|
95
99
|
# Also apply this argument to the input type:
|
96
100
|
def argument(*args, own_argument: false, **kwargs, &block)
|
97
101
|
it = input_type # make sure any inherited arguments are already added to it
|
@@ -73,7 +73,7 @@ module GraphQL
|
|
73
73
|
context.schema.after_lazy(ready_val) do |is_ready, ready_early_return|
|
74
74
|
if ready_early_return
|
75
75
|
if is_ready != false
|
76
|
-
raise "Unexpected result from #ready? (expected `true`, `false` or `[false, {...}]`): [#{
|
76
|
+
raise "Unexpected result from #ready? (expected `true`, `false` or `[false, {...}]`): [#{is_ready.inspect}, #{ready_early_return.inspect}]"
|
77
77
|
else
|
78
78
|
ready_early_return
|
79
79
|
end
|
@@ -216,8 +216,8 @@ module GraphQL
|
|
216
216
|
get_argument(name, context)
|
217
217
|
end
|
218
218
|
|
219
|
-
def
|
220
|
-
|
219
|
+
def all_field_argument_definitions
|
220
|
+
all_argument_definitions
|
221
221
|
end
|
222
222
|
|
223
223
|
# Default `:resolve` set below.
|
@@ -55,7 +55,9 @@ module GraphQL
|
|
55
55
|
if visible_item.nil?
|
56
56
|
visible_item = item
|
57
57
|
else
|
58
|
-
raise
|
58
|
+
raise DuplicateNamesError.new(
|
59
|
+
duplicated_name: item.path, duplicated_definition_1: visible_item.inspect, duplicated_definition_2: item.inspect
|
60
|
+
)
|
59
61
|
end
|
60
62
|
end
|
61
63
|
end
|
@@ -362,7 +364,9 @@ module GraphQL
|
|
362
364
|
if @reachable_type_set.add?(type)
|
363
365
|
type_by_name = rt_hash[type.graphql_name] ||= type
|
364
366
|
if type_by_name != type
|
365
|
-
raise DuplicateNamesError
|
367
|
+
raise DuplicateNamesError.new(
|
368
|
+
duplicated_name: type.graphql_name, duplicated_definition_1: type.inspect, duplicated_definition_2: type_by_name.inspect
|
369
|
+
)
|
366
370
|
end
|
367
371
|
if type.kind.input_object?
|
368
372
|
# recurse into visible arguments
|
data/lib/graphql/schema.rb
CHANGED
@@ -73,14 +73,16 @@ module GraphQL
|
|
73
73
|
extend GraphQL::Schema::Member::HasAstNode
|
74
74
|
extend GraphQL::Schema::FindInheritedValue
|
75
75
|
|
76
|
-
class
|
77
|
-
|
78
|
-
|
76
|
+
class DuplicateNamesError < GraphQL::Error
|
77
|
+
attr_reader :duplicated_name
|
78
|
+
def initialize(duplicated_name:, duplicated_definition_1:, duplicated_definition_2:)
|
79
|
+
@duplicated_name = duplicated_name
|
80
|
+
super(
|
81
|
+
"Found two visible definitions for `#{duplicated_name}`: #{duplicated_definition_1}, #{duplicated_definition_2}"
|
82
|
+
)
|
79
83
|
end
|
80
84
|
end
|
81
85
|
|
82
|
-
class DuplicateNamesError < GraphQL::Error; end
|
83
|
-
|
84
86
|
class UnresolvedLateBoundTypeError < GraphQL::Error
|
85
87
|
attr_reader :type
|
86
88
|
def initialize(type:)
|
@@ -225,7 +227,9 @@ module GraphQL
|
|
225
227
|
if visible_t.nil?
|
226
228
|
visible_t = t
|
227
229
|
else
|
228
|
-
raise DuplicateNamesError
|
230
|
+
raise DuplicateNamesError.new(
|
231
|
+
duplicated_name: k, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
|
232
|
+
)
|
229
233
|
end
|
230
234
|
end
|
231
235
|
end
|
@@ -252,7 +256,9 @@ module GraphQL
|
|
252
256
|
if visible_t.nil?
|
253
257
|
visible_t = t
|
254
258
|
else
|
255
|
-
raise DuplicateNamesError
|
259
|
+
raise DuplicateNamesError.new(
|
260
|
+
duplicated_name: type_name, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
|
261
|
+
)
|
256
262
|
end
|
257
263
|
end
|
258
264
|
end
|
@@ -932,6 +938,7 @@ module GraphQL
|
|
932
938
|
{
|
933
939
|
backtrace: ctx[:backtrace],
|
934
940
|
tracers: ctx[:tracers],
|
941
|
+
dataloader: ctx[:dataloader],
|
935
942
|
}
|
936
943
|
else
|
937
944
|
{}
|
@@ -976,7 +983,9 @@ module GraphQL
|
|
976
983
|
if !defined?(@subscription_extension_added) && subscription && self.subscriptions
|
977
984
|
@subscription_extension_added = true
|
978
985
|
subscription.all_field_definitions.each do |field|
|
979
|
-
field.
|
986
|
+
if !field.extensions.any? { |ext| ext.is_a?(Subscriptions::DefaultSubscriptionResolveExtension) }
|
987
|
+
field.extension(Subscriptions::DefaultSubscriptionResolveExtension)
|
988
|
+
end
|
980
989
|
end
|
981
990
|
end
|
982
991
|
end
|
@@ -39,12 +39,14 @@ module GraphQL
|
|
39
39
|
end
|
40
40
|
|
41
41
|
# @param schema [Class] the GraphQL schema this manager belongs to
|
42
|
-
|
42
|
+
# @param validate_update [Boolean] If false, then validation is skipped when executing updates
|
43
|
+
def initialize(schema:, validate_update: true, broadcast: false, default_broadcastable: false, **rest)
|
43
44
|
if broadcast
|
44
45
|
schema.query_analyzer(Subscriptions::BroadcastAnalyzer)
|
45
46
|
end
|
46
47
|
@default_broadcastable = default_broadcastable
|
47
48
|
@schema = schema
|
49
|
+
@validate_update = validate_update
|
48
50
|
end
|
49
51
|
|
50
52
|
# @return [Boolean] Used when fields don't have `broadcastable:` explicitly set
|
@@ -117,14 +119,16 @@ module GraphQL
|
|
117
119
|
variables = query_data.fetch(:variables)
|
118
120
|
context = query_data.fetch(:context)
|
119
121
|
operation_name = query_data.fetch(:operation_name)
|
120
|
-
|
122
|
+
execute_options = {
|
121
123
|
query: query_string,
|
122
124
|
context: context,
|
123
125
|
subscription_topic: event.topic,
|
124
126
|
operation_name: operation_name,
|
125
127
|
variables: variables,
|
126
128
|
root_value: object,
|
127
|
-
|
129
|
+
}
|
130
|
+
execute_options[:validate] = validate_update?(**execute_options)
|
131
|
+
result = @schema.execute(**execute_options)
|
128
132
|
subscriptions_context = result.context.namespace(:subscriptions)
|
129
133
|
if subscriptions_context[:no_update]
|
130
134
|
result = nil
|
@@ -142,6 +146,14 @@ module GraphQL
|
|
142
146
|
result
|
143
147
|
end
|
144
148
|
|
149
|
+
# Define this method to customize whether to validate
|
150
|
+
# this subscription when executing an update.
|
151
|
+
#
|
152
|
+
# @return [Boolean] defaults to `true`, or false if `validate: false` is provided.
|
153
|
+
def validate_update?(query:, context:, root_value:, subscription_topic:, operation_name:, variables:)
|
154
|
+
@validate_update
|
155
|
+
end
|
156
|
+
|
145
157
|
# Run the update query for this subscription and deliver it
|
146
158
|
# @see {#execute_update}
|
147
159
|
# @see {#deliver}
|
@@ -17,15 +17,21 @@ module GraphQL
|
|
17
17
|
def platform_trace(platform_key, key, data)
|
18
18
|
tracer.trace(platform_key, service: service_name) do |span|
|
19
19
|
span.span_type = 'custom'
|
20
|
+
if defined?(Datadog::Tracing::Metadata::Ext) # Introduced in ddtrace 1.0
|
21
|
+
span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT, 'graphql')
|
22
|
+
span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION, key)
|
23
|
+
end
|
20
24
|
|
21
25
|
if key == 'execute_multiplex'
|
22
26
|
operations = data[:multiplex].queries.map(&:selected_operation_name).join(', ')
|
23
|
-
|
27
|
+
|
28
|
+
resource = if operations.empty?
|
24
29
|
first_query = data[:multiplex].queries.first
|
25
30
|
fallback_transaction_name(first_query && first_query.context)
|
26
31
|
else
|
27
32
|
operations
|
28
33
|
end
|
34
|
+
span.resource = resource if resource
|
29
35
|
|
30
36
|
# For top span of query, set the analytics sample rate tag, if available.
|
31
37
|
if analytics_enabled?
|
@@ -14,6 +14,7 @@ module GraphQL
|
|
14
14
|
# own Date type.
|
15
15
|
class ISO8601Date < GraphQL::Schema::Scalar
|
16
16
|
description "An ISO 8601-encoded date"
|
17
|
+
specified_by_url "https://tools.ietf.org/html/rfc3339"
|
17
18
|
|
18
19
|
# @param value [Date,Time,DateTime,String]
|
19
20
|
# @return [String]
|
@@ -22,7 +23,7 @@ module GraphQL
|
|
22
23
|
end
|
23
24
|
|
24
25
|
# @param str_value [String, Date, DateTime, Time]
|
25
|
-
# @return [Date]
|
26
|
+
# @return [Date, nil]
|
26
27
|
def self.coerce_input(value, ctx)
|
27
28
|
if value.is_a?(::Date)
|
28
29
|
value
|
@@ -30,6 +31,8 @@ module GraphQL
|
|
30
31
|
value.to_date
|
31
32
|
elsif value.is_a?(::Time)
|
32
33
|
value.to_date
|
34
|
+
elsif value.nil?
|
35
|
+
nil
|
33
36
|
else
|
34
37
|
Date.iso8601(value)
|
35
38
|
end
|
@@ -17,6 +17,7 @@ module GraphQL
|
|
17
17
|
# own DateTime type.
|
18
18
|
class ISO8601DateTime < GraphQL::Schema::Scalar
|
19
19
|
description "An ISO 8601-encoded datetime"
|
20
|
+
specified_by_url "https://tools.ietf.org/html/rfc3339"
|
20
21
|
|
21
22
|
# It's not compatible with Rails' default,
|
22
23
|
# i.e. ActiveSupport::JSON::Encoder.time_precision (3 by default)
|
@@ -10,6 +10,8 @@ module GraphQL
|
|
10
10
|
# so you can extend your own `BaseObject` instead of `GraphQL::Schema::Object`.
|
11
11
|
#
|
12
12
|
# @example Implementation a connection and edge
|
13
|
+
# class BaseObject < GraphQL::Schema::Object; end
|
14
|
+
#
|
13
15
|
# # Given some object in your app ...
|
14
16
|
# class Types::Post < BaseObject
|
15
17
|
# end
|
@@ -20,14 +22,22 @@ module GraphQL
|
|
20
22
|
#
|
21
23
|
# # Then extend them for the object in your app
|
22
24
|
# class Types::PostEdge < Types::BaseEdge
|
23
|
-
# node_type
|
25
|
+
# node_type Types::Post
|
24
26
|
# end
|
27
|
+
#
|
25
28
|
# class Types::PostConnection < Types::BaseConnection
|
26
|
-
# edge_type
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
29
|
+
# edge_type Types::PostEdge,
|
30
|
+
# edges_nullable: true,
|
31
|
+
# edge_nullable: true,
|
32
|
+
# node_nullable: true,
|
33
|
+
# nodes_field: true
|
34
|
+
#
|
35
|
+
# # Alternatively, you can call the class methods followed by your edge type
|
36
|
+
# # edges_nullable true
|
37
|
+
# # edge_nullable true
|
38
|
+
# # nodes_nullable true
|
39
|
+
# # has_nodes_field true
|
40
|
+
# # edge_type Types::PostEdge
|
31
41
|
# end
|
32
42
|
#
|
33
43
|
# @see Relay::BaseEdge for edge types
|
data/lib/graphql/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-04-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-ips
|
@@ -314,7 +314,6 @@ files:
|
|
314
314
|
- lib/graphql/execution/interpreter/runtime.rb
|
315
315
|
- lib/graphql/execution/lazy.rb
|
316
316
|
- lib/graphql/execution/lazy/lazy_method_map.rb
|
317
|
-
- lib/graphql/execution/lazy/resolve.rb
|
318
317
|
- lib/graphql/execution/lookahead.rb
|
319
318
|
- lib/graphql/execution/multiplex.rb
|
320
319
|
- lib/graphql/execution_error.rb
|
@@ -1,91 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module GraphQL
|
3
|
-
module Execution
|
4
|
-
class Lazy
|
5
|
-
# Helpers for dealing with data structures containing {Lazy} instances
|
6
|
-
# @api private
|
7
|
-
module Resolve
|
8
|
-
# Mutate `value`, replacing {Lazy} instances in place with their resolved values
|
9
|
-
# @return [void]
|
10
|
-
|
11
|
-
# This object can be passed like an array, but it doesn't allocate an
|
12
|
-
# array until it's used.
|
13
|
-
#
|
14
|
-
# There's one crucial difference: you have to _capture_ the result
|
15
|
-
# of `#<<`. (This _works_ with arrays but isn't required, since it has a side-effect.)
|
16
|
-
# @api private
|
17
|
-
module NullAccumulator
|
18
|
-
def self.<<(item)
|
19
|
-
[item]
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.empty?
|
23
|
-
true
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.resolve(value)
|
28
|
-
lazies = resolve_in_place(value)
|
29
|
-
deep_sync(lazies)
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.resolve_in_place(value)
|
33
|
-
acc = each_lazy(NullAccumulator, value)
|
34
|
-
|
35
|
-
if acc.empty?
|
36
|
-
Lazy::NullResult
|
37
|
-
else
|
38
|
-
Lazy.new {
|
39
|
-
acc.each_with_index { |ctx, idx|
|
40
|
-
acc[idx] = ctx.value.value
|
41
|
-
}
|
42
|
-
resolve_in_place(acc)
|
43
|
-
}
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# If `value` is a collection,
|
48
|
-
# add any {Lazy} instances in the collection
|
49
|
-
# to `acc`
|
50
|
-
# @return [void]
|
51
|
-
def self.each_lazy(acc, value)
|
52
|
-
case value
|
53
|
-
when Hash
|
54
|
-
value.each do |key, field_result|
|
55
|
-
acc = each_lazy(acc, field_result)
|
56
|
-
end
|
57
|
-
when Array
|
58
|
-
value.each do |field_result|
|
59
|
-
acc = each_lazy(acc, field_result)
|
60
|
-
end
|
61
|
-
when Query::Context::SharedMethods
|
62
|
-
field_value = value.value
|
63
|
-
case field_value
|
64
|
-
when Lazy
|
65
|
-
acc = acc << value
|
66
|
-
when Enumerable # shortcut for Hash & Array
|
67
|
-
acc = each_lazy(acc, field_value)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
acc
|
72
|
-
end
|
73
|
-
|
74
|
-
# Traverse `val`, triggering resolution for each {Lazy}.
|
75
|
-
# These {Lazy}s are expected to mutate their owner data structures
|
76
|
-
# during resolution! (They're created with the `.then` calls in `resolve_in_place`).
|
77
|
-
# @return [void]
|
78
|
-
def self.deep_sync(val)
|
79
|
-
case val
|
80
|
-
when Lazy
|
81
|
-
deep_sync(val.value)
|
82
|
-
when Array
|
83
|
-
val.each { |v| deep_sync(v.value) }
|
84
|
-
when Hash
|
85
|
-
val.each { |k, v| deep_sync(v.value) }
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|