graphql 1.9.16 → 1.9.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql.rb +8 -0
- data/lib/graphql/argument.rb +2 -2
- data/lib/graphql/define/assign_object_field.rb +2 -2
- data/lib/graphql/define/defined_object_proxy.rb +3 -0
- data/lib/graphql/define/instance_definable.rb +14 -3
- data/lib/graphql/execution/errors.rb +15 -14
- data/lib/graphql/execution/execute.rb +1 -1
- data/lib/graphql/execution/interpreter/runtime.rb +39 -17
- data/lib/graphql/execution/multiplex.rb +3 -3
- data/lib/graphql/introspection/entry_points.rb +2 -1
- data/lib/graphql/introspection/schema_type.rb +2 -1
- data/lib/graphql/language/document_from_schema_definition.rb +9 -3
- data/lib/graphql/language/nodes.rb +2 -2
- data/lib/graphql/query.rb +7 -1
- data/lib/graphql/query/context.rb +31 -9
- data/lib/graphql/query/null_context.rb +4 -0
- data/lib/graphql/query/variables.rb +3 -1
- data/lib/graphql/relay/node.rb +2 -2
- data/lib/graphql/schema.rb +58 -7
- data/lib/graphql/schema/argument.rb +4 -0
- data/lib/graphql/schema/base_64_bp.rb +3 -2
- data/lib/graphql/schema/build_from_definition.rb +26 -9
- data/lib/graphql/schema/directive.rb +7 -1
- data/lib/graphql/schema/introspection_system.rb +4 -1
- data/lib/graphql/schema/loader.rb +9 -3
- data/lib/graphql/schema/member/has_fields.rb +1 -4
- data/lib/graphql/schema/mutation.rb +1 -1
- data/lib/graphql/schema/object.rb +6 -4
- data/lib/graphql/schema/possible_types.rb +3 -3
- data/lib/graphql/schema/relay_classic_mutation.rb +1 -1
- data/lib/graphql/schema/resolver.rb +1 -1
- data/lib/graphql/schema/subscription.rb +5 -5
- data/lib/graphql/schema/type_membership.rb +34 -0
- data/lib/graphql/schema/union.rb +26 -6
- data/lib/graphql/schema/warden.rb +77 -3
- data/lib/graphql/subscriptions.rb +2 -2
- data/lib/graphql/subscriptions/subscription_root.rb +10 -2
- data/lib/graphql/union_type.rb +58 -23
- data/lib/graphql/version.rb +1 -1
- metadata +6 -5
@@ -143,9 +143,9 @@ module GraphQL
|
|
143
143
|
# Make a new context which delegates key lookup to `values`
|
144
144
|
# @param query [GraphQL::Query] the query who owns this context
|
145
145
|
# @param values [Hash] A hash of arbitrary values which will be accessible at query-time
|
146
|
-
def initialize(query:,
|
146
|
+
def initialize(query:, schema: query.schema, values:, object:)
|
147
147
|
@query = query
|
148
|
-
@schema =
|
148
|
+
@schema = schema
|
149
149
|
@provided_values = values || {}
|
150
150
|
@object = object
|
151
151
|
# Namespaced storage, where user-provided values are in `nil` namespace:
|
@@ -155,6 +155,7 @@ module GraphQL
|
|
155
155
|
@path = []
|
156
156
|
@value = nil
|
157
157
|
@context = self # for SharedMethods
|
158
|
+
@scoped_context = {}
|
158
159
|
end
|
159
160
|
|
160
161
|
# @api private
|
@@ -163,15 +164,30 @@ module GraphQL
|
|
163
164
|
# @api private
|
164
165
|
attr_writer :value
|
165
166
|
|
166
|
-
|
167
|
-
|
167
|
+
# @api private
|
168
|
+
attr_accessor :scoped_context
|
168
169
|
|
169
|
-
|
170
|
-
|
170
|
+
def_delegators :@provided_values, :[]=
|
171
|
+
def_delegators :to_h, :fetch, :dig
|
172
|
+
def_delegators :@query, :trace, :interpreter?
|
171
173
|
|
172
174
|
# @!method []=(key, value)
|
173
175
|
# Reassign `key` to the hash passed to {Schema#execute} as `context:`
|
174
176
|
|
177
|
+
# Lookup `key` from the hash passed to {Schema#execute} as `context:`
|
178
|
+
def [](key)
|
179
|
+
return @scoped_context[key] if @scoped_context.key?(key)
|
180
|
+
@provided_values[key]
|
181
|
+
end
|
182
|
+
|
183
|
+
def to_h
|
184
|
+
@provided_values.merge(@scoped_context)
|
185
|
+
end
|
186
|
+
alias :to_hash :to_h
|
187
|
+
|
188
|
+
def key?(key)
|
189
|
+
@scoped_context.key?(key) || @provided_values.key?(key)
|
190
|
+
end
|
175
191
|
|
176
192
|
# @return [GraphQL::Schema::Warden]
|
177
193
|
def warden
|
@@ -195,6 +211,15 @@ module GraphQL
|
|
195
211
|
@value = nil
|
196
212
|
end
|
197
213
|
|
214
|
+
def scoped_merge!(hash)
|
215
|
+
@scoped_context = @scoped_context.merge(hash)
|
216
|
+
end
|
217
|
+
|
218
|
+
def scoped_set!(key, value)
|
219
|
+
scoped_merge!(key => value)
|
220
|
+
nil
|
221
|
+
end
|
222
|
+
|
198
223
|
class FieldResolutionContext
|
199
224
|
include SharedMethods
|
200
225
|
include Tracing::Traceable
|
@@ -309,6 +334,3 @@ module GraphQL
|
|
309
334
|
end
|
310
335
|
end
|
311
336
|
end
|
312
|
-
|
313
|
-
|
314
|
-
GraphQL::Schema::Context = GraphQL::Query::Context
|
@@ -35,7 +35,9 @@ module GraphQL
|
|
35
35
|
if validation_result.valid?
|
36
36
|
if value_was_provided
|
37
37
|
# Add the variable if a value was provided
|
38
|
-
memo[variable_name] =
|
38
|
+
memo[variable_name] = schema.error_handler.with_error_handling(context) do
|
39
|
+
variable_type.coerce_input(provided_value, ctx)
|
40
|
+
end
|
39
41
|
elsif default_value != nil
|
40
42
|
# Add the variable if it wasn't provided but it has a default value (including `null`)
|
41
43
|
memo[variable_name] = GraphQL::Query::LiteralInput.coerce(variable_type, default_value, self)
|
data/lib/graphql/relay/node.rb
CHANGED
@@ -11,7 +11,7 @@ module GraphQL
|
|
11
11
|
field = GraphQL::Types::Relay::NodeField.graphql_definition
|
12
12
|
|
13
13
|
if kwargs.any? || block
|
14
|
-
field = field.redefine(kwargs, &block)
|
14
|
+
field = field.redefine(**kwargs, &block)
|
15
15
|
end
|
16
16
|
|
17
17
|
field
|
@@ -21,7 +21,7 @@ module GraphQL
|
|
21
21
|
field = GraphQL::Types::Relay::NodesField.graphql_definition
|
22
22
|
|
23
23
|
if kwargs.any? || block
|
24
|
-
field = field.redefine(kwargs, &block)
|
24
|
+
field = field.redefine(**kwargs, &block)
|
25
25
|
end
|
26
26
|
|
27
27
|
field
|
data/lib/graphql/schema.rb
CHANGED
@@ -40,6 +40,7 @@ require "graphql/schema/directive/include"
|
|
40
40
|
require "graphql/schema/directive/skip"
|
41
41
|
require "graphql/schema/directive/feature"
|
42
42
|
require "graphql/schema/directive/transform"
|
43
|
+
require "graphql/schema/type_membership"
|
43
44
|
|
44
45
|
require "graphql/schema/resolver"
|
45
46
|
require "graphql/schema/mutation"
|
@@ -98,6 +99,8 @@ module GraphQL
|
|
98
99
|
mutation: ->(schema, t) { schema.mutation = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
|
99
100
|
subscription: ->(schema, t) { schema.subscription = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
|
100
101
|
disable_introspection_entry_points: ->(schema) { schema.disable_introspection_entry_points = true },
|
102
|
+
disable_schema_introspection_entry_point: ->(schema) { schema.disable_schema_introspection_entry_point = true },
|
103
|
+
disable_type_introspection_entry_point: ->(schema) { schema.disable_type_introspection_entry_point = true },
|
101
104
|
directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.name] = d; m } },
|
102
105
|
directive: ->(schema, directive) { schema.directives[directive.graphql_name] = directive },
|
103
106
|
instrument: ->(schema, type, instrumenter, after_built_ins: false) {
|
@@ -153,6 +156,12 @@ module GraphQL
|
|
153
156
|
# [Boolean] True if this object disables the introspection entry point fields
|
154
157
|
attr_accessor :disable_introspection_entry_points
|
155
158
|
|
159
|
+
# [Boolean] True if this object disables the __schema introspection entry point field
|
160
|
+
attr_accessor :disable_schema_introspection_entry_point
|
161
|
+
|
162
|
+
# [Boolean] True if this object disables the __type introspection entry point field
|
163
|
+
attr_accessor :disable_type_introspection_entry_point
|
164
|
+
|
156
165
|
class << self
|
157
166
|
attr_writer :default_execution_strategy
|
158
167
|
end
|
@@ -202,6 +211,8 @@ module GraphQL
|
|
202
211
|
@interpreter = false
|
203
212
|
@error_bubbling = false
|
204
213
|
@disable_introspection_entry_points = false
|
214
|
+
@disable_schema_introspection_entry_point = false
|
215
|
+
@disable_type_introspection_entry_point = false
|
205
216
|
end
|
206
217
|
|
207
218
|
# @return [Boolean] True if using the new {GraphQL::Execution::Interpreter}
|
@@ -271,7 +282,7 @@ module GraphQL
|
|
271
282
|
query = GraphQL::Query.new(self, document: doc, context: context)
|
272
283
|
validator_opts = { schema: self }
|
273
284
|
rules && (validator_opts[:rules] = rules)
|
274
|
-
validator = GraphQL::StaticValidation::Validator.new(validator_opts)
|
285
|
+
validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
|
275
286
|
res = validator.validate(query)
|
276
287
|
res[:errors]
|
277
288
|
end
|
@@ -448,10 +459,11 @@ module GraphQL
|
|
448
459
|
|
449
460
|
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
450
461
|
# @param type_defn [GraphQL::InterfaceType, GraphQL::UnionType] the type whose members you want to retrieve
|
462
|
+
# @param context [GraphQL::Query::Context] The context for the current query
|
451
463
|
# @return [Array<GraphQL::ObjectType>] types which belong to `type_defn` in this schema
|
452
|
-
def possible_types(type_defn)
|
464
|
+
def possible_types(type_defn, context = GraphQL::Query::NullContext)
|
453
465
|
@possible_types ||= GraphQL::Schema::PossibleTypes.new(self)
|
454
|
-
@possible_types.possible_types(type_defn)
|
466
|
+
@possible_types.possible_types(type_defn, context)
|
455
467
|
end
|
456
468
|
|
457
469
|
# @see [GraphQL::Schema::Warden] Resticted access to root types
|
@@ -597,6 +609,7 @@ module GraphQL
|
|
597
609
|
alias :_schema_class :class
|
598
610
|
def_delegators :_schema_class, :visible?, :accessible?, :authorized?, :unauthorized_object, :unauthorized_field, :inaccessible_fields
|
599
611
|
def_delegators :_schema_class, :directive
|
612
|
+
def_delegators :_schema_class, :error_handler
|
600
613
|
|
601
614
|
# A function to call when {#execute} receives an invalid query string
|
602
615
|
#
|
@@ -676,9 +689,12 @@ module GraphQL
|
|
676
689
|
end
|
677
690
|
|
678
691
|
# Return the GraphQL::Language::Document IDL AST for the schema
|
692
|
+
# @param context [Hash]
|
693
|
+
# @param only [<#call(member, ctx)>]
|
694
|
+
# @param except [<#call(member, ctx)>]
|
679
695
|
# @return [GraphQL::Language::Document]
|
680
|
-
def to_document
|
681
|
-
GraphQL::Language::DocumentFromSchemaDefinition.new(self).document
|
696
|
+
def to_document(only: nil, except: nil, context: {})
|
697
|
+
GraphQL::Language::DocumentFromSchemaDefinition.new(self, only: only, except: except, context: context).document
|
682
698
|
end
|
683
699
|
|
684
700
|
# Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
|
@@ -729,13 +745,15 @@ module GraphQL
|
|
729
745
|
:union_memberships,
|
730
746
|
:get_field, :root_types, :references_to, :type_from_ast,
|
731
747
|
:possible_types,
|
732
|
-
:disable_introspection_entry_points
|
748
|
+
:disable_introspection_entry_points=,
|
749
|
+
:disable_schema_introspection_entry_point=,
|
750
|
+
:disable_type_introspection_entry_point=
|
733
751
|
|
734
752
|
def graphql_definition
|
735
753
|
@graphql_definition ||= to_graphql
|
736
754
|
end
|
737
755
|
|
738
|
-
def use(plugin, options
|
756
|
+
def use(plugin, **options)
|
739
757
|
own_plugins << [plugin, options]
|
740
758
|
end
|
741
759
|
|
@@ -755,6 +773,8 @@ module GraphQL
|
|
755
773
|
schema_defn.default_max_page_size = default_max_page_size
|
756
774
|
schema_defn.orphan_types = orphan_types
|
757
775
|
schema_defn.disable_introspection_entry_points = disable_introspection_entry_points?
|
776
|
+
schema_defn.disable_schema_introspection_entry_point = disable_schema_introspection_entry_point?
|
777
|
+
schema_defn.disable_type_introspection_entry_point = disable_type_introspection_entry_point?
|
758
778
|
|
759
779
|
prepped_dirs = {}
|
760
780
|
directives.each { |k, v| prepped_dirs[k] = v.graphql_definition}
|
@@ -910,6 +930,14 @@ module GraphQL
|
|
910
930
|
@disable_introspection_entry_points = true
|
911
931
|
end
|
912
932
|
|
933
|
+
def disable_schema_introspection_entry_point
|
934
|
+
@disable_schema_introspection_entry_point = true
|
935
|
+
end
|
936
|
+
|
937
|
+
def disable_type_introspection_entry_point
|
938
|
+
@disable_type_introspection_entry_point = true
|
939
|
+
end
|
940
|
+
|
913
941
|
def disable_introspection_entry_points?
|
914
942
|
if instance_variable_defined?(:@disable_introspection_entry_points)
|
915
943
|
@disable_introspection_entry_points
|
@@ -918,6 +946,22 @@ module GraphQL
|
|
918
946
|
end
|
919
947
|
end
|
920
948
|
|
949
|
+
def disable_schema_introspection_entry_point?
|
950
|
+
if instance_variable_defined?(:@disable_schema_introspection_entry_point)
|
951
|
+
@disable_schema_introspection_entry_point
|
952
|
+
else
|
953
|
+
find_inherited_value(:disable_schema_introspection_entry_point?, false)
|
954
|
+
end
|
955
|
+
end
|
956
|
+
|
957
|
+
def disable_type_introspection_entry_point?
|
958
|
+
if instance_variable_defined?(:@disable_type_introspection_entry_point)
|
959
|
+
@disable_type_introspection_entry_point
|
960
|
+
else
|
961
|
+
find_inherited_value(:disable_type_introspection_entry_point?, false)
|
962
|
+
end
|
963
|
+
end
|
964
|
+
|
921
965
|
def orphan_types(*new_orphan_types)
|
922
966
|
if new_orphan_types.any?
|
923
967
|
own_orphan_types.concat(new_orphan_types.flatten)
|
@@ -1027,6 +1071,13 @@ module GraphQL
|
|
1027
1071
|
DefaultTypeError.call(type_err, ctx)
|
1028
1072
|
end
|
1029
1073
|
|
1074
|
+
attr_writer :error_handler
|
1075
|
+
|
1076
|
+
# @return [GraphQL::Execution::Errors, Class<GraphQL::Execution::Errors::NullErrorHandler>]
|
1077
|
+
def error_handler
|
1078
|
+
@error_handler ||= GraphQL::Execution::Errors::NullErrorHandler
|
1079
|
+
end
|
1080
|
+
|
1030
1081
|
def lazy_resolve(lazy_class, value_method)
|
1031
1082
|
lazy_classes[lazy_class] = value_method
|
1032
1083
|
end
|
@@ -121,6 +121,10 @@ module GraphQL
|
|
121
121
|
# Used by the runtime.
|
122
122
|
# @api private
|
123
123
|
def prepare_value(obj, value)
|
124
|
+
if value.is_a?(GraphQL::Schema::InputObject)
|
125
|
+
value = value.prepare
|
126
|
+
end
|
127
|
+
|
124
128
|
if @prepare.nil?
|
125
129
|
value
|
126
130
|
elsif @prepare.is_a?(String) || @prepare.is_a?(Symbol)
|
@@ -10,8 +10,9 @@ module Base64Bp
|
|
10
10
|
module_function
|
11
11
|
|
12
12
|
def urlsafe_encode64(bin, padding:)
|
13
|
-
str = strict_encode64(bin)
|
14
|
-
str
|
13
|
+
str = strict_encode64(bin)
|
14
|
+
str.tr!("+/", "-_")
|
15
|
+
str.delete!("=") unless padding
|
15
16
|
str
|
16
17
|
end
|
17
18
|
|
@@ -183,12 +183,16 @@ module GraphQL
|
|
183
183
|
def build_object_type(object_type_definition, type_resolver, default_resolve:)
|
184
184
|
type_def = nil
|
185
185
|
typed_resolve_fn = ->(field, obj, args, ctx) { default_resolve.call(type_def, field, obj, args, ctx) }
|
186
|
-
|
186
|
+
defns = {
|
187
187
|
name: object_type_definition.name,
|
188
188
|
description: object_type_definition.description,
|
189
|
-
fields: Hash[build_fields(object_type_definition.fields, type_resolver, default_resolve: typed_resolve_fn)],
|
190
189
|
interfaces: object_type_definition.interfaces.map{ |interface_name| type_resolver.call(interface_name) },
|
191
|
-
|
190
|
+
}
|
191
|
+
obj_fields = Hash[build_fields(object_type_definition.fields, type_resolver, default_resolve: typed_resolve_fn)]
|
192
|
+
if obj_fields.any?
|
193
|
+
defns[:fields] = obj_fields
|
194
|
+
end
|
195
|
+
type_def = GraphQL::ObjectType.define(**defns)
|
192
196
|
type_def.ast_node = object_type_definition
|
193
197
|
type_def
|
194
198
|
end
|
@@ -246,13 +250,19 @@ module GraphQL
|
|
246
250
|
end
|
247
251
|
|
248
252
|
def build_directive(directive_definition, type_resolver)
|
249
|
-
|
253
|
+
directive_args = Hash[build_directive_arguments(directive_definition, type_resolver)]
|
254
|
+
|
255
|
+
defn = {
|
250
256
|
name: directive_definition.name,
|
251
257
|
description: directive_definition.description,
|
252
|
-
arguments: Hash[build_directive_arguments(directive_definition, type_resolver)],
|
253
258
|
locations: directive_definition.locations.map { |location| location.name.to_sym },
|
254
|
-
|
259
|
+
}
|
260
|
+
|
261
|
+
if directive_args.any?
|
262
|
+
defn[:arguments] = directive_args
|
263
|
+
end
|
255
264
|
|
265
|
+
directive = GraphQL::Directive.define(**defn)
|
256
266
|
directive.ast_node = directive_definition
|
257
267
|
|
258
268
|
directive
|
@@ -317,14 +327,21 @@ module GraphQL
|
|
317
327
|
[argument.name, arg]
|
318
328
|
end]
|
319
329
|
|
320
|
-
field =
|
330
|
+
field = nil
|
331
|
+
|
332
|
+
defns = {
|
321
333
|
name: field_definition.name,
|
322
334
|
description: field_definition.description,
|
323
335
|
type: type_resolver.call(field_definition.type),
|
324
|
-
arguments: field_arguments,
|
325
336
|
resolve: ->(obj, args, ctx) { default_resolve.call(field, obj, args, ctx) },
|
326
337
|
deprecation_reason: build_deprecation_reason(field_definition.directives),
|
327
|
-
|
338
|
+
}
|
339
|
+
|
340
|
+
if field_arguments.any?
|
341
|
+
defns[:arguments] = field_arguments
|
342
|
+
end
|
343
|
+
|
344
|
+
field = GraphQL::Field.define(**defns)
|
328
345
|
|
329
346
|
field.ast_node = field_definition
|
330
347
|
|
@@ -9,8 +9,14 @@ module GraphQL
|
|
9
9
|
class Directive < GraphQL::Schema::Member
|
10
10
|
extend GraphQL::Schema::Member::HasArguments
|
11
11
|
class << self
|
12
|
+
# Return a name based on the class name,
|
13
|
+
# but downcase the first letter.
|
12
14
|
def default_graphql_name
|
13
|
-
|
15
|
+
@default_graphql_name ||= begin
|
16
|
+
camelized_name = super
|
17
|
+
camelized_name[0] = camelized_name[0].downcase
|
18
|
+
camelized_name
|
19
|
+
end
|
14
20
|
end
|
15
21
|
|
16
22
|
def locations(*new_locations)
|
@@ -22,7 +22,10 @@ module GraphQL
|
|
22
22
|
if schema.disable_introspection_entry_points
|
23
23
|
{}
|
24
24
|
else
|
25
|
-
get_fields_from_class(class_sym: :EntryPoints)
|
25
|
+
entry_point_fields = get_fields_from_class(class_sym: :EntryPoints)
|
26
|
+
entry_point_fields.delete('__schema') if schema.disable_schema_introspection_entry_point
|
27
|
+
entry_point_fields.delete('__type') if schema.disable_type_introspection_entry_point
|
28
|
+
entry_point_fields
|
26
29
|
end
|
27
30
|
@dynamic_fields = get_fields_from_class(class_sym: :DynamicFields)
|
28
31
|
end
|
@@ -118,14 +118,20 @@ module GraphQL
|
|
118
118
|
}]
|
119
119
|
)
|
120
120
|
when "FIELD"
|
121
|
-
|
121
|
+
defns = {
|
122
122
|
name: type["name"],
|
123
123
|
type: type_resolver.call(type["type"]),
|
124
124
|
description: type["description"],
|
125
|
-
|
125
|
+
}
|
126
|
+
|
127
|
+
# Avoid passing an empty hash, which warns on Ruby 2.7
|
128
|
+
if type["args"].any?
|
129
|
+
defns[:arguments] = Hash[type["args"].map { |arg|
|
126
130
|
[arg["name"], define_type(arg.merge("kind" => "ARGUMENT"), type_resolver)]
|
127
131
|
}]
|
128
|
-
|
132
|
+
end
|
133
|
+
|
134
|
+
GraphQL::Field.define(**defns)
|
129
135
|
when "ARGUMENT"
|
130
136
|
kwargs = {}
|
131
137
|
if type["defaultValue"]
|
@@ -1,5 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require 'irb/ruby-token'
|
3
2
|
|
4
3
|
module GraphQL
|
5
4
|
class Schema
|
@@ -43,9 +42,7 @@ module GraphQL
|
|
43
42
|
# A list of Ruby keywords.
|
44
43
|
#
|
45
44
|
# @api private
|
46
|
-
RUBY_KEYWORDS =
|
47
|
-
.map { |definition| definition[2] }
|
48
|
-
.compact
|
45
|
+
RUBY_KEYWORDS = [:class, :module, :def, :undef, :begin, :rescue, :ensure, :end, :if, :unless, :then, :elsif, :else, :case, :when, :while, :until, :for, :break, :next, :redo, :retry, :in, :do, :return, :yield, :super, :self, :nil, :true, :false, :and, :or, :not, :alias, :defined?, :BEGIN, :END, :__LINE__, :__FILE__]
|
49
46
|
|
50
47
|
# A list of GraphQL-Ruby keywords.
|
51
48
|
#
|
@@ -64,7 +64,7 @@ module GraphQL
|
|
64
64
|
|
65
65
|
class << self
|
66
66
|
# Override this method to handle legacy-style usages of `MyMutation.field`
|
67
|
-
def field(*args, &block)
|
67
|
+
def field(*args, **kwargs, &block)
|
68
68
|
if args.empty?
|
69
69
|
raise ArgumentError, "#{name}.field is used for adding fields to this mutation. Use `mutation: #{name}` to attach this mutation instead."
|
70
70
|
else
|