graphql 1.10.6 → 1.10.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/generators/graphql/object_generator.rb +50 -8
- data/lib/graphql.rb +4 -4
- data/lib/graphql/analysis/ast/query_complexity.rb +1 -1
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +2 -2
- data/lib/graphql/execution/instrumentation.rb +1 -1
- data/lib/graphql/execution/interpreter.rb +2 -0
- data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
- data/lib/graphql/execution/interpreter/arguments.rb +36 -0
- data/lib/graphql/execution/interpreter/arguments_cache.rb +3 -7
- data/lib/graphql/execution/interpreter/runtime.rb +47 -38
- data/lib/graphql/execution/lookahead.rb +3 -1
- data/lib/graphql/internal_representation/scope.rb +2 -2
- data/lib/graphql/internal_representation/visit.rb +2 -2
- data/lib/graphql/language/document_from_schema_definition.rb +42 -23
- data/lib/graphql/object_type.rb +1 -1
- data/lib/graphql/relay/base_connection.rb +0 -2
- data/lib/graphql/schema.rb +28 -13
- data/lib/graphql/schema/argument.rb +6 -0
- data/lib/graphql/schema/base_64_encoder.rb +2 -0
- data/lib/graphql/schema/enum.rb +9 -1
- data/lib/graphql/schema/field.rb +30 -21
- data/lib/graphql/schema/input_object.rb +9 -6
- data/lib/graphql/schema/interface.rb +5 -0
- data/lib/graphql/schema/list.rb +7 -1
- data/lib/graphql/schema/loader.rb +110 -103
- data/lib/graphql/schema/member.rb +1 -0
- data/lib/graphql/schema/member/has_arguments.rb +33 -13
- data/lib/graphql/schema/member/has_fields.rb +1 -1
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
- data/lib/graphql/schema/non_null.rb +5 -0
- data/lib/graphql/schema/object.rb +10 -3
- data/lib/graphql/schema/printer.rb +0 -14
- data/lib/graphql/schema/resolver.rb +1 -1
- data/lib/graphql/schema/union.rb +6 -0
- data/lib/graphql/schema/warden.rb +7 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +1 -0
- data/lib/graphql/subscriptions/subscription_root.rb +10 -2
- data/lib/graphql/tracing.rb +5 -4
- data/lib/graphql/tracing/new_relic_tracing.rb +1 -12
- data/lib/graphql/tracing/platform_tracing.rb +14 -0
- data/lib/graphql/tracing/scout_tracing.rb +11 -0
- data/lib/graphql/types/iso_8601_date.rb +3 -3
- data/lib/graphql/types/iso_8601_date_time.rb +18 -8
- data/lib/graphql/version.rb +1 -1
- metadata +6 -3
@@ -23,11 +23,11 @@ module GraphQL
|
|
23
23
|
|
24
24
|
# Traverse a node in a rewritten query tree,
|
25
25
|
# visiting the node itself and each of its typed children.
|
26
|
-
def each_node(node)
|
26
|
+
def each_node(node, &block)
|
27
27
|
yield(node)
|
28
28
|
node.typed_children.each do |obj_type, children|
|
29
29
|
children.each do |name, node|
|
30
|
-
each_node(node
|
30
|
+
each_node(node, &block)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
@@ -49,7 +49,7 @@ module GraphQL
|
|
49
49
|
subscription: (s = warden.root_type_for_operation("subscription")) && s.graphql_name,
|
50
50
|
# This only supports directives from parsing,
|
51
51
|
# use a custom printer to add to this list.
|
52
|
-
directives: @schema
|
52
|
+
directives: ast_directives(@schema),
|
53
53
|
)
|
54
54
|
end
|
55
55
|
|
@@ -59,32 +59,26 @@ module GraphQL
|
|
59
59
|
interfaces: warden.interfaces(object_type).sort_by(&:graphql_name).map { |iface| build_type_name_node(iface) },
|
60
60
|
fields: build_field_nodes(warden.fields(object_type)),
|
61
61
|
description: object_type.description,
|
62
|
+
directives: ast_directives(object_type),
|
62
63
|
)
|
63
64
|
end
|
64
65
|
|
65
66
|
def build_field_node(field)
|
66
|
-
|
67
|
+
GraphQL::Language::Nodes::FieldDefinition.new(
|
67
68
|
name: field.graphql_name,
|
68
69
|
arguments: build_argument_nodes(warden.arguments(field)),
|
69
70
|
type: build_type_name_node(field.type),
|
70
71
|
description: field.description,
|
72
|
+
directives: ast_directives(field),
|
71
73
|
)
|
72
|
-
|
73
|
-
if field.deprecation_reason
|
74
|
-
field_node = field_node.merge_directive(
|
75
|
-
name: GraphQL::Directive::DeprecatedDirective.graphql_name,
|
76
|
-
arguments: [GraphQL::Language::Nodes::Argument.new(name: "reason", value: field.deprecation_reason)]
|
77
|
-
)
|
78
|
-
end
|
79
|
-
|
80
|
-
field_node
|
81
74
|
end
|
82
75
|
|
83
76
|
def build_union_type_node(union_type)
|
84
77
|
GraphQL::Language::Nodes::UnionTypeDefinition.new(
|
85
78
|
name: union_type.graphql_name,
|
86
79
|
description: union_type.description,
|
87
|
-
types: warden.possible_types(union_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) }
|
80
|
+
types: warden.possible_types(union_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) },
|
81
|
+
directives: ast_directives(union_type),
|
88
82
|
)
|
89
83
|
end
|
90
84
|
|
@@ -92,7 +86,8 @@ module GraphQL
|
|
92
86
|
GraphQL::Language::Nodes::InterfaceTypeDefinition.new(
|
93
87
|
name: interface_type.graphql_name,
|
94
88
|
description: interface_type.description,
|
95
|
-
fields: build_field_nodes(warden.fields(interface_type))
|
89
|
+
fields: build_field_nodes(warden.fields(interface_type)),
|
90
|
+
directives: ast_directives(interface_type),
|
96
91
|
)
|
97
92
|
end
|
98
93
|
|
@@ -103,29 +98,23 @@ module GraphQL
|
|
103
98
|
build_enum_value_node(enum_value)
|
104
99
|
end,
|
105
100
|
description: enum_type.description,
|
101
|
+
directives: ast_directives(enum_type),
|
106
102
|
)
|
107
103
|
end
|
108
104
|
|
109
105
|
def build_enum_value_node(enum_value)
|
110
|
-
|
106
|
+
GraphQL::Language::Nodes::EnumValueDefinition.new(
|
111
107
|
name: enum_value.graphql_name,
|
112
108
|
description: enum_value.description,
|
109
|
+
directives: ast_directives(enum_value),
|
113
110
|
)
|
114
|
-
|
115
|
-
if enum_value.deprecation_reason
|
116
|
-
enum_value_node = enum_value_node.merge_directive(
|
117
|
-
name: GraphQL::Directive::DeprecatedDirective.graphql_name,
|
118
|
-
arguments: [GraphQL::Language::Nodes::Argument.new(name: "reason", value: enum_value.deprecation_reason)]
|
119
|
-
)
|
120
|
-
end
|
121
|
-
|
122
|
-
enum_value_node
|
123
111
|
end
|
124
112
|
|
125
113
|
def build_scalar_type_node(scalar_type)
|
126
114
|
GraphQL::Language::Nodes::ScalarTypeDefinition.new(
|
127
115
|
name: scalar_type.graphql_name,
|
128
116
|
description: scalar_type.description,
|
117
|
+
directives: ast_directives(scalar_type),
|
129
118
|
)
|
130
119
|
end
|
131
120
|
|
@@ -141,6 +130,7 @@ module GraphQL
|
|
141
130
|
description: argument.description,
|
142
131
|
type: build_type_name_node(argument.type),
|
143
132
|
default_value: default_value,
|
133
|
+
directives: ast_directives(argument),
|
144
134
|
)
|
145
135
|
|
146
136
|
argument_node
|
@@ -151,6 +141,7 @@ module GraphQL
|
|
151
141
|
name: input_object.graphql_name,
|
152
142
|
fields: build_argument_nodes(warden.arguments(input_object)),
|
153
143
|
description: input_object.description,
|
144
|
+
directives: ast_directives(input_object),
|
154
145
|
)
|
155
146
|
end
|
156
147
|
|
@@ -292,6 +283,34 @@ module GraphQL
|
|
292
283
|
(schema.subscription.nil? || schema.subscription.graphql_name == 'Subscription')
|
293
284
|
end
|
294
285
|
|
286
|
+
def ast_directives(member)
|
287
|
+
ast_directives = member.ast_node ? member.ast_node.directives : []
|
288
|
+
|
289
|
+
# If this schema was built from IDL, it will already have `@deprecated` in `ast_node.directives`
|
290
|
+
if member.respond_to?(:deprecation_reason) &&
|
291
|
+
(reason = member.deprecation_reason) &&
|
292
|
+
ast_directives.none? { |d| d.name == "deprecated" }
|
293
|
+
|
294
|
+
arguments = []
|
295
|
+
|
296
|
+
if reason != GraphQL::Schema::Directive::DEFAULT_DEPRECATION_REASON
|
297
|
+
arguments << GraphQL::Language::Nodes::Argument.new(
|
298
|
+
name: "reason",
|
299
|
+
value: reason
|
300
|
+
)
|
301
|
+
end
|
302
|
+
|
303
|
+
ast_directives += [
|
304
|
+
GraphQL::Language::Nodes::Directive.new(
|
305
|
+
name: GraphQL::Directive::DeprecatedDirective.graphql_name,
|
306
|
+
arguments: arguments
|
307
|
+
)
|
308
|
+
]
|
309
|
+
end
|
310
|
+
|
311
|
+
ast_directives
|
312
|
+
end
|
313
|
+
|
295
314
|
attr_reader :schema, :warden, :always_include_schema,
|
296
315
|
:include_introspection_types, :include_built_in_directives, :include_built_in_scalars
|
297
316
|
end
|
data/lib/graphql/object_type.rb
CHANGED
@@ -88,7 +88,7 @@ module GraphQL
|
|
88
88
|
interfaces.each do |iface|
|
89
89
|
iface = BaseType.resolve_related_type(iface)
|
90
90
|
if iface.is_a?(GraphQL::InterfaceType)
|
91
|
-
type_memberships << iface.type_membership_class.new(iface, self, options)
|
91
|
+
type_memberships << iface.type_membership_class.new(iface, self, **options)
|
92
92
|
end
|
93
93
|
end
|
94
94
|
end
|
data/lib/graphql/schema.rb
CHANGED
@@ -101,14 +101,12 @@ module GraphQL
|
|
101
101
|
# - Right away, if `value` is not registered with `lazy_resolve`
|
102
102
|
# - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
|
103
103
|
# @api private
|
104
|
-
def after_lazy(value)
|
104
|
+
def after_lazy(value, &block)
|
105
105
|
if lazy?(value)
|
106
106
|
GraphQL::Execution::Lazy.new do
|
107
107
|
result = sync_lazy(value)
|
108
108
|
# The returned result might also be lazy, so check it, too
|
109
|
-
after_lazy(result)
|
110
|
-
yield(final_result) if block_given?
|
111
|
-
end
|
109
|
+
after_lazy(result, &block)
|
112
110
|
end
|
113
111
|
else
|
114
112
|
yield(value) if block_given?
|
@@ -146,10 +144,10 @@ module GraphQL
|
|
146
144
|
def after_any_lazies(maybe_lazies)
|
147
145
|
if maybe_lazies.any? { |l| lazy?(l) }
|
148
146
|
GraphQL::Execution::Lazy.all(maybe_lazies).then do |result|
|
149
|
-
yield
|
147
|
+
yield result
|
150
148
|
end
|
151
149
|
else
|
152
|
-
yield
|
150
|
+
yield maybe_lazies
|
153
151
|
end
|
154
152
|
end
|
155
153
|
end
|
@@ -555,8 +553,17 @@ module GraphQL
|
|
555
553
|
# @param context [GraphQL::Query::Context] The context for the current query
|
556
554
|
# @return [Array<GraphQL::ObjectType>] types which belong to `type_defn` in this schema
|
557
555
|
def possible_types(type_defn, context = GraphQL::Query::NullContext)
|
558
|
-
|
559
|
-
|
556
|
+
if context == GraphQL::Query::NullContext
|
557
|
+
@possible_types ||= GraphQL::Schema::PossibleTypes.new(self)
|
558
|
+
@possible_types.possible_types(type_defn, context)
|
559
|
+
else
|
560
|
+
# Use the incoming context to cache this instance --
|
561
|
+
# if it were cached on the schema, we'd have a memory leak
|
562
|
+
# https://github.com/rmosolgo/graphql-ruby/issues/2878
|
563
|
+
ns = context.namespace(:possible_types)
|
564
|
+
per_query_possible_types = ns[:possible_types] ||= GraphQL::Schema::PossibleTypes.new(self)
|
565
|
+
per_query_possible_types.possible_types(type_defn, context)
|
566
|
+
end
|
560
567
|
end
|
561
568
|
|
562
569
|
# @see [GraphQL::Schema::Warden] Resticted access to root types
|
@@ -863,8 +870,8 @@ module GraphQL
|
|
863
870
|
# Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
|
864
871
|
# @see {#as_json}
|
865
872
|
# @return [String]
|
866
|
-
def to_json(
|
867
|
-
JSON.pretty_generate(as_json(
|
873
|
+
def to_json(**args)
|
874
|
+
JSON.pretty_generate(as_json(**args))
|
868
875
|
end
|
869
876
|
|
870
877
|
# Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
|
@@ -1382,7 +1389,7 @@ module GraphQL
|
|
1382
1389
|
# rubocop:disable Lint/DuplicateMethods
|
1383
1390
|
module ResolveTypeWithType
|
1384
1391
|
def resolve_type(type, obj, ctx)
|
1385
|
-
first_resolved_type = if type.is_a?(Module) && type.respond_to?(:resolve_type)
|
1392
|
+
first_resolved_type, resolved_value = if type.is_a?(Module) && type.respond_to?(:resolve_type)
|
1386
1393
|
type.resolve_type(obj, ctx)
|
1387
1394
|
else
|
1388
1395
|
super
|
@@ -1390,7 +1397,11 @@ module GraphQL
|
|
1390
1397
|
|
1391
1398
|
after_lazy(first_resolved_type) do |resolved_type|
|
1392
1399
|
if resolved_type.nil? || (resolved_type.is_a?(Module) && resolved_type.respond_to?(:kind)) || resolved_type.is_a?(GraphQL::BaseType)
|
1393
|
-
|
1400
|
+
if resolved_value
|
1401
|
+
[resolved_type, resolved_value]
|
1402
|
+
else
|
1403
|
+
resolved_type
|
1404
|
+
end
|
1394
1405
|
else
|
1395
1406
|
raise ".resolve_type should return a type definition, but got #{resolved_type.inspect} (#{resolved_type.class}) from `resolve_type(#{type}, #{obj}, #{ctx})`"
|
1396
1407
|
end
|
@@ -1499,7 +1510,11 @@ module GraphQL
|
|
1499
1510
|
|
1500
1511
|
# @return [GraphQL::Execution::Errors, Class<GraphQL::Execution::Errors::NullErrorHandler>]
|
1501
1512
|
def error_handler
|
1502
|
-
@error_handler
|
1513
|
+
if defined?(@error_handler)
|
1514
|
+
@error_handler
|
1515
|
+
else
|
1516
|
+
find_inherited_value(:error_handler, GraphQL::Execution::Errors::NullErrorHandler)
|
1517
|
+
end
|
1503
1518
|
end
|
1504
1519
|
|
1505
1520
|
def lazy_resolve(lazy_class, value_method)
|
@@ -154,6 +154,12 @@ module GraphQL
|
|
154
154
|
raise ArgumentError, "Couldn't build type for Argument #{@owner.name}.#{name}: #{err.class.name}: #{err.message}", err.backtrace
|
155
155
|
end
|
156
156
|
|
157
|
+
def statically_coercible?
|
158
|
+
return @statically_coercible if defined?(@statically_coercible)
|
159
|
+
|
160
|
+
@statically_coercible = !@prepare.is_a?(String) && !@prepare.is_a?(Symbol)
|
161
|
+
end
|
162
|
+
|
157
163
|
# Apply the {prepare} configuration to `value`, using methods from `obj`.
|
158
164
|
# Used by the runtime.
|
159
165
|
# @api private
|
@@ -13,6 +13,8 @@ module GraphQL
|
|
13
13
|
def self.decode(encoded_text, nonce: false)
|
14
14
|
# urlsafe_decode64 is for forward compatibility
|
15
15
|
Base64Bp.urlsafe_decode64(encoded_text)
|
16
|
+
rescue ArgumentError
|
17
|
+
raise GraphQL::ExecutionError, "Invalid input: #{encoded_text.inspect}"
|
16
18
|
end
|
17
19
|
end
|
18
20
|
end
|
data/lib/graphql/schema/enum.rb
CHANGED
@@ -23,6 +23,9 @@ module GraphQL
|
|
23
23
|
extend GraphQL::Schema::Member::AcceptsDefinition
|
24
24
|
extend GraphQL::Schema::Member::ValidatesInput
|
25
25
|
|
26
|
+
class UnresolvedValueError < GraphQL::EnumType::UnresolvedValueError
|
27
|
+
end
|
28
|
+
|
26
29
|
class << self
|
27
30
|
# Define a value for this enum
|
28
31
|
# @param graphql_name [String, Symbol] the GraphQL value for this, usually `SCREAMING_CASE`
|
@@ -94,7 +97,7 @@ module GraphQL
|
|
94
97
|
if enum_value
|
95
98
|
enum_value.graphql_name
|
96
99
|
else
|
97
|
-
raise(
|
100
|
+
raise(self::UnresolvedValueError, "Can't resolve enum #{graphql_name} for #{value.inspect}")
|
98
101
|
end
|
99
102
|
end
|
100
103
|
|
@@ -112,6 +115,11 @@ module GraphQL
|
|
112
115
|
end
|
113
116
|
end
|
114
117
|
|
118
|
+
def inherited(child_class)
|
119
|
+
child_class.const_set(:UnresolvedValueError, Class.new(Schema::Enum::UnresolvedValueError))
|
120
|
+
super
|
121
|
+
end
|
122
|
+
|
115
123
|
private
|
116
124
|
|
117
125
|
def own_values
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -47,6 +47,11 @@ module GraphQL
|
|
47
47
|
@resolver_class
|
48
48
|
end
|
49
49
|
|
50
|
+
# @return [Boolean] Is this field a predefined introspection field?
|
51
|
+
def introspection?
|
52
|
+
@introspection
|
53
|
+
end
|
54
|
+
|
50
55
|
alias :mutation :resolver
|
51
56
|
|
52
57
|
# @return [Boolean] Apply tracing to this field? (Default: skip scalars, this is the override value)
|
@@ -551,34 +556,36 @@ module GraphQL
|
|
551
556
|
begin
|
552
557
|
# Unwrap the GraphQL object to get the application object.
|
553
558
|
application_object = object.object
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
extended_obj.
|
559
|
+
ctx.schema.after_lazy(self.authorized?(application_object, args, ctx)) do |is_authorized|
|
560
|
+
if is_authorized
|
561
|
+
# Apply field extensions
|
562
|
+
with_extensions(object, args, ctx) do |extended_obj, extended_args|
|
563
|
+
field_receiver = if @resolver_class
|
564
|
+
resolver_obj = if extended_obj.is_a?(GraphQL::Schema::Object)
|
565
|
+
extended_obj.object
|
566
|
+
else
|
567
|
+
extended_obj
|
568
|
+
end
|
569
|
+
@resolver_class.new(object: resolver_obj, context: ctx, field: self)
|
560
570
|
else
|
561
571
|
extended_obj
|
562
572
|
end
|
563
|
-
@resolver_class.new(object: resolver_obj, context: ctx, field: self)
|
564
|
-
else
|
565
|
-
extended_obj
|
566
|
-
end
|
567
573
|
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
574
|
+
if field_receiver.respond_to?(@resolver_method)
|
575
|
+
# Call the method with kwargs, if there are any
|
576
|
+
if extended_args.any?
|
577
|
+
field_receiver.public_send(@resolver_method, **extended_args)
|
578
|
+
else
|
579
|
+
field_receiver.public_send(@resolver_method)
|
580
|
+
end
|
572
581
|
else
|
573
|
-
field_receiver
|
582
|
+
resolve_field_method(field_receiver, extended_args, ctx)
|
574
583
|
end
|
575
|
-
else
|
576
|
-
resolve_field_method(field_receiver, extended_args, ctx)
|
577
584
|
end
|
585
|
+
else
|
586
|
+
err = GraphQL::UnauthorizedFieldError.new(object: application_object, type: object.class, context: ctx, field: self)
|
587
|
+
ctx.schema.unauthorized_field(err)
|
578
588
|
end
|
579
|
-
else
|
580
|
-
err = GraphQL::UnauthorizedFieldError.new(object: application_object, type: object.class, context: ctx, field: self)
|
581
|
-
ctx.schema.unauthorized_field(err)
|
582
589
|
end
|
583
590
|
rescue GraphQL::UnauthorizedFieldError => err
|
584
591
|
err.field ||= self
|
@@ -663,10 +670,12 @@ module GraphQL
|
|
663
670
|
loaded_value = if loads && !arg_defn.from_resolver?
|
664
671
|
if arg_defn.type.list?
|
665
672
|
loaded_values = value.map { |val| load_application_object(arg_defn, loads, val, field_ctx.query.context) }
|
666
|
-
|
673
|
+
field_ctx.schema.after_any_lazies(loaded_values) { |result| result }
|
667
674
|
else
|
668
675
|
load_application_object(arg_defn, loads, value, field_ctx.query.context)
|
669
676
|
end
|
677
|
+
elsif arg_defn.type.list? && value.is_a?(Array)
|
678
|
+
field_ctx.schema.after_any_lazies(value, &:itself)
|
670
679
|
else
|
671
680
|
value
|
672
681
|
end
|
@@ -10,12 +10,13 @@ module GraphQL
|
|
10
10
|
|
11
11
|
include GraphQL::Dig
|
12
12
|
|
13
|
-
def initialize(
|
13
|
+
def initialize(arguments = nil, ruby_kwargs: nil, context:, defaults_used:)
|
14
14
|
@context = context
|
15
15
|
if ruby_kwargs
|
16
16
|
@ruby_style_hash = ruby_kwargs
|
17
|
+
@arguments = arguments
|
17
18
|
else
|
18
|
-
@arguments = self.class.arguments_class.new(
|
19
|
+
@arguments = self.class.arguments_class.new(arguments, context: context, defaults_used: defaults_used)
|
19
20
|
# Symbolized, underscored hash:
|
20
21
|
@ruby_style_hash = @arguments.to_kwargs
|
21
22
|
end
|
@@ -56,7 +57,7 @@ module GraphQL
|
|
56
57
|
# @return [GraphQL::Query::Context] The context for this query
|
57
58
|
attr_reader :context
|
58
59
|
|
59
|
-
# @return [GraphQL::Query::Arguments] The underlying arguments instance
|
60
|
+
# @return [GraphQL::Query::Arguments, GraphQL::Execution::Interpereter::Arguments] The underlying arguments instance
|
60
61
|
attr_reader :arguments
|
61
62
|
|
62
63
|
# Ruby-like hash behaviors, read-only
|
@@ -208,10 +209,12 @@ module GraphQL
|
|
208
209
|
return nil
|
209
210
|
end
|
210
211
|
|
211
|
-
|
212
|
+
arguments = coerce_arguments(nil, value, ctx)
|
212
213
|
|
213
|
-
|
214
|
-
|
214
|
+
ctx.schema.after_lazy(arguments) do |resolved_arguments|
|
215
|
+
input_obj_instance = self.new(resolved_arguments, ruby_kwargs: resolved_arguments.keyword_arguments, context: ctx, defaults_used: nil)
|
216
|
+
input_obj_instance.prepare
|
217
|
+
end
|
215
218
|
end
|
216
219
|
|
217
220
|
# It's funny to think of a _result_ of an input object.
|
@@ -14,6 +14,7 @@ module GraphQL
|
|
14
14
|
include GraphQL::Schema::Member::RelayShortcuts
|
15
15
|
include GraphQL::Schema::Member::Scoped
|
16
16
|
include GraphQL::Schema::Member::HasAstNode
|
17
|
+
include GraphQL::Schema::Member::HasUnresolvedTypeError
|
17
18
|
|
18
19
|
# Methods defined in this block will be:
|
19
20
|
# - Added as class methods to this interface
|
@@ -74,6 +75,10 @@ module GraphQL
|
|
74
75
|
if overridden_graphql_name
|
75
76
|
child_class.graphql_name(overridden_graphql_name)
|
76
77
|
end
|
78
|
+
# If interfaces are mixed into each other, only define this class once
|
79
|
+
if !child_class.const_defined?(:UnresolvedTypeError, false)
|
80
|
+
add_unresolved_type_error(child_class)
|
81
|
+
end
|
77
82
|
elsif child_class < GraphQL::Schema::Object
|
78
83
|
# This is being included into an object type, make sure it's using `implements(...)`
|
79
84
|
backtrace_line = caller(0, 10).find { |line| line.include?("schema/object.rb") && line.include?("in `implements'")}
|