graphql 1.1.0 → 1.2.0
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/analysis/analyze_query.rb +4 -2
- data/lib/graphql/analysis/field_usage.rb +4 -4
- data/lib/graphql/analysis/query_complexity.rb +16 -21
- data/lib/graphql/argument.rb +13 -6
- data/lib/graphql/base_type.rb +2 -1
- data/lib/graphql/compatibility/execution_specification.rb +76 -0
- data/lib/graphql/compatibility/query_parser_specification.rb +16 -2
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -5
- data/lib/graphql/compatibility/schema_parser_specification.rb +6 -0
- data/lib/graphql/define/assign_argument.rb +8 -2
- data/lib/graphql/define/instance_definable.rb +12 -15
- data/lib/graphql/directive.rb +2 -1
- data/lib/graphql/enum_type.rb +5 -7
- data/lib/graphql/field.rb +6 -11
- data/lib/graphql/field/resolve.rb +1 -0
- data/lib/graphql/input_object_type.rb +9 -9
- data/lib/graphql/interface_type.rb +2 -1
- data/lib/graphql/internal_representation.rb +1 -0
- data/lib/graphql/internal_representation/node.rb +31 -9
- data/lib/graphql/internal_representation/rewrite.rb +26 -26
- data/lib/graphql/internal_representation/selections.rb +41 -0
- data/lib/graphql/introspection/input_value_type.rb +6 -2
- data/lib/graphql/language/generation.rb +2 -0
- data/lib/graphql/language/lexer.rl +4 -0
- data/lib/graphql/language/nodes.rb +3 -0
- data/lib/graphql/language/parser.rb +525 -509
- data/lib/graphql/language/parser.y +2 -0
- data/lib/graphql/object_type.rb +2 -2
- data/lib/graphql/query.rb +21 -0
- data/lib/graphql/query/context.rb +52 -4
- data/lib/graphql/query/serial_execution.rb +3 -4
- data/lib/graphql/query/serial_execution/field_resolution.rb +35 -36
- data/lib/graphql/query/serial_execution/operation_resolution.rb +9 -15
- data/lib/graphql/query/serial_execution/selection_resolution.rb +14 -11
- data/lib/graphql/query/serial_execution/value_resolution.rb +18 -17
- data/lib/graphql/query/variables.rb +1 -1
- data/lib/graphql/relay/mutation.rb +5 -8
- data/lib/graphql/scalar_type.rb +1 -2
- data/lib/graphql/schema.rb +2 -13
- data/lib/graphql/schema/build_from_definition.rb +28 -13
- data/lib/graphql/schema/loader.rb +4 -1
- data/lib/graphql/schema/printer.rb +10 -3
- data/lib/graphql/schema/timeout_middleware.rb +18 -2
- data/lib/graphql/schema/unique_within_type.rb +6 -3
- data/lib/graphql/static_validation/literal_validator.rb +3 -1
- data/lib/graphql/union_type.rb +1 -2
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -0
- data/spec/graphql/analysis/analyze_query_spec.rb +6 -8
- data/spec/graphql/argument_spec.rb +18 -0
- data/spec/graphql/define/assign_argument_spec.rb +48 -0
- data/spec/graphql/define/instance_definable_spec.rb +4 -2
- data/spec/graphql/execution_error_spec.rb +66 -0
- data/spec/graphql/input_object_type_spec.rb +81 -0
- data/spec/graphql/internal_representation/rewrite_spec.rb +104 -21
- data/spec/graphql/introspection/input_value_type_spec.rb +43 -6
- data/spec/graphql/introspection/schema_type_spec.rb +1 -0
- data/spec/graphql/introspection/type_type_spec.rb +2 -0
- data/spec/graphql/language/generation_spec.rb +3 -2
- data/spec/graphql/query/arguments_spec.rb +17 -4
- data/spec/graphql/query/context_spec.rb +23 -0
- data/spec/graphql/query/variables_spec.rb +15 -1
- data/spec/graphql/relay/mutation_spec.rb +42 -2
- data/spec/graphql/schema/build_from_definition_spec.rb +4 -2
- data/spec/graphql/schema/loader_spec.rb +59 -1
- data/spec/graphql/schema/printer_spec.rb +2 -0
- data/spec/graphql/schema/reduce_types_spec.rb +1 -1
- data/spec/graphql/schema/timeout_middleware_spec.rb +2 -2
- data/spec/graphql/schema/unique_within_type_spec.rb +9 -0
- data/spec/graphql/schema/validation_spec.rb +15 -3
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +122 -0
- data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +78 -0
- data/spec/support/dairy_app.rb +9 -0
- data/spec/support/minimum_input_object.rb +4 -0
- data/spec/support/star_wars_schema.rb +1 -1
- metadata +5 -5
- data/lib/graphql/query/serial_execution/execution_context.rb +0 -37
- data/spec/graphql/query/serial_execution/execution_context_spec.rb +0 -54
@@ -55,9 +55,9 @@ module GraphQL
|
|
55
55
|
input_field: GraphQL::Define::AssignArgument,
|
56
56
|
return_field: GraphQL::Define::AssignObjectField,
|
57
57
|
)
|
58
|
-
|
59
|
-
lazy_defined_attr_accessor :fields, :arguments, :return_type
|
58
|
+
attr_accessor :name, :description, :fields, :arguments, :return_type
|
60
59
|
|
60
|
+
ensure_defined(:name, :description, :fields, :arguments, :return_type, :resolve=, :field, :result_class, :input_type)
|
61
61
|
# For backwards compat, but do we need this separate API?
|
62
62
|
alias :return_fields :fields
|
63
63
|
alias :input_fields :arguments
|
@@ -75,13 +75,11 @@ module GraphQL
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def resolve=(new_resolve_proc)
|
78
|
-
ensure_defined
|
79
78
|
@resolve_proc = MutationResolve.new(self, new_resolve_proc, wrap_result: has_generated_return_type?)
|
80
79
|
end
|
81
80
|
|
82
81
|
def field
|
83
82
|
@field ||= begin
|
84
|
-
ensure_defined
|
85
83
|
relay_mutation = self
|
86
84
|
field_resolve_proc = @resolve_proc
|
87
85
|
GraphQL::Field.define do
|
@@ -95,7 +93,6 @@ module GraphQL
|
|
95
93
|
end
|
96
94
|
|
97
95
|
def return_type
|
98
|
-
ensure_defined
|
99
96
|
@return_type ||= begin
|
100
97
|
@has_generated_return_type = true
|
101
98
|
relay_mutation = self
|
@@ -113,14 +110,15 @@ module GraphQL
|
|
113
110
|
|
114
111
|
def input_type
|
115
112
|
@input_type ||= begin
|
116
|
-
ensure_defined
|
117
113
|
relay_mutation = self
|
118
114
|
GraphQL::InputObjectType.define do
|
119
115
|
name("#{relay_mutation.name}Input")
|
120
116
|
description("Autogenerated input type of #{relay_mutation.name}")
|
121
117
|
input_field :clientMutationId, types.String, "A unique identifier for the client performing the mutation."
|
122
118
|
relay_mutation.input_fields.each do |input_field_name, field_obj|
|
123
|
-
|
119
|
+
kwargs = {}
|
120
|
+
kwargs[:default_value] = field_obj.default_value if field_obj.default_value?
|
121
|
+
input_field input_field_name, field_obj.type, field_obj.description, **kwargs
|
124
122
|
end
|
125
123
|
mutation(relay_mutation)
|
126
124
|
end
|
@@ -129,7 +127,6 @@ module GraphQL
|
|
129
127
|
|
130
128
|
def result_class
|
131
129
|
@result_class ||= begin
|
132
|
-
ensure_defined
|
133
130
|
Result.define_subclass(self)
|
134
131
|
end
|
135
132
|
end
|
data/lib/graphql/scalar_type.rb
CHANGED
@@ -35,6 +35,7 @@ module GraphQL
|
|
35
35
|
#
|
36
36
|
class ScalarType < GraphQL::BaseType
|
37
37
|
accepts_definitions :coerce, :coerce_input, :coerce_result
|
38
|
+
ensure_defined :coerce_non_null_input, :coerce_result
|
38
39
|
|
39
40
|
def coerce=(proc)
|
40
41
|
self.coerce_input = proc
|
@@ -50,7 +51,6 @@ module GraphQL
|
|
50
51
|
end
|
51
52
|
|
52
53
|
def coerce_non_null_input(value)
|
53
|
-
ensure_defined
|
54
54
|
@coerce_input_proc.call(value)
|
55
55
|
end
|
56
56
|
|
@@ -61,7 +61,6 @@ module GraphQL
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def coerce_result(value)
|
64
|
-
ensure_defined
|
65
64
|
@coerce_result_proc ? @coerce_result_proc.call(value) : value
|
66
65
|
end
|
67
66
|
|
data/lib/graphql/schema.rb
CHANGED
@@ -61,7 +61,7 @@ module GraphQL
|
|
61
61
|
middleware: ->(schema, middleware) { schema.middleware << middleware },
|
62
62
|
rescue_from: ->(schema, err_class, &block) { schema.rescue_from(err_class, &block)}
|
63
63
|
|
64
|
-
|
64
|
+
attr_accessor \
|
65
65
|
:query, :mutation, :subscription,
|
66
66
|
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
67
67
|
:max_depth, :max_complexity,
|
@@ -99,17 +99,16 @@ module GraphQL
|
|
99
99
|
end
|
100
100
|
|
101
101
|
def rescue_from(*args, &block)
|
102
|
-
ensure_defined
|
103
102
|
rescue_middleware.rescue_from(*args, &block)
|
104
103
|
end
|
105
104
|
|
106
105
|
def remove_handler(*args, &block)
|
107
|
-
ensure_defined
|
108
106
|
rescue_middleware.remove_handler(*args, &block)
|
109
107
|
end
|
110
108
|
|
111
109
|
def define(**kwargs, &block)
|
112
110
|
super
|
111
|
+
ensure_defined
|
113
112
|
all_types = orphan_types + [query, mutation, subscription, GraphQL::Introspection::SchemaType]
|
114
113
|
@types = GraphQL::Schema::ReduceTypes.reduce(all_types.compact)
|
115
114
|
|
@@ -151,7 +150,6 @@ module GraphQL
|
|
151
150
|
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
152
151
|
# @return [GraphQL::Field, nil] The field named `field_name` on `parent_type`
|
153
152
|
def get_field(parent_type, field_name)
|
154
|
-
ensure_defined
|
155
153
|
defined_field = @instrumented_field_map.get(parent_type.name, field_name)
|
156
154
|
if defined_field
|
157
155
|
defined_field
|
@@ -167,7 +165,6 @@ module GraphQL
|
|
167
165
|
end
|
168
166
|
|
169
167
|
def type_from_ast(ast_node)
|
170
|
-
ensure_defined
|
171
168
|
GraphQL::Schema::TypeExpression.build_type(self.types, ast_node)
|
172
169
|
end
|
173
170
|
|
@@ -175,7 +172,6 @@ module GraphQL
|
|
175
172
|
# @param type_defn [GraphQL::InterfaceType, GraphQL::UnionType] the type whose members you want to retrieve
|
176
173
|
# @return [Array<GraphQL::ObjectType>] types which belong to `type_defn` in this schema
|
177
174
|
def possible_types(type_defn)
|
178
|
-
ensure_defined
|
179
175
|
@possible_types ||= GraphQL::Schema::PossibleTypes.new(self)
|
180
176
|
@possible_types.possible_types(type_defn)
|
181
177
|
end
|
@@ -213,8 +209,6 @@ module GraphQL
|
|
213
209
|
# @param ctx [GraphQL::Query::Context] The context for the current query
|
214
210
|
# @return [GraphQL::ObjectType] The type for exposing `object` in GraphQL
|
215
211
|
def resolve_type(object, ctx)
|
216
|
-
ensure_defined
|
217
|
-
|
218
212
|
if @resolve_type_proc.nil?
|
219
213
|
raise(NotImplementedError, "Can't determine GraphQL type for: #{object.inspect}, define `resolve_type (obj, ctx) -> { ... }` inside `Schema.define`.")
|
220
214
|
end
|
@@ -231,7 +225,6 @@ module GraphQL
|
|
231
225
|
end
|
232
226
|
|
233
227
|
def resolve_type=(new_resolve_type_proc)
|
234
|
-
ensure_defined
|
235
228
|
@resolve_type_proc = new_resolve_type_proc
|
236
229
|
end
|
237
230
|
|
@@ -240,7 +233,6 @@ module GraphQL
|
|
240
233
|
# @param ctx [GraphQL::Query::Context] The context for the current query
|
241
234
|
# @return [Any] The application object identified by `id`
|
242
235
|
def object_from_id(id, ctx)
|
243
|
-
ensure_defined
|
244
236
|
if @object_from_id_proc.nil?
|
245
237
|
raise(NotImplementedError, "Can't fetch an object for id \"#{id}\" because the schema's `object_from_id (id, ctx) -> { ... }` function is not defined")
|
246
238
|
else
|
@@ -250,7 +242,6 @@ module GraphQL
|
|
250
242
|
|
251
243
|
# @param new_proc [#call] A new callable for fetching objects by ID
|
252
244
|
def object_from_id=(new_proc)
|
253
|
-
ensure_defined
|
254
245
|
@object_from_id_proc = new_proc
|
255
246
|
end
|
256
247
|
|
@@ -260,7 +251,6 @@ module GraphQL
|
|
260
251
|
# @param ctx [GraphQL::Query::Context] the context for the current query
|
261
252
|
# @return [String] a unique identifier for `object` which clients can use to refetch it
|
262
253
|
def id_from_object(object, type, ctx)
|
263
|
-
ensure_defined
|
264
254
|
if @id_from_object_proc.nil?
|
265
255
|
raise(NotImplementedError, "Can't generate an ID for #{object.inspect} of type #{type}, schema's `id_from_object` must be defined")
|
266
256
|
else
|
@@ -270,7 +260,6 @@ module GraphQL
|
|
270
260
|
|
271
261
|
# @param new_proc [#call] A new callable for generating unique IDs
|
272
262
|
def id_from_object=(new_proc)
|
273
|
-
ensure_defined
|
274
263
|
@id_from_object_proc = new_proc
|
275
264
|
end
|
276
265
|
|
@@ -150,13 +150,23 @@ module GraphQL
|
|
150
150
|
)
|
151
151
|
end
|
152
152
|
|
153
|
+
def build_default_value(default_value)
|
154
|
+
case default_value
|
155
|
+
when GraphQL::Language::Nodes::Enum
|
156
|
+
default_value.name
|
157
|
+
when GraphQL::Language::Nodes::NullValue
|
158
|
+
nil
|
159
|
+
else
|
160
|
+
default_value
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
153
164
|
def build_input_arguments(input_object_type_definition, type_resolver)
|
154
165
|
input_object_type_definition.fields.map do |input_argument|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
input_argument.default_value
|
166
|
+
kwargs = {}
|
167
|
+
|
168
|
+
if !input_argument.default_value.nil?
|
169
|
+
kwargs[:default_value] = build_default_value(input_argument.default_value)
|
160
170
|
end
|
161
171
|
|
162
172
|
[
|
@@ -165,7 +175,7 @@ module GraphQL
|
|
165
175
|
name: input_argument.name,
|
166
176
|
type: type_resolver.call(input_argument.type),
|
167
177
|
description: input_argument.description,
|
168
|
-
|
178
|
+
**kwargs,
|
169
179
|
)
|
170
180
|
]
|
171
181
|
end
|
@@ -182,13 +192,19 @@ module GraphQL
|
|
182
192
|
|
183
193
|
def build_directive_arguments(directive_definition, type_resolver)
|
184
194
|
directive_definition.arguments.map do |directive_argument|
|
195
|
+
kwargs = {}
|
196
|
+
|
197
|
+
if !directive_argument.default_value.nil?
|
198
|
+
kwargs[:default_value] = build_default_value(directive_argument.default_value)
|
199
|
+
end
|
200
|
+
|
185
201
|
[
|
186
202
|
directive_argument.name,
|
187
203
|
GraphQL::Argument.define(
|
188
204
|
name: directive_argument.name,
|
189
205
|
type: type_resolver.call(directive_argument.type),
|
190
206
|
description: directive_argument.description,
|
191
|
-
|
207
|
+
**kwargs,
|
192
208
|
)
|
193
209
|
]
|
194
210
|
end
|
@@ -205,18 +221,17 @@ module GraphQL
|
|
205
221
|
def build_fields(field_definitions, type_resolver)
|
206
222
|
field_definitions.map do |field_definition|
|
207
223
|
field_arguments = Hash[field_definition.arguments.map do |argument|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
argument.default_value
|
224
|
+
kwargs = {}
|
225
|
+
|
226
|
+
if !argument.default_value.nil?
|
227
|
+
kwargs[:default_value] = build_default_value(argument.default_value)
|
213
228
|
end
|
214
229
|
|
215
230
|
arg = GraphQL::Argument.define(
|
216
231
|
name: argument.name,
|
217
232
|
description: argument.description,
|
218
233
|
type: type_resolver.call(argument.type),
|
219
|
-
|
234
|
+
**kwargs,
|
220
235
|
)
|
221
236
|
|
222
237
|
[argument.name, arg]
|
@@ -103,11 +103,14 @@ module GraphQL
|
|
103
103
|
}]
|
104
104
|
)
|
105
105
|
when "ARGUMENT"
|
106
|
+
kwargs = {}
|
107
|
+
kwargs[:default_value] = JSON.parse(type["defaultValue"], quirks_mode: true) if type["defaultValue"]
|
108
|
+
|
106
109
|
Argument.define(
|
107
110
|
name: type["name"],
|
108
111
|
type: type_resolver.call(type["type"]),
|
109
112
|
description: type["description"],
|
110
|
-
|
113
|
+
**kwargs
|
111
114
|
)
|
112
115
|
when "SCALAR"
|
113
116
|
type_name = type.fetch("name")
|
@@ -120,10 +120,10 @@ module GraphQL
|
|
120
120
|
end
|
121
121
|
|
122
122
|
def print_input_value(arg)
|
123
|
-
if arg.default_value
|
124
|
-
default_string = nil
|
125
|
-
else
|
123
|
+
if arg.default_value?
|
126
124
|
default_string = " = #{print_value(arg.default_value, arg.type)}"
|
125
|
+
else
|
126
|
+
default_string = nil
|
127
127
|
end
|
128
128
|
|
129
129
|
"#{arg.name}: #{arg.type.to_s}#{default_string}"
|
@@ -132,16 +132,22 @@ module GraphQL
|
|
132
132
|
def print_value(value, type)
|
133
133
|
case type
|
134
134
|
when FLOAT_TYPE
|
135
|
+
return 'null' if value.nil?
|
135
136
|
value.to_f.inspect
|
136
137
|
when INT_TYPE
|
138
|
+
return 'null' if value.nil?
|
137
139
|
value.to_i.inspect
|
138
140
|
when BOOLEAN_TYPE
|
141
|
+
return 'null' if value.nil?
|
139
142
|
(!!value).inspect
|
140
143
|
when ScalarType, ID_TYPE, STRING_TYPE
|
144
|
+
return 'null' if value.nil?
|
141
145
|
value.to_s.inspect
|
142
146
|
when EnumType
|
147
|
+
return 'null' if value.nil?
|
143
148
|
type.coerce_result(value)
|
144
149
|
when InputObjectType
|
150
|
+
return 'null' if value.nil?
|
145
151
|
fields = value.to_h.map{ |field_name, field_value|
|
146
152
|
field_type = type.input_fields.fetch(field_name.to_s).type
|
147
153
|
"#{field_name}: #{print_value(field_value, field_type)}"
|
@@ -150,6 +156,7 @@ module GraphQL
|
|
150
156
|
when NonNullType
|
151
157
|
print_value(value, type.of_type)
|
152
158
|
when ListType
|
159
|
+
return 'null' if value.nil?
|
153
160
|
"[#{value.to_a.map{ |v| print_value(v, type.of_type) }.join(", ")}]"
|
154
161
|
else
|
155
162
|
raise NotImplementedError, "Unexpected value type #{type.inspect}"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "delegate"
|
2
|
+
|
1
3
|
module GraphQL
|
2
4
|
class Schema
|
3
5
|
# This middleware will stop resolving new fields after `max_seconds` have elapsed.
|
@@ -43,14 +45,28 @@ module GraphQL
|
|
43
45
|
|
44
46
|
# This is called when a field _would_ be resolved, except that we're over the time limit.
|
45
47
|
# @return [GraphQL::Schema::TimeoutMiddleware::TimeoutError] An error whose message will be added to the `errors` key
|
46
|
-
def on_timeout(parent_type, parent_object, field_definition, field_args,
|
48
|
+
def on_timeout(parent_type, parent_object, field_definition, field_args, field_context)
|
47
49
|
err = GraphQL::Schema::TimeoutMiddleware::TimeoutError.new(parent_type, field_definition)
|
48
50
|
if @error_handler
|
49
|
-
|
51
|
+
query_proxy = TimeoutQueryProxy.new(field_context.query, field_context)
|
52
|
+
@error_handler.call(err, query_proxy)
|
50
53
|
end
|
51
54
|
err
|
52
55
|
end
|
53
56
|
|
57
|
+
# This behaves like {GraphQL::Query} but {#context} returns
|
58
|
+
# the _field-level_ context, not the query-level context.
|
59
|
+
# This means you can reliably get the `irep_node` and `path`
|
60
|
+
# from it after the fact.
|
61
|
+
class TimeoutQueryProxy < SimpleDelegator
|
62
|
+
def initialize(query, ctx)
|
63
|
+
@context = ctx
|
64
|
+
super(query)
|
65
|
+
end
|
66
|
+
|
67
|
+
attr_reader :context
|
68
|
+
end
|
69
|
+
|
54
70
|
# This error is raised when a query exceeds `max_seconds`.
|
55
71
|
# Since it's a child of {GraphQL::ExecutionError},
|
56
72
|
# its message will be added to the response's `errors` key.
|
@@ -1,14 +1,17 @@
|
|
1
1
|
module GraphQL
|
2
2
|
class Schema
|
3
3
|
module UniqueWithinType
|
4
|
-
|
4
|
+
class << self
|
5
|
+
attr_accessor :default_id_separator
|
6
|
+
end
|
7
|
+
self.default_id_separator = "-"
|
5
8
|
|
6
9
|
module_function
|
7
10
|
|
8
11
|
# @param type_name [String]
|
9
12
|
# @param object_value [Any]
|
10
13
|
# @return [String] a unique, opaque ID generated as a function of the two inputs
|
11
|
-
def encode(type_name, object_value, separator:
|
14
|
+
def encode(type_name, object_value, separator: self.default_id_separator)
|
12
15
|
object_value_str = object_value.to_s
|
13
16
|
|
14
17
|
if type_name.include?(separator) || object_value_str.include?(separator)
|
@@ -20,7 +23,7 @@ module GraphQL
|
|
20
23
|
|
21
24
|
# @param node_id [String] A unique ID generated by {.encode}
|
22
25
|
# @return [Array<(String, String)>] The type name & value passed to {.encode}
|
23
|
-
def decode(node_id, separator:
|
26
|
+
def decode(node_id, separator: self.default_id_separator)
|
24
27
|
Base64.decode64(node_id).split(separator)
|
25
28
|
end
|
26
29
|
end
|
@@ -7,7 +7,9 @@ module GraphQL
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def validate(ast_value, type)
|
10
|
-
if
|
10
|
+
if ast_value.is_a?(GraphQL::Language::Nodes::NullValue)
|
11
|
+
!type.kind.non_null?
|
12
|
+
elsif type.kind.non_null?
|
11
13
|
(!ast_value.nil?) && validate(ast_value, type.of_type)
|
12
14
|
elsif type.kind.list?
|
13
15
|
item_type = type.of_type
|
data/lib/graphql/union_type.rb
CHANGED
@@ -24,6 +24,7 @@ module GraphQL
|
|
24
24
|
#
|
25
25
|
class UnionType < GraphQL::BaseType
|
26
26
|
accepts_definitions :possible_types, :resolve_type
|
27
|
+
ensure_defined :possible_types
|
27
28
|
|
28
29
|
def kind
|
29
30
|
GraphQL::TypeKinds::UNION
|
@@ -40,8 +41,6 @@ module GraphQL
|
|
40
41
|
|
41
42
|
def possible_types
|
42
43
|
@clean_possible_types ||= begin
|
43
|
-
ensure_defined
|
44
|
-
|
45
44
|
if @dirty_possible_types.respond_to?(:map)
|
46
45
|
@dirty_possible_types.map { |type| GraphQL::BaseType.resolve_related_type(type) }
|
47
46
|
else
|
data/lib/graphql/version.rb
CHANGED
data/readme.md
CHANGED
@@ -68,3 +68,4 @@ See "Getting Started" on the [website](https://rmosolgo.github.io/graphql-ruby/)
|
|
68
68
|
- Renaming fragments from local names to unique names
|
69
69
|
- Document encrypted & versioned cursors
|
70
70
|
- Make it faster
|
71
|
+
- Is it possible to merge typed branches before resolving them? It's hard because even the branches will have branches.
|
@@ -82,14 +82,12 @@ describe GraphQL::Analysis do
|
|
82
82
|
memo ||= Hash.new { |h,k| h[k] = 0 }
|
83
83
|
if visit_type == :enter
|
84
84
|
if irep_node.ast_node.is_a?(GraphQL::Language::Nodes::Field)
|
85
|
-
irep_node.
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
memo[:field] += 1
|
92
|
-
end
|
85
|
+
if irep_node.definition.resolve_proc.is_a?(GraphQL::Relay::ConnectionResolve)
|
86
|
+
memo[:connection] ||= 0
|
87
|
+
memo[:connection] += 1
|
88
|
+
else
|
89
|
+
memo[:field] ||= 0
|
90
|
+
memo[:field] += 1
|
93
91
|
end
|
94
92
|
end
|
95
93
|
end
|