graphql 1.9.0.pre2 → 1.9.0.pre3
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.
- checksums.yaml +4 -4
- data/lib/graphql/execution/lookahead.rb +22 -13
- data/lib/graphql/language/visitor.rb +63 -52
- data/lib/graphql/query/variable_validation_error.rb +10 -1
- data/lib/graphql/schema.rb +8 -3
- data/lib/graphql/schema/field.rb +3 -2
- data/lib/graphql/schema/mutation.rb +5 -49
- data/lib/graphql/schema/resolver.rb +1 -0
- data/lib/graphql/schema/resolver/has_payload_type.rb +65 -0
- data/lib/graphql/schema/subscription.rb +97 -0
- data/lib/graphql/subscriptions.rb +15 -2
- data/lib/graphql/subscriptions/subscription_root.rb +27 -4
- data/lib/graphql/version.rb +1 -1
- data/spec/dummy/Gemfile.lock +2 -2
- data/spec/dummy/app/channels/graphql_channel.rb +4 -4
- data/spec/dummy/log/test.log +3 -0
- data/spec/graphql/execution/lookahead_spec.rb +54 -1
- data/spec/graphql/query/executor_spec.rb +15 -13
- data/spec/graphql/query_spec.rb +12 -6
- data/spec/graphql/schema/subscription_spec.rb +416 -0
- data/spec/graphql/subscriptions_spec.rb +5 -12
- metadata +291 -287
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d574e6bf6c3c4644fd85e279ddf56ab3128bef2d
|
4
|
+
data.tar.gz: a6227d0ec2ee59131b2de45ccf87c2541279543d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d91a0736831fa204240513b2cff401bf51a8ffb09739662fd95415bf2a91f53f088dcbcb026ff883d43476980260d1ab222d6bd5c969060ce279e9badf7ecb5
|
7
|
+
data.tar.gz: 0eaa0115f08cae059cb4d514fc572cf064956dda38ac87919d841b72103aa67df7f871e761375704ade18b5e77c474c99e5e514dcb098608bba7b3e629a0241d
|
@@ -40,6 +40,7 @@ module GraphQL
|
|
40
40
|
@field = field
|
41
41
|
@root_type = root_type
|
42
42
|
@query = query
|
43
|
+
@selected_type = @field ? @field.type.unwrap : root_type
|
43
44
|
end
|
44
45
|
|
45
46
|
# @return [Array<GraphQL::Language::Nodes::Field>]
|
@@ -72,16 +73,10 @@ module GraphQL
|
|
72
73
|
# Like {#selects?}, but can be used for chaining.
|
73
74
|
# It returns a null object (check with {#selected?})
|
74
75
|
# @return [GraphQL::Execution::Lookahead]
|
75
|
-
def selection(field_name, arguments: nil)
|
76
|
+
def selection(field_name, selected_type: @selected_type, arguments: nil)
|
76
77
|
next_field_name = normalize_name(field_name)
|
77
78
|
|
78
|
-
|
79
|
-
@field.type.unwrap
|
80
|
-
else
|
81
|
-
@root_type
|
82
|
-
end
|
83
|
-
|
84
|
-
next_field_defn = FieldHelpers.get_field(@query.schema, next_field_owner, next_field_name)
|
79
|
+
next_field_defn = FieldHelpers.get_field(@query.schema, selected_type, next_field_name)
|
85
80
|
if next_field_defn
|
86
81
|
next_nodes = []
|
87
82
|
@ast_nodes.each do |ast_node|
|
@@ -118,7 +113,7 @@ module GraphQL
|
|
118
113
|
def selections(arguments: nil)
|
119
114
|
subselections_by_name = {}
|
120
115
|
@ast_nodes.each do |node|
|
121
|
-
find_selections(subselections_by_name, node.selections, arguments)
|
116
|
+
find_selections(subselections_by_name, @selected_type, node.selections, arguments)
|
122
117
|
end
|
123
118
|
|
124
119
|
# Items may be filtered out if `arguments` doesn't match
|
@@ -139,6 +134,10 @@ module GraphQL
|
|
139
134
|
@field && @field.original_name
|
140
135
|
end
|
141
136
|
|
137
|
+
def inspect
|
138
|
+
"#<GraphQL::Execution::Lookahead #{@field ? "@field=#{@field.path.inspect}": "@root_type=#{@root_type}"} @ast_nodes.size=#{@ast_nodes.size}>"
|
139
|
+
end
|
140
|
+
|
142
141
|
# This is returned for {Lookahead#selection} when a non-existent field is passed
|
143
142
|
class NullLookahead < Lookahead
|
144
143
|
# No inputs required here.
|
@@ -160,6 +159,10 @@ module GraphQL
|
|
160
159
|
def selections(*)
|
161
160
|
[]
|
162
161
|
end
|
162
|
+
|
163
|
+
def inspect
|
164
|
+
"#<GraphQL::Execution::Lookahead::NullLookahead>"
|
165
|
+
end
|
163
166
|
end
|
164
167
|
|
165
168
|
# A singleton, so that misses don't come with overhead.
|
@@ -184,16 +187,22 @@ module GraphQL
|
|
184
187
|
end
|
185
188
|
end
|
186
189
|
|
187
|
-
def find_selections(subselections_by_name, ast_selections, arguments)
|
190
|
+
def find_selections(subselections_by_name, selected_type, ast_selections, arguments)
|
188
191
|
ast_selections.each do |ast_selection|
|
189
192
|
case ast_selection
|
190
193
|
when GraphQL::Language::Nodes::Field
|
191
|
-
subselections_by_name[ast_selection.name] ||= selection(ast_selection.name, arguments: arguments)
|
194
|
+
subselections_by_name[ast_selection.name] ||= selection(ast_selection.name, selected_type: selected_type, arguments: arguments)
|
192
195
|
when GraphQL::Language::Nodes::InlineFragment
|
193
|
-
|
196
|
+
if (t = ast_selection.type)
|
197
|
+
# Assuming this is valid, that `t` will be found.
|
198
|
+
selected_type = @query.schema.types[t.name].metadata[:type_class]
|
199
|
+
end
|
200
|
+
find_selections(subselections_by_name, selected_type, ast_selection.selections, arguments)
|
194
201
|
when GraphQL::Language::Nodes::FragmentSpread
|
195
202
|
frag_defn = @query.fragments[ast_selection.name] || raise("Invariant: Can't look ahead to nonexistent fragment #{ast_selection.name} (found: #{@query.fragments.keys})")
|
196
|
-
|
203
|
+
# Again, assuming a valid AST
|
204
|
+
selected_type = @query.schema.types[frag_defn.type.name].metadata[:type_class]
|
205
|
+
find_selections(subselections_by_name, selected_type, frag_defn.selections, arguments)
|
197
206
|
else
|
198
207
|
raise "Invariant: Unexpected selection type: #{ast_selection.class}"
|
199
208
|
end
|
@@ -65,9 +65,16 @@ module GraphQL
|
|
65
65
|
# Visit `document` and all children, applying hooks as you go
|
66
66
|
# @return [void]
|
67
67
|
def visit
|
68
|
-
|
68
|
+
result = on_node_with_modifications(@document, nil)
|
69
|
+
@result = if result.is_a?(Array)
|
70
|
+
result.first
|
71
|
+
else
|
72
|
+
# The node wasn't modified
|
73
|
+
@document
|
74
|
+
end
|
69
75
|
end
|
70
76
|
|
77
|
+
# Call the user-defined handler for `node`.
|
71
78
|
def visit_node(node, parent)
|
72
79
|
public_send(node.visit_method, node, parent)
|
73
80
|
end
|
@@ -80,77 +87,81 @@ module GraphQL
|
|
80
87
|
# For compatibility, it calls hook procs, too.
|
81
88
|
# @param node [GraphQL::Language::Nodes::AbstractNode] the node being visited
|
82
89
|
# @param parent [GraphQL::Language::Nodes::AbstractNode, nil] the previously-visited node, or `nil` if this is the root node.
|
83
|
-
# @return [
|
90
|
+
# @return [Array, nil] If there were modifications, it returns an array of new nodes, otherwise, it returns `nil`.
|
84
91
|
def on_abstract_node(node, parent)
|
85
92
|
if node == DELETE_NODE
|
86
93
|
# This might be passed to `super(DELETE_NODE, ...)`
|
87
94
|
# by a user hook, don't want to keep visiting in that case.
|
88
|
-
|
95
|
+
nil
|
89
96
|
else
|
90
97
|
# Run hooks if there are any
|
91
|
-
|
98
|
+
new_node = node
|
99
|
+
begin_hooks_ok = @visitors.none? || begin_visit(new_node, parent)
|
92
100
|
if begin_hooks_ok
|
93
101
|
node.children.each do |child_node|
|
94
|
-
new_child_and_node = on_node_with_modifications(child_node,
|
102
|
+
new_child_and_node = on_node_with_modifications(child_node, new_node)
|
95
103
|
# Reassign `node` in case the child hook makes a modification
|
96
104
|
if new_child_and_node.is_a?(Array)
|
97
|
-
|
105
|
+
new_node = new_child_and_node[1]
|
98
106
|
end
|
99
107
|
end
|
100
108
|
end
|
101
|
-
@visitors.any? && end_visit(
|
102
|
-
|
109
|
+
@visitors.any? && end_visit(new_node, parent)
|
110
|
+
|
111
|
+
if new_node.equal?(node)
|
112
|
+
nil
|
113
|
+
else
|
114
|
+
[new_node, parent]
|
115
|
+
end
|
103
116
|
end
|
104
117
|
end
|
105
118
|
|
106
119
|
# We don't use `alias` here because it breaks `super`
|
107
|
-
def self.make_visit_method(node_method
|
108
|
-
class_eval(<<-
|
120
|
+
def self.make_visit_method(node_method)
|
121
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
109
122
|
def #{node_method}(node, parent)
|
110
|
-
|
123
|
+
child_mod = on_abstract_node(node, parent)
|
124
|
+
# If visiting the children returned changes, continue passing those.
|
125
|
+
child_mod || [node, parent]
|
111
126
|
end
|
112
|
-
|
127
|
+
RUBY
|
113
128
|
end
|
114
129
|
|
115
|
-
make_visit_method :on_argument
|
116
|
-
make_visit_method :on_directive
|
117
|
-
make_visit_method :on_directive_definition
|
118
|
-
make_visit_method :on_directive_location
|
119
|
-
make_visit_method :on_document
|
120
|
-
make_visit_method :on_enum
|
121
|
-
make_visit_method :on_enum_type_definition
|
122
|
-
make_visit_method :on_enum_type_extension
|
123
|
-
make_visit_method :on_enum_value_definition
|
124
|
-
make_visit_method :on_field
|
125
|
-
make_visit_method :on_field_definition
|
126
|
-
make_visit_method :on_fragment_definition
|
127
|
-
make_visit_method :on_fragment_spread
|
128
|
-
make_visit_method :on_inline_fragment
|
129
|
-
make_visit_method :on_input_object
|
130
|
-
make_visit_method :on_input_object_type_definition
|
131
|
-
make_visit_method :on_input_object_type_extension
|
132
|
-
make_visit_method :on_input_value_definition
|
133
|
-
make_visit_method :on_interface_type_definition
|
134
|
-
make_visit_method :on_interface_type_extension
|
135
|
-
make_visit_method :on_list_type
|
136
|
-
make_visit_method :on_non_null_type
|
137
|
-
make_visit_method :on_null_value
|
138
|
-
make_visit_method :on_object_type_definition
|
139
|
-
make_visit_method :on_object_type_extension
|
140
|
-
make_visit_method :on_operation_definition
|
141
|
-
make_visit_method :on_scalar_type_definition
|
142
|
-
make_visit_method :on_scalar_type_extension
|
143
|
-
make_visit_method :on_schema_definition
|
144
|
-
make_visit_method :on_schema_extension
|
145
|
-
make_visit_method :on_type_name
|
146
|
-
make_visit_method :on_union_type_definition
|
147
|
-
make_visit_method :on_union_type_extension
|
148
|
-
make_visit_method :on_variable_definition
|
149
|
-
make_visit_method :on_variable_identifier
|
150
|
-
|
151
|
-
def visit_node(node, parent)
|
152
|
-
public_send(node.visit_method, node, parent)
|
153
|
-
end
|
130
|
+
make_visit_method :on_argument
|
131
|
+
make_visit_method :on_directive
|
132
|
+
make_visit_method :on_directive_definition
|
133
|
+
make_visit_method :on_directive_location
|
134
|
+
make_visit_method :on_document
|
135
|
+
make_visit_method :on_enum
|
136
|
+
make_visit_method :on_enum_type_definition
|
137
|
+
make_visit_method :on_enum_type_extension
|
138
|
+
make_visit_method :on_enum_value_definition
|
139
|
+
make_visit_method :on_field
|
140
|
+
make_visit_method :on_field_definition
|
141
|
+
make_visit_method :on_fragment_definition
|
142
|
+
make_visit_method :on_fragment_spread
|
143
|
+
make_visit_method :on_inline_fragment
|
144
|
+
make_visit_method :on_input_object
|
145
|
+
make_visit_method :on_input_object_type_definition
|
146
|
+
make_visit_method :on_input_object_type_extension
|
147
|
+
make_visit_method :on_input_value_definition
|
148
|
+
make_visit_method :on_interface_type_definition
|
149
|
+
make_visit_method :on_interface_type_extension
|
150
|
+
make_visit_method :on_list_type
|
151
|
+
make_visit_method :on_non_null_type
|
152
|
+
make_visit_method :on_null_value
|
153
|
+
make_visit_method :on_object_type_definition
|
154
|
+
make_visit_method :on_object_type_extension
|
155
|
+
make_visit_method :on_operation_definition
|
156
|
+
make_visit_method :on_scalar_type_definition
|
157
|
+
make_visit_method :on_scalar_type_extension
|
158
|
+
make_visit_method :on_schema_definition
|
159
|
+
make_visit_method :on_schema_extension
|
160
|
+
make_visit_method :on_type_name
|
161
|
+
make_visit_method :on_union_type_definition
|
162
|
+
make_visit_method :on_union_type_extension
|
163
|
+
make_visit_method :on_variable_definition
|
164
|
+
make_visit_method :on_variable_identifier
|
154
165
|
|
155
166
|
private
|
156
167
|
|
@@ -177,7 +188,7 @@ module GraphQL
|
|
177
188
|
# The user-provided hook didn't make any modifications.
|
178
189
|
# In fact, the hook might have returned who-knows-what, so
|
179
190
|
# ignore the return value and use the original values.
|
180
|
-
|
191
|
+
new_node_and_new_parent
|
181
192
|
end
|
182
193
|
end
|
183
194
|
|
@@ -14,7 +14,16 @@ module GraphQL
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def to_h
|
17
|
-
|
17
|
+
# It is possible there are other extension items in this error, so handle
|
18
|
+
# a one level deep merge explicitly. However beyond that only show the
|
19
|
+
# latest value and problems.
|
20
|
+
super.merge({ "extensions" => { "value" => value, "problems" => validation_result.problems }}) do |key, oldValue, newValue|
|
21
|
+
if oldValue.respond_to? merge
|
22
|
+
oldValue.merge(newValue)
|
23
|
+
else
|
24
|
+
newValue
|
25
|
+
end
|
26
|
+
end
|
18
27
|
end
|
19
28
|
end
|
20
29
|
end
|
data/lib/graphql/schema.rb
CHANGED
@@ -42,6 +42,7 @@ require "graphql/schema/directive/transform"
|
|
42
42
|
require "graphql/schema/resolver"
|
43
43
|
require "graphql/schema/mutation"
|
44
44
|
require "graphql/schema/relay_classic_mutation"
|
45
|
+
require "graphql/schema/subscription"
|
45
46
|
|
46
47
|
module GraphQL
|
47
48
|
# A GraphQL schema which may be queried with {GraphQL::Query}.
|
@@ -184,7 +185,7 @@ module GraphQL
|
|
184
185
|
@introspection_namespace = nil
|
185
186
|
@introspection_system = nil
|
186
187
|
@interpeter = false
|
187
|
-
@error_bubbling =
|
188
|
+
@error_bubbling = false
|
188
189
|
end
|
189
190
|
|
190
191
|
# @return [Boolean] True if using the new {GraphQL::Execution::Interpreter}
|
@@ -915,11 +916,15 @@ module GraphQL
|
|
915
916
|
end
|
916
917
|
|
917
918
|
def resolve_type(type, obj, ctx)
|
918
|
-
|
919
|
+
if type.kind.object?
|
920
|
+
type
|
921
|
+
else
|
922
|
+
raise NotImplementedError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types or Interface types (tried to resolve: #{type.name})"
|
923
|
+
end
|
919
924
|
end
|
920
925
|
|
921
926
|
def object_from_id(node_id, ctx)
|
922
|
-
raise NotImplementedError, "#{self.name}.object_from_id(node_id, ctx) must be implemented to
|
927
|
+
raise NotImplementedError, "#{self.name}.object_from_id(node_id, ctx) must be implemented to load by ID (tried to load from id `#{node_id}`)"
|
923
928
|
end
|
924
929
|
|
925
930
|
def id_from_object(object, type, ctx)
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -59,10 +59,11 @@ module GraphQL
|
|
59
59
|
# It also normalizes positional arguments into keywords for {Schema::Field#initialize}.
|
60
60
|
# @param resolver [Class] A {GraphQL::Schema::Resolver} class to use for field configuration
|
61
61
|
# @param mutation [Class] A {GraphQL::Schema::Mutation} class to use for field configuration
|
62
|
+
# @param subscription [Class] A {GraphQL::Schema::Subscription} class to use for field configuration
|
62
63
|
# @return [GraphQL::Schema:Field] an instance of `self
|
63
64
|
# @see {.initialize} for other options
|
64
|
-
def self.from_options(name = nil, type = nil, desc = nil, resolver: nil, mutation: nil,
|
65
|
-
if (parent_config = resolver || mutation)
|
65
|
+
def self.from_options(name = nil, type = nil, desc = nil, resolver: nil, mutation: nil, subscription: nil,**kwargs, &block)
|
66
|
+
if (parent_config = resolver || mutation || subscription)
|
66
67
|
# Get the parent config, merge in local overrides
|
67
68
|
kwargs = parent_config.field_options.merge(kwargs)
|
68
69
|
# Add a reference to that parent class
|
@@ -60,6 +60,7 @@ module GraphQL
|
|
60
60
|
#
|
61
61
|
class Mutation < GraphQL::Schema::Resolver
|
62
62
|
extend GraphQL::Schema::Member::HasFields
|
63
|
+
extend GraphQL::Schema::Resolver::HasPayloadType
|
63
64
|
|
64
65
|
class << self
|
65
66
|
# Override this method to handle legacy-style usages of `MyMutation.field`
|
@@ -71,62 +72,17 @@ module GraphQL
|
|
71
72
|
end
|
72
73
|
end
|
73
74
|
|
74
|
-
# Call this method to get the derived return type of the mutation,
|
75
|
-
# or use it as a configuration method to assign a return type
|
76
|
-
# instead of generating one.
|
77
|
-
# @param new_payload_type [Class, nil] If a type definition class is provided, it will be used as the return type of the mutation field
|
78
|
-
# @return [Class] The object type which this mutation returns.
|
79
|
-
def payload_type(new_payload_type = nil)
|
80
|
-
if new_payload_type
|
81
|
-
@payload_type = new_payload_type
|
82
|
-
end
|
83
|
-
@payload_type ||= generate_payload_type
|
84
|
-
end
|
85
|
-
|
86
|
-
alias :type :payload_type
|
87
|
-
alias :type_expr :payload_type
|
88
|
-
|
89
|
-
def field_class(new_class = nil)
|
90
|
-
if new_class
|
91
|
-
@field_class = new_class
|
92
|
-
else
|
93
|
-
@field_class || find_inherited_method(:field_class, GraphQL::Schema::Field)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
# An object class to use for deriving return types
|
98
|
-
# @param new_class [Class, nil] Defaults to {GraphQL::Schema::Object}
|
99
|
-
# @return [Class]
|
100
|
-
def object_class(new_class = nil)
|
101
|
-
if new_class
|
102
|
-
@object_class = new_class
|
103
|
-
end
|
104
|
-
@object_class || (superclass.respond_to?(:object_class) ? superclass.object_class : GraphQL::Schema::Object)
|
105
|
-
end
|
106
|
-
|
107
75
|
def visible?(context)
|
108
76
|
true
|
109
77
|
end
|
110
78
|
|
111
79
|
private
|
112
80
|
|
113
|
-
#
|
114
|
-
# This value will be cached as `{.payload_type}`.
|
115
|
-
# Override this hook to customize return type generation.
|
81
|
+
# Override this to attach self as `mutation`
|
116
82
|
def generate_payload_type
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
Class.new(object_class) do
|
121
|
-
graphql_name("#{mutation_name}Payload")
|
122
|
-
description("Autogenerated return type of #{mutation_name}")
|
123
|
-
mutation(mutation_class)
|
124
|
-
mutation_fields.each do |name, f|
|
125
|
-
# Reattach the already-defined field here
|
126
|
-
# (The field's `.owner` will still point to the mutation, not the object type, I think)
|
127
|
-
add_field(f)
|
128
|
-
end
|
129
|
-
end
|
83
|
+
payload_class = super
|
84
|
+
payload_class.mutation(self)
|
85
|
+
payload_class
|
130
86
|
end
|
131
87
|
end
|
132
88
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
class Schema
|
5
|
+
class Resolver
|
6
|
+
# Adds `field(...)` helper to resolvers so that they can
|
7
|
+
# generate payload types.
|
8
|
+
#
|
9
|
+
# Or, an already-defined one can be attached with `payload_type(...)`.
|
10
|
+
module HasPayloadType
|
11
|
+
# Call this method to get the derived return type of the mutation,
|
12
|
+
# or use it as a configuration method to assign a return type
|
13
|
+
# instead of generating one.
|
14
|
+
# @param new_payload_type [Class, nil] If a type definition class is provided, it will be used as the return type of the mutation field
|
15
|
+
# @return [Class] The object type which this mutation returns.
|
16
|
+
def payload_type(new_payload_type = nil)
|
17
|
+
if new_payload_type
|
18
|
+
@payload_type = new_payload_type
|
19
|
+
end
|
20
|
+
@payload_type ||= generate_payload_type
|
21
|
+
end
|
22
|
+
|
23
|
+
alias :type :payload_type
|
24
|
+
alias :type_expr :payload_type
|
25
|
+
|
26
|
+
def field_class(new_class = nil)
|
27
|
+
if new_class
|
28
|
+
@field_class = new_class
|
29
|
+
else
|
30
|
+
@field_class || find_inherited_method(:field_class, GraphQL::Schema::Field)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# An object class to use for deriving return types
|
35
|
+
# @param new_class [Class, nil] Defaults to {GraphQL::Schema::Object}
|
36
|
+
# @return [Class]
|
37
|
+
def object_class(new_class = nil)
|
38
|
+
if new_class
|
39
|
+
@object_class = new_class
|
40
|
+
end
|
41
|
+
@object_class || (superclass.respond_to?(:object_class) ? superclass.object_class : GraphQL::Schema::Object)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# Build a subclass of {.object_class} based on `self`.
|
47
|
+
# This value will be cached as `{.payload_type}`.
|
48
|
+
# Override this hook to customize return type generation.
|
49
|
+
def generate_payload_type
|
50
|
+
resolver_name = graphql_name
|
51
|
+
resolver_fields = fields
|
52
|
+
Class.new(object_class) do
|
53
|
+
graphql_name("#{resolver_name}Payload")
|
54
|
+
description("Autogenerated return type of #{resolver_name}")
|
55
|
+
resolver_fields.each do |name, f|
|
56
|
+
# Reattach the already-defined field here
|
57
|
+
# (The field's `.owner` will still point to the mutation, not the object type, I think)
|
58
|
+
add_field(f)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|