graphql 2.0.0 → 2.0.3
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/analysis/ast/max_query_complexity.rb +0 -1
- data/lib/graphql/dataloader/null_dataloader.rb +3 -1
- data/lib/graphql/execution/errors.rb +12 -74
- data/lib/graphql/execution/interpreter/runtime.rb +35 -38
- data/lib/graphql/query/context.rb +96 -9
- data/lib/graphql/query/input_validation_result.rb +10 -1
- data/lib/graphql/query/null_context.rb +0 -3
- data/lib/graphql/query.rb +2 -5
- data/lib/graphql/relay/range_add.rb +9 -16
- data/lib/graphql/schema/addition.rb +5 -0
- data/lib/graphql/schema/argument.rb +13 -4
- data/lib/graphql/schema/enum.rb +3 -5
- data/lib/graphql/schema/field.rb +164 -130
- data/lib/graphql/schema/input_object.rb +12 -12
- data/lib/graphql/schema/list.rb +2 -1
- data/lib/graphql/schema/member/has_arguments.rb +36 -6
- data/lib/graphql/schema/member/has_directives.rb +1 -1
- data/lib/graphql/schema/member/has_interfaces.rb +1 -1
- data/lib/graphql/schema/member/relay_shortcuts.rb +28 -2
- data/lib/graphql/schema/member/validates_input.rb +2 -2
- data/lib/graphql/schema/object.rb +14 -9
- data/lib/graphql/schema/relay_classic_mutation.rb +32 -14
- data/lib/graphql/schema/resolver/has_payload_type.rb +11 -1
- data/lib/graphql/schema/resolver.rb +23 -45
- data/lib/graphql/schema/scalar.rb +7 -7
- data/lib/graphql/schema/subscription.rb +0 -7
- data/lib/graphql/schema/warden.rb +1 -1
- data/lib/graphql/schema.rb +35 -6
- data/lib/graphql/subscriptions.rb +10 -3
- data/lib/graphql/tracing/data_dog_tracing.rb +3 -1
- data/lib/graphql/types/relay/connection_behaviors.rb +0 -16
- data/lib/graphql/version.rb +1 -1
- metadata +6 -7
- data/lib/graphql/query/literal_input.rb +0 -131
@@ -8,7 +8,15 @@ module GraphQL
|
|
8
8
|
if new_edge_type_class
|
9
9
|
@edge_type_class = new_edge_type_class
|
10
10
|
else
|
11
|
-
|
11
|
+
# Don't call `ancestor.edge_type_class`
|
12
|
+
# because we don't want a fallback from any ancestors --
|
13
|
+
# only apply the fallback if _no_ ancestor has a configured value!
|
14
|
+
for ancestor in self.ancestors
|
15
|
+
if ancestor.respond_to?(:configured_edge_type_class, true) && (etc = ancestor.configured_edge_type_class)
|
16
|
+
return etc
|
17
|
+
end
|
18
|
+
end
|
19
|
+
Types::Relay::BaseEdge
|
12
20
|
end
|
13
21
|
end
|
14
22
|
|
@@ -16,7 +24,15 @@ module GraphQL
|
|
16
24
|
if new_connection_type_class
|
17
25
|
@connection_type_class = new_connection_type_class
|
18
26
|
else
|
19
|
-
|
27
|
+
# Don't call `ancestor.connection_type_class`
|
28
|
+
# because we don't want a fallback from any ancestors --
|
29
|
+
# only apply the fallback if _no_ ancestor has a configured value!
|
30
|
+
for ancestor in self.ancestors
|
31
|
+
if ancestor.respond_to?(:configured_connection_type_class, true) && (ctc = ancestor.configured_connection_type_class)
|
32
|
+
return ctc
|
33
|
+
end
|
34
|
+
end
|
35
|
+
Types::Relay::BaseConnection
|
20
36
|
end
|
21
37
|
end
|
22
38
|
|
@@ -41,6 +57,16 @@ module GraphQL
|
|
41
57
|
end
|
42
58
|
end
|
43
59
|
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
def configured_connection_type_class
|
64
|
+
@connection_type_class
|
65
|
+
end
|
66
|
+
|
67
|
+
def configured_edge_type_class
|
68
|
+
@edge_type_class
|
69
|
+
end
|
44
70
|
end
|
45
71
|
end
|
46
72
|
end
|
@@ -10,9 +10,9 @@ module GraphQL
|
|
10
10
|
|
11
11
|
def validate_input(val, ctx)
|
12
12
|
if val.nil?
|
13
|
-
|
13
|
+
Query::InputValidationResult::VALID
|
14
14
|
else
|
15
|
-
validate_non_null_input(val, ctx)
|
15
|
+
validate_non_null_input(val, ctx) || Query::InputValidationResult::VALID
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -51,12 +51,12 @@ module GraphQL
|
|
51
51
|
trace_payload = { context: context, type: self, object: object, path: context[:current_path] }
|
52
52
|
|
53
53
|
maybe_lazy_auth_val = context.query.trace("authorized", trace_payload) do
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
54
|
+
begin
|
55
|
+
authorized?(object, context)
|
56
|
+
rescue GraphQL::UnauthorizedError => err
|
57
|
+
context.schema.unauthorized_object(err)
|
58
|
+
rescue StandardError => err
|
59
|
+
context.query.handle_or_reraise(err)
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -98,9 +98,14 @@ module GraphQL
|
|
98
98
|
class << self
|
99
99
|
# Set up a type-specific invalid null error to use when this object's non-null fields wrongly return `nil`.
|
100
100
|
# It should help with debugging and bug tracker integrations.
|
101
|
-
def
|
102
|
-
|
103
|
-
|
101
|
+
def const_missing(name)
|
102
|
+
if name == :InvalidNullError
|
103
|
+
custom_err_class = GraphQL::InvalidNullError.subclass_for(self)
|
104
|
+
const_set(:InvalidNullError, custom_err_class)
|
105
|
+
custom_err_class
|
106
|
+
else
|
107
|
+
super
|
108
|
+
end
|
104
109
|
end
|
105
110
|
|
106
111
|
def kind
|
@@ -70,11 +70,32 @@ module GraphQL
|
|
70
70
|
end
|
71
71
|
|
72
72
|
class << self
|
73
|
+
def dummy
|
74
|
+
@dummy ||= begin
|
75
|
+
d = Class.new(GraphQL::Schema::Resolver)
|
76
|
+
d.argument_class(self.argument_class)
|
77
|
+
# TODO make this lazier?
|
78
|
+
d.argument(:input, input_type, description: "Parameters for #{self.graphql_name}")
|
79
|
+
d
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def field_arguments(context = GraphQL::Query::NullContext)
|
84
|
+
dummy.arguments(context)
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_field_argument(name, context = GraphQL::Query::NullContext)
|
88
|
+
dummy.get_argument(name, context)
|
89
|
+
end
|
90
|
+
|
91
|
+
def own_field_arguments
|
92
|
+
dummy.own_arguments
|
93
|
+
end
|
73
94
|
|
74
95
|
# Also apply this argument to the input type:
|
75
|
-
def argument(*args, **kwargs, &block)
|
96
|
+
def argument(*args, own_argument: false, **kwargs, &block)
|
76
97
|
it = input_type # make sure any inherited arguments are already added to it
|
77
|
-
arg = super
|
98
|
+
arg = super(*args, **kwargs, &block)
|
78
99
|
|
79
100
|
# This definition might be overriding something inherited;
|
80
101
|
# if it is, remove the inherited definition so it's not confused at runtime as having multiple definitions
|
@@ -114,15 +135,6 @@ module GraphQL
|
|
114
135
|
@input_type ||= generate_input_type
|
115
136
|
end
|
116
137
|
|
117
|
-
# Extend {Schema::Mutation.field_options} to add the `input` argument
|
118
|
-
def field_options
|
119
|
-
sig = super
|
120
|
-
# Arguments were added at the root, but they should be nested
|
121
|
-
sig[:arguments].clear
|
122
|
-
sig[:arguments][:input] = { type: input_type, required: true, description: "Parameters for #{graphql_name}" }
|
123
|
-
sig
|
124
|
-
end
|
125
|
-
|
126
138
|
private
|
127
139
|
|
128
140
|
# Generate the input type for the `input:` argument
|
@@ -130,11 +142,17 @@ module GraphQL
|
|
130
142
|
# @return [Class] a subclass of {.input_object_class}
|
131
143
|
def generate_input_type
|
132
144
|
mutation_args = all_argument_definitions
|
133
|
-
mutation_name = graphql_name
|
134
145
|
mutation_class = self
|
135
146
|
Class.new(input_object_class) do
|
136
|
-
|
137
|
-
|
147
|
+
class << self
|
148
|
+
def default_graphql_name
|
149
|
+
"#{self.mutation.graphql_name}Input"
|
150
|
+
end
|
151
|
+
|
152
|
+
def description(new_desc = nil)
|
153
|
+
super || "Autogenerated input type of #{self.mutation.graphql_name}"
|
154
|
+
end
|
155
|
+
end
|
138
156
|
mutation(mutation_class)
|
139
157
|
# these might be inherited:
|
140
158
|
mutation_args.each do |arg|
|
@@ -20,7 +20,17 @@ module GraphQL
|
|
20
20
|
@payload_type ||= generate_payload_type
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
def type(new_type = nil, null: nil)
|
24
|
+
if new_type
|
25
|
+
payload_type(new_type)
|
26
|
+
if !null.nil?
|
27
|
+
self.null(null)
|
28
|
+
end
|
29
|
+
else
|
30
|
+
super()
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
24
34
|
alias :type_expr :payload_type
|
25
35
|
|
26
36
|
def field_class(new_class = nil)
|
@@ -15,8 +15,6 @@ module GraphQL
|
|
15
15
|
#
|
16
16
|
# A resolver's configuration may be overridden with other keywords in the `field(...)` call.
|
17
17
|
#
|
18
|
-
# See the {.field_options} to see how a Resolver becomes a set of field configuration options.
|
19
|
-
#
|
20
18
|
# @see {GraphQL::Schema::Mutation} for a concrete subclass of `Resolver`.
|
21
19
|
# @see {GraphQL::Function} `Resolver` is a replacement for `GraphQL::Function`
|
22
20
|
class Resolver
|
@@ -210,6 +208,18 @@ module GraphQL
|
|
210
208
|
end
|
211
209
|
|
212
210
|
class << self
|
211
|
+
def field_arguments(context = GraphQL::Query::NullContext)
|
212
|
+
arguments(context)
|
213
|
+
end
|
214
|
+
|
215
|
+
def get_field_argument(name, context = GraphQL::Query::NullContext)
|
216
|
+
get_argument(name, context)
|
217
|
+
end
|
218
|
+
|
219
|
+
def own_field_arguments
|
220
|
+
own_arguments
|
221
|
+
end
|
222
|
+
|
213
223
|
# Default `:resolve` set below.
|
214
224
|
# @return [Symbol] The method to call on instances of this object to resolve the field
|
215
225
|
def resolve_method(new_method = nil)
|
@@ -242,6 +252,14 @@ module GraphQL
|
|
242
252
|
@null.nil? ? (superclass.respond_to?(:null) ? superclass.null : true) : @null
|
243
253
|
end
|
244
254
|
|
255
|
+
def resolver_method(new_method_name = nil)
|
256
|
+
if new_method_name
|
257
|
+
@resolver_method = new_method_name
|
258
|
+
else
|
259
|
+
@resolver_method || :resolve_with_support
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
245
263
|
# Call this method to get the return type of the field,
|
246
264
|
# or use it as a configuration method to assign a return type
|
247
265
|
# instead of generating one.
|
@@ -257,8 +275,8 @@ module GraphQL
|
|
257
275
|
@type_expr = new_type
|
258
276
|
@null = null
|
259
277
|
else
|
260
|
-
if
|
261
|
-
GraphQL::Schema::Member::BuildType.parse_type(
|
278
|
+
if type_expr
|
279
|
+
GraphQL::Schema::Member::BuildType.parse_type(type_expr, null: self.null)
|
262
280
|
elsif superclass.respond_to?(:type)
|
263
281
|
superclass.type
|
264
282
|
else
|
@@ -307,47 +325,7 @@ module GraphQL
|
|
307
325
|
|
308
326
|
# @return [Boolean] `true` if this resolver or a superclass has an assigned `max_page_size`
|
309
327
|
def has_max_page_size?
|
310
|
-
defined?(@max_page_size) || (superclass.respond_to?(:has_max_page_size?) && superclass.has_max_page_size?)
|
311
|
-
end
|
312
|
-
|
313
|
-
def field_options
|
314
|
-
|
315
|
-
all_args = {}
|
316
|
-
all_argument_definitions.each do |arg|
|
317
|
-
if (prev_entry = all_args[arg.graphql_name])
|
318
|
-
if prev_entry.is_a?(Array)
|
319
|
-
prev_entry << arg
|
320
|
-
else
|
321
|
-
all_args[arg.graphql_name] = [prev_entry, arg]
|
322
|
-
end
|
323
|
-
else
|
324
|
-
all_args[arg.graphql_name] = arg
|
325
|
-
end
|
326
|
-
end
|
327
|
-
|
328
|
-
field_opts = {
|
329
|
-
type: type_expr,
|
330
|
-
description: description,
|
331
|
-
extras: extras,
|
332
|
-
resolver_method: :resolve_with_support,
|
333
|
-
resolver_class: self,
|
334
|
-
arguments: all_args,
|
335
|
-
null: null,
|
336
|
-
complexity: complexity,
|
337
|
-
broadcastable: broadcastable?,
|
338
|
-
}
|
339
|
-
|
340
|
-
# If there aren't any, then the returned array is `[].freeze`,
|
341
|
-
# but passing that along breaks some user code.
|
342
|
-
if (exts = extensions).any?
|
343
|
-
field_opts[:extensions] = exts
|
344
|
-
end
|
345
|
-
|
346
|
-
if has_max_page_size?
|
347
|
-
field_opts[:max_page_size] = max_page_size
|
348
|
-
end
|
349
|
-
|
350
|
-
field_opts
|
328
|
+
(!!defined?(@max_page_size)) || (superclass.respond_to?(:has_max_page_size?) && superclass.has_max_page_size?)
|
351
329
|
end
|
352
330
|
|
353
331
|
# A non-normalized type configuration, without `null` applied
|
@@ -41,13 +41,12 @@ module GraphQL
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def validate_non_null_input(value, ctx)
|
44
|
-
result = Query::InputValidationResult.new
|
45
44
|
coerced_result = begin
|
46
|
-
ctx
|
47
|
-
coerce_input(value, ctx)
|
48
|
-
end
|
45
|
+
coerce_input(value, ctx)
|
49
46
|
rescue GraphQL::CoercionError => err
|
50
47
|
err
|
48
|
+
rescue StandardError => err
|
49
|
+
ctx.query.handle_or_reraise(err)
|
51
50
|
end
|
52
51
|
|
53
52
|
if coerced_result.nil?
|
@@ -56,11 +55,12 @@ module GraphQL
|
|
56
55
|
else
|
57
56
|
" #{GraphQL::Language.serialize(value)}"
|
58
57
|
end
|
59
|
-
|
58
|
+
Query::InputValidationResult.from_problem("Could not coerce value#{str_value} to #{graphql_name}")
|
60
59
|
elsif coerced_result.is_a?(GraphQL::CoercionError)
|
61
|
-
|
60
|
+
Query::InputValidationResult.from_problem(coerced_result.message, message: coerced_result.message, extensions: coerced_result.extensions)
|
61
|
+
else
|
62
|
+
nil
|
62
63
|
end
|
63
|
-
result
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
@@ -143,13 +143,6 @@ module GraphQL
|
|
143
143
|
def self.topic_for(arguments:, field:, scope:)
|
144
144
|
Subscriptions::Serialize.dump_recursive([scope, field.graphql_name, arguments])
|
145
145
|
end
|
146
|
-
|
147
|
-
# Overriding Resolver#field_options to include subscription_scope
|
148
|
-
def self.field_options
|
149
|
-
super.merge(
|
150
|
-
subscription_scope: subscription_scope
|
151
|
-
)
|
152
|
-
end
|
153
146
|
end
|
154
147
|
end
|
155
148
|
end
|
@@ -10,7 +10,7 @@ module GraphQL
|
|
10
10
|
# should go through a warden. If you access the schema directly,
|
11
11
|
# you may show a client something that it shouldn't be allowed to see.
|
12
12
|
#
|
13
|
-
# @example
|
13
|
+
# @example Hiding private fields
|
14
14
|
# private_members = -> (member, ctx) { member.metadata[:private] }
|
15
15
|
# result = Schema.execute(query_string, except: private_members)
|
16
16
|
#
|
data/lib/graphql/schema.rb
CHANGED
@@ -693,7 +693,41 @@ module GraphQL
|
|
693
693
|
|
694
694
|
def rescue_from(*err_classes, &handler_block)
|
695
695
|
err_classes.each do |err_class|
|
696
|
-
|
696
|
+
Execution::Errors.register_rescue_from(err_class, error_handlers[:subclass_handlers], handler_block)
|
697
|
+
end
|
698
|
+
end
|
699
|
+
|
700
|
+
NEW_HANDLER_HASH = ->(h, k) {
|
701
|
+
h[k] = {
|
702
|
+
class: k,
|
703
|
+
handler: nil,
|
704
|
+
subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
|
705
|
+
}
|
706
|
+
}
|
707
|
+
|
708
|
+
def error_handlers
|
709
|
+
@error_handlers ||= {
|
710
|
+
class: nil,
|
711
|
+
handler: nil,
|
712
|
+
subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
|
713
|
+
}
|
714
|
+
end
|
715
|
+
|
716
|
+
# @api private
|
717
|
+
def handle_or_reraise(context, err)
|
718
|
+
handler = Execution::Errors.find_handler_for(self, err.class)
|
719
|
+
if handler
|
720
|
+
runtime_info = context.namespace(:interpreter) || {}
|
721
|
+
obj = runtime_info[:current_object]
|
722
|
+
args = runtime_info[:current_arguments]
|
723
|
+
args = args && args.keyword_arguments
|
724
|
+
field = runtime_info[:current_field]
|
725
|
+
if obj.is_a?(GraphQL::Schema::Object)
|
726
|
+
obj = obj.object
|
727
|
+
end
|
728
|
+
handler[:handler].call(err, obj, args, context, field)
|
729
|
+
else
|
730
|
+
raise err
|
697
731
|
end
|
698
732
|
end
|
699
733
|
|
@@ -821,11 +855,6 @@ module GraphQL
|
|
821
855
|
ctx.errors.push(parse_err)
|
822
856
|
end
|
823
857
|
|
824
|
-
# @return [GraphQL::Execution::Errors]
|
825
|
-
def error_handler
|
826
|
-
@error_handler ||= GraphQL::Execution::Errors.new(self)
|
827
|
-
end
|
828
|
-
|
829
858
|
def lazy_resolve(lazy_class, value_method)
|
830
859
|
lazy_methods.set(lazy_class, value_method)
|
831
860
|
end
|
@@ -56,17 +56,24 @@ module GraphQL
|
|
56
56
|
# @param args [Hash<String, Symbol => Object]
|
57
57
|
# @param object [Object]
|
58
58
|
# @param scope [Symbol, String]
|
59
|
+
# @param context [Hash]
|
59
60
|
# @return [void]
|
60
|
-
def trigger(event_name, args, object, scope: nil)
|
61
|
+
def trigger(event_name, args, object, scope: nil, context: {})
|
62
|
+
# Make something as context-like as possible, even though there isn't a current query:
|
63
|
+
context = @schema.context_class.new(
|
64
|
+
query: GraphQL::Query.new(@schema, "", validate: false),
|
65
|
+
object: nil,
|
66
|
+
values: context
|
67
|
+
)
|
61
68
|
event_name = event_name.to_s
|
62
69
|
|
63
70
|
# Try with the verbatim input first:
|
64
|
-
field = @schema.get_field(@schema.subscription, event_name)
|
71
|
+
field = @schema.get_field(@schema.subscription, event_name, context)
|
65
72
|
|
66
73
|
if field.nil?
|
67
74
|
# And if it wasn't found, normalize it:
|
68
75
|
normalized_event_name = normalize_name(event_name)
|
69
|
-
field = @schema.get_field(@schema.subscription, normalized_event_name)
|
76
|
+
field = @schema.get_field(@schema.subscription, normalized_event_name, context)
|
70
77
|
if field.nil?
|
71
78
|
raise InvalidTriggerError, "No subscription matching trigger: #{event_name} (looked for #{@schema.subscription.graphql_name}.#{normalized_event_name})"
|
72
79
|
end
|
@@ -148,22 +148,6 @@ module GraphQL
|
|
148
148
|
obj_type.field :page_info, GraphQL::Types::Relay::PageInfo, null: false, description: "Information to aid in pagination."
|
149
149
|
end
|
150
150
|
end
|
151
|
-
|
152
|
-
# By default this calls through to the ConnectionWrapper's edge nodes method,
|
153
|
-
# but sometimes you need to override it to support the `nodes` field
|
154
|
-
def nodes
|
155
|
-
@object.edge_nodes
|
156
|
-
end
|
157
|
-
|
158
|
-
def edges
|
159
|
-
if @object.is_a?(GraphQL::Pagination::Connection)
|
160
|
-
@object.edges
|
161
|
-
else
|
162
|
-
context.schema.after_lazy(object.edge_nodes) do |nodes|
|
163
|
-
nodes.map { |n| self.class.edge_class.new(n, object) }
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
151
|
end
|
168
152
|
end
|
169
153
|
end
|
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.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-03-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-ips
|
@@ -366,7 +366,6 @@ files:
|
|
366
366
|
- lib/graphql/query/context.rb
|
367
367
|
- lib/graphql/query/fingerprint.rb
|
368
368
|
- lib/graphql/query/input_validation_result.rb
|
369
|
-
- lib/graphql/query/literal_input.rb
|
370
369
|
- lib/graphql/query/null_context.rb
|
371
370
|
- lib/graphql/query/result.rb
|
372
371
|
- lib/graphql/query/validation_pipeline.rb
|
@@ -582,7 +581,7 @@ metadata:
|
|
582
581
|
source_code_uri: https://github.com/rmosolgo/graphql-ruby
|
583
582
|
bug_tracker_uri: https://github.com/rmosolgo/graphql-ruby/issues
|
584
583
|
mailing_list_uri: https://tinyletter.com/graphql-ruby
|
585
|
-
post_install_message:
|
584
|
+
post_install_message:
|
586
585
|
rdoc_options: []
|
587
586
|
require_paths:
|
588
587
|
- lib
|
@@ -597,8 +596,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
597
596
|
- !ruby/object:Gem::Version
|
598
597
|
version: '0'
|
599
598
|
requirements: []
|
600
|
-
rubygems_version: 3.
|
601
|
-
signing_key:
|
599
|
+
rubygems_version: 3.3.3
|
600
|
+
signing_key:
|
602
601
|
specification_version: 4
|
603
602
|
summary: A GraphQL language and runtime for Ruby
|
604
603
|
test_files: []
|
@@ -1,131 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module GraphQL
|
3
|
-
class Query
|
4
|
-
# Turn query string values into something useful for query execution
|
5
|
-
class LiteralInput
|
6
|
-
def self.coerce(type, ast_node, variables)
|
7
|
-
case ast_node
|
8
|
-
when nil
|
9
|
-
nil
|
10
|
-
when Language::Nodes::NullValue
|
11
|
-
nil
|
12
|
-
when Language::Nodes::VariableIdentifier
|
13
|
-
variables[ast_node.name]
|
14
|
-
else
|
15
|
-
case type.kind.name
|
16
|
-
when "SCALAR"
|
17
|
-
# TODO smell
|
18
|
-
# This gets used for plain values during subscriber.trigger
|
19
|
-
if variables
|
20
|
-
type.coerce_input(ast_node, variables.context)
|
21
|
-
else
|
22
|
-
type.coerce_isolated_input(ast_node)
|
23
|
-
end
|
24
|
-
when "ENUM"
|
25
|
-
# TODO smell
|
26
|
-
# This gets used for plain values sometimes
|
27
|
-
v = ast_node.is_a?(GraphQL::Language::Nodes::Enum) ? ast_node.name : ast_node
|
28
|
-
if variables
|
29
|
-
type.coerce_input(v, variables.context)
|
30
|
-
else
|
31
|
-
type.coerce_isolated_input(v)
|
32
|
-
end
|
33
|
-
when "NON_NULL"
|
34
|
-
LiteralInput.coerce(type.of_type, ast_node, variables)
|
35
|
-
when "LIST"
|
36
|
-
if ast_node.is_a?(Array)
|
37
|
-
ast_node.map { |element_ast| LiteralInput.coerce(type.of_type, element_ast, variables) }
|
38
|
-
else
|
39
|
-
[LiteralInput.coerce(type.of_type, ast_node, variables)]
|
40
|
-
end
|
41
|
-
when "INPUT_OBJECT"
|
42
|
-
# TODO smell: handling AST vs handling plain Ruby
|
43
|
-
next_args = ast_node.is_a?(Hash) ? ast_node : ast_node.arguments
|
44
|
-
from_arguments(next_args, type, variables)
|
45
|
-
else
|
46
|
-
raise "Invariant: unexpected type to coerce to: #{type}"
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.from_arguments(ast_arguments, argument_owner, variables)
|
52
|
-
context = variables ? variables.context : nil
|
53
|
-
values_hash = {}
|
54
|
-
defaults_used = Set.new
|
55
|
-
|
56
|
-
indexed_arguments = case ast_arguments
|
57
|
-
when Hash
|
58
|
-
ast_arguments
|
59
|
-
when Array
|
60
|
-
ast_arguments.each_with_object({}) { |a, memo| memo[a.name] = a }
|
61
|
-
else
|
62
|
-
raise ArgumentError, "Unexpected ast_arguments: #{ast_arguments}"
|
63
|
-
end
|
64
|
-
|
65
|
-
argument_defns = argument_owner.arguments(context || GraphQL::Query::NullContext)
|
66
|
-
argument_defns.each do |arg_name, arg_defn|
|
67
|
-
ast_arg = indexed_arguments[arg_name]
|
68
|
-
# First, check the argument in the AST.
|
69
|
-
# If the value is a variable,
|
70
|
-
# only add a value if the variable is actually present.
|
71
|
-
# Otherwise, coerce the value in the AST, prepare the value and add it.
|
72
|
-
#
|
73
|
-
# TODO: since indexed_arguments can come from a plain Ruby hash,
|
74
|
-
# have to check for `false` or `nil` as hash values. This is getting smelly :S
|
75
|
-
if indexed_arguments.key?(arg_name)
|
76
|
-
arg_value = ast_arg.is_a?(GraphQL::Language::Nodes::Argument) ? ast_arg.value : ast_arg
|
77
|
-
|
78
|
-
value_is_a_variable = arg_value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
|
79
|
-
|
80
|
-
if (!value_is_a_variable || (value_is_a_variable && variables.key?(arg_value.name)))
|
81
|
-
|
82
|
-
value = coerce(arg_defn.type, arg_value, variables)
|
83
|
-
# Legacy `prepare` application
|
84
|
-
if arg_defn.is_a?(GraphQL::Argument)
|
85
|
-
value = arg_defn.prepare(value, context)
|
86
|
-
end
|
87
|
-
|
88
|
-
if value.is_a?(GraphQL::ExecutionError)
|
89
|
-
value.ast_node = ast_arg
|
90
|
-
raise value
|
91
|
-
end
|
92
|
-
|
93
|
-
values_hash[arg_name] = value
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
# Then, the definition for a default value.
|
98
|
-
# If the definition has a default value and
|
99
|
-
# a value wasn't provided from the AST,
|
100
|
-
# then add the default value.
|
101
|
-
if arg_defn.default_value? && !values_hash.key?(arg_name)
|
102
|
-
value = arg_defn.default_value
|
103
|
-
defaults_used << arg_name
|
104
|
-
# `context` isn't present when pre-calculating defaults
|
105
|
-
if context
|
106
|
-
if arg_defn.is_a?(GraphQL::Argument)
|
107
|
-
value = arg_defn.prepare(value, context)
|
108
|
-
end
|
109
|
-
if value.is_a?(GraphQL::ExecutionError)
|
110
|
-
value.ast_node = ast_arg
|
111
|
-
raise value
|
112
|
-
end
|
113
|
-
end
|
114
|
-
values_hash[arg_name] = value
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
# A Schema::InputObject, Schema::GraphQL::Field, Schema::Directive, logic from Interpreter::Arguments
|
119
|
-
ruby_kwargs = {}
|
120
|
-
values_hash.each do |key, value|
|
121
|
-
ruby_kwargs[Schema::Member::BuildType.underscore(key).to_sym] = value
|
122
|
-
end
|
123
|
-
if argument_owner.is_a?(Class) && argument_owner < GraphQL::Schema::InputObject
|
124
|
-
argument_owner.new(ruby_kwargs: ruby_kwargs, context: context, defaults_used: defaults_used)
|
125
|
-
else
|
126
|
-
ruby_kwargs
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|