graphql 0.19.3 → 0.19.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql/analysis/max_query_complexity.rb +1 -1
- data/lib/graphql/analysis/max_query_depth.rb +1 -1
- data/lib/graphql/boolean_type.rb +2 -2
- data/lib/graphql/define/instance_definable.rb +2 -2
- data/lib/graphql/enum_type.rb +3 -3
- data/lib/graphql/field.rb +6 -6
- data/lib/graphql/float_type.rb +2 -2
- data/lib/graphql/id_type.rb +2 -2
- data/lib/graphql/input_object_type.rb +1 -1
- data/lib/graphql/int_type.rb +2 -2
- data/lib/graphql/internal_representation/rewrite.rb +12 -12
- data/lib/graphql/introspection/arguments_field.rb +1 -1
- data/lib/graphql/introspection/enum_value_type.rb +1 -1
- data/lib/graphql/introspection/enum_values_field.rb +1 -1
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/fields_field.rb +1 -1
- data/lib/graphql/introspection/input_fields_field.rb +1 -1
- data/lib/graphql/introspection/input_value_type.rb +2 -2
- data/lib/graphql/introspection/interfaces_field.rb +1 -1
- data/lib/graphql/introspection/of_type_field.rb +1 -1
- data/lib/graphql/introspection/possible_types_field.rb +1 -1
- data/lib/graphql/introspection/schema_field.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +5 -5
- data/lib/graphql/introspection/type_by_name_field.rb +1 -1
- data/lib/graphql/introspection/type_type.rb +6 -6
- data/lib/graphql/introspection/typename_field.rb +1 -1
- data/lib/graphql/language.rb +1 -0
- data/lib/graphql/language/comments.rb +44 -0
- data/lib/graphql/language/definition_slice.rb +1 -1
- data/lib/graphql/language/generation.rb +35 -12
- data/lib/graphql/language/lexer.rb +29 -10
- data/lib/graphql/language/lexer.rl +25 -6
- data/lib/graphql/language/nodes.rb +30 -23
- data/lib/graphql/language/parser.rb +33 -14
- data/lib/graphql/language/parser.y +33 -14
- data/lib/graphql/language/parser_tests.rb +86 -2
- data/lib/graphql/language/token.rb +3 -2
- data/lib/graphql/language/visitor.rb +3 -3
- data/lib/graphql/object_type.rb +1 -1
- data/lib/graphql/query/arguments.rb +23 -2
- data/lib/graphql/query/serial_execution/field_resolution.rb +31 -14
- data/lib/graphql/relay/base_connection.rb +1 -3
- data/lib/graphql/relay/connection_type.rb +1 -1
- data/lib/graphql/relay/mutation.rb +1 -1
- data/lib/graphql/relay/relation_connection.rb +7 -3
- data/lib/graphql/scalar_type.rb +1 -1
- data/lib/graphql/schema.rb +19 -8
- data/lib/graphql/schema/loader.rb +2 -2
- data/lib/graphql/schema/printer.rb +63 -8
- data/lib/graphql/schema/timeout_middleware.rb +11 -11
- data/lib/graphql/schema/validation.rb +12 -12
- data/lib/graphql/static_validation/arguments_validator.rb +1 -1
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +3 -2
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +9 -4
- data/lib/graphql/static_validation/rules/fragments_are_named.rb +1 -1
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
- data/lib/graphql/static_validation/rules/fragments_are_used.rb +3 -3
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +2 -2
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +6 -6
- data/lib/graphql/static_validation/type_stack.rb +2 -2
- data/lib/graphql/string_type.rb +2 -2
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -1
- data/spec/graphql/analysis/analyze_query_spec.rb +3 -3
- data/spec/graphql/analysis/query_complexity_spec.rb +7 -7
- data/spec/graphql/introspection/directive_type_spec.rb +2 -2
- data/spec/graphql/introspection/introspection_query_spec.rb +26 -26
- data/spec/graphql/language/generation_spec.rb +137 -53
- data/spec/graphql/language/lexer_spec.rb +22 -0
- data/spec/graphql/language/visitor_spec.rb +6 -6
- data/spec/graphql/query/arguments_spec.rb +45 -1
- data/spec/graphql/query/context_spec.rb +4 -4
- data/spec/graphql/query/executor_spec.rb +1 -1
- data/spec/graphql/query/serial_execution/value_resolution_spec.rb +1 -1
- data/spec/graphql/relay/mutation_spec.rb +2 -2
- data/spec/graphql/relay/node_spec.rb +2 -2
- data/spec/graphql/relay/relation_connection_spec.rb +16 -0
- data/spec/graphql/schema/loader_spec.rb +2 -2
- data/spec/graphql/schema/middleware_chain_spec.rb +6 -6
- data/spec/graphql/schema/printer_spec.rb +268 -18
- data/spec/graphql/schema/rescue_middleware_spec.rb +1 -1
- data/spec/graphql/schema/timeout_middleware_spec.rb +2 -2
- data/spec/graphql/schema_spec.rb +2 -2
- data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +13 -0
- data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +1 -1
- data/spec/graphql/static_validation/type_stack_spec.rb +1 -1
- data/spec/support/dairy_app.rb +25 -25
- data/spec/support/dairy_data.rb +2 -0
- data/spec/support/star_wars_data.rb +2 -1
- data/spec/support/star_wars_schema.rb +18 -18
- metadata +19 -2
@@ -54,35 +54,52 @@ module GraphQL
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
|
58
57
|
# Get the result of:
|
59
58
|
# - Any middleware on this schema
|
60
59
|
# - The field's resolve method
|
61
60
|
# If the middleware chain returns a GraphQL::ExecutionError, its message
|
62
61
|
# is added to the "errors" key.
|
63
62
|
def get_raw_value
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
63
|
+
middlewares = execution_context.query.schema.middleware
|
64
|
+
field_resolve_step = FieldResolveStep.new(irep_node)
|
65
|
+
resolve_arguments = [parent_type, target, field, arguments, execution_context.query.context]
|
66
|
+
# only run a middleware chain if there are any middleware
|
67
|
+
if middlewares.any?
|
68
|
+
chain = GraphQL::Schema::MiddlewareChain.new(
|
69
|
+
steps: middlewares + [field_resolve_step],
|
70
|
+
arguments: resolve_arguments
|
71
|
+
)
|
72
|
+
chain.call
|
73
|
+
else
|
74
|
+
field_resolve_step.call(*resolve_arguments)
|
75
|
+
end
|
70
76
|
rescue GraphQL::ExecutionError => err
|
71
77
|
err
|
72
78
|
end
|
73
79
|
|
74
80
|
|
75
|
-
#
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
+
# A `.call`-able suitable to be the last step in a middleware chain
|
82
|
+
class FieldResolveStep
|
83
|
+
def initialize(irep_node)
|
84
|
+
@irep_node = irep_node
|
85
|
+
end
|
86
|
+
|
87
|
+
# Execute the field's resolve method
|
88
|
+
def call(_parent_type, parent_object, field_definition, field_args, context, _next = nil)
|
89
|
+
# setup
|
90
|
+
context.ast_node = @irep_node.ast_node
|
91
|
+
context.irep_node = @irep_node
|
92
|
+
|
93
|
+
# resolve
|
81
94
|
value = field_definition.resolve(parent_object, field_args, context)
|
95
|
+
|
96
|
+
# teardown
|
82
97
|
context.ast_node = nil
|
83
98
|
context.irep_node = nil
|
99
|
+
|
100
|
+
# return
|
84
101
|
value
|
85
|
-
|
102
|
+
end
|
86
103
|
end
|
87
104
|
end
|
88
105
|
end
|
@@ -74,7 +74,7 @@ module GraphQL
|
|
74
74
|
deprecate(:object, :nodes, 2016, 9)
|
75
75
|
|
76
76
|
# Provide easy access to provided arguments:
|
77
|
-
METHODS_FROM_ARGUMENTS = [:first, :after, :last, :before
|
77
|
+
METHODS_FROM_ARGUMENTS = [:first, :after, :last, :before]
|
78
78
|
|
79
79
|
# @!method first
|
80
80
|
# The value passed as `first:`, if there was one
|
@@ -84,8 +84,6 @@ module GraphQL
|
|
84
84
|
# The value passed as `last:`, if there was one
|
85
85
|
# @!method before
|
86
86
|
# The value passed as `before:`, if there was one
|
87
|
-
# @!method order
|
88
|
-
# The value passed as `order:`, if there was one
|
89
87
|
METHODS_FROM_ARGUMENTS.each do |arg_name|
|
90
88
|
define_method(arg_name) do
|
91
89
|
arguments[arg_name]
|
@@ -6,8 +6,13 @@ module GraphQL
|
|
6
6
|
# - `Sequel::Dataset`
|
7
7
|
class RelationConnection < BaseConnection
|
8
8
|
def cursor_from_node(item)
|
9
|
-
|
10
|
-
|
9
|
+
item_index = paged_nodes_array.index(item)
|
10
|
+
if item_index.nil?
|
11
|
+
raise("Can't generate cursor, item not found in connection: #{item}")
|
12
|
+
else
|
13
|
+
offset = starting_offset + item_index + 1
|
14
|
+
Base64.strict_encode64(offset.to_s)
|
15
|
+
end
|
11
16
|
end
|
12
17
|
|
13
18
|
def has_next_page
|
@@ -81,7 +86,6 @@ module GraphQL
|
|
81
86
|
end
|
82
87
|
end
|
83
88
|
|
84
|
-
|
85
89
|
if defined?(ActiveRecord::Relation)
|
86
90
|
BaseConnection.register_connection_implementation(ActiveRecord::Relation, RelationConnection)
|
87
91
|
end
|
data/lib/graphql/scalar_type.rb
CHANGED
@@ -44,7 +44,7 @@ module GraphQL
|
|
44
44
|
def validate_non_null_input(value)
|
45
45
|
result = Query::InputValidationResult.new
|
46
46
|
if coerce_non_null_input(value).nil?
|
47
|
-
result.add_problem("Could not coerce value #{JSON.
|
47
|
+
result.add_problem("Could not coerce value #{JSON.generate(value, quirks_mode: true)} to #{name}")
|
48
48
|
end
|
49
49
|
result
|
50
50
|
end
|
data/lib/graphql/schema.rb
CHANGED
@@ -50,9 +50,9 @@ module GraphQL
|
|
50
50
|
:max_depth, :max_complexity,
|
51
51
|
:orphan_types, :resolve_type,
|
52
52
|
:object_from_id, :id_from_object,
|
53
|
-
query_analyzer: ->
|
54
|
-
middleware: ->
|
55
|
-
rescue_from: ->
|
53
|
+
query_analyzer: ->(schema, analyzer) { schema.query_analyzers << analyzer },
|
54
|
+
middleware: ->(schema, middleware) { schema.middleware << middleware },
|
55
|
+
rescue_from: ->(schema, err_class, &block) { schema.rescue_from(err_class, &block)}
|
56
56
|
|
57
57
|
lazy_defined_attr_accessor \
|
58
58
|
:query, :mutation, :subscription,
|
@@ -61,7 +61,7 @@ module GraphQL
|
|
61
61
|
:orphan_types,
|
62
62
|
:query_analyzers, :middleware
|
63
63
|
|
64
|
-
DIRECTIVES = [GraphQL::Directive::
|
64
|
+
DIRECTIVES = [GraphQL::Directive::IncludeDirective, GraphQL::Directive::SkipDirective, GraphQL::Directive::DeprecatedDirective]
|
65
65
|
DYNAMIC_FIELDS = ["__type", "__typename", "__schema"]
|
66
66
|
|
67
67
|
attr_reader :directives, :static_validator, :object_from_id_proc, :id_from_object_proc, :resolve_type_proc
|
@@ -86,8 +86,7 @@ module GraphQL
|
|
86
86
|
@orphan_types = types
|
87
87
|
@directives = DIRECTIVES.reduce({}) { |m, d| m[d.name] = d; m }
|
88
88
|
@static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
|
89
|
-
@
|
90
|
-
@middleware = [@rescue_middleware]
|
89
|
+
@middleware = []
|
91
90
|
@query_analyzers = []
|
92
91
|
@resolve_type_proc = nil
|
93
92
|
@object_from_id_proc = nil
|
@@ -100,12 +99,12 @@ module GraphQL
|
|
100
99
|
|
101
100
|
def rescue_from(*args, &block)
|
102
101
|
ensure_defined
|
103
|
-
|
102
|
+
rescue_middleware.rescue_from(*args, &block)
|
104
103
|
end
|
105
104
|
|
106
105
|
def remove_handler(*args, &block)
|
107
106
|
ensure_defined
|
108
|
-
|
107
|
+
rescue_middleware.remove_handler(*args, &block)
|
109
108
|
end
|
110
109
|
|
111
110
|
def define(**kwargs, &block)
|
@@ -258,5 +257,17 @@ module GraphQL
|
|
258
257
|
ensure_defined
|
259
258
|
@id_from_object_proc = new_proc
|
260
259
|
end
|
260
|
+
|
261
|
+
private
|
262
|
+
|
263
|
+
# Lazily create a middleware and add it to the schema
|
264
|
+
# (Don't add it if it's not used)
|
265
|
+
def rescue_middleware
|
266
|
+
@rescue_middleware ||= begin
|
267
|
+
middleware = GraphQL::Schema::RescueMiddleware.new
|
268
|
+
@middleware << middleware
|
269
|
+
middleware
|
270
|
+
end
|
271
|
+
end
|
261
272
|
end
|
262
273
|
end
|
@@ -14,7 +14,7 @@ module GraphQL
|
|
14
14
|
schema = introspection_result.fetch("data").fetch("__schema")
|
15
15
|
|
16
16
|
types = {}
|
17
|
-
type_resolver = ->
|
17
|
+
type_resolver = ->(type) { -> { resolve_type(types, type) } }
|
18
18
|
|
19
19
|
schema.fetch("types").each do |type|
|
20
20
|
next if type.fetch("name").start_with?("__")
|
@@ -31,7 +31,7 @@ module GraphQL
|
|
31
31
|
Schema.define(**kargs)
|
32
32
|
end
|
33
33
|
|
34
|
-
NullResolveType = ->
|
34
|
+
NullResolveType = ->(obj, ctx) {
|
35
35
|
raise(NotImplementedError, "This schema was loaded from string, so it can't resolve types for objects")
|
36
36
|
}
|
37
37
|
|
@@ -18,7 +18,7 @@ module GraphQL
|
|
18
18
|
# Return the GraphQL schema string for the introspection type system
|
19
19
|
def print_introspection_schema
|
20
20
|
query_root = ObjectType.define do
|
21
|
-
name "
|
21
|
+
name "Root"
|
22
22
|
end
|
23
23
|
schema = GraphQL::Schema.define(query: query_root)
|
24
24
|
print_filtered_schema(schema, method(:is_spec_directive), method(:is_introspection_type))
|
@@ -33,11 +33,18 @@ module GraphQL
|
|
33
33
|
types = schema.types.values.select{ |type| type_filter.call(type) }.sort_by(&:name)
|
34
34
|
type_definitions = types.map{ |type| print_type(type) }
|
35
35
|
|
36
|
-
[print_schema_definition(schema)].
|
36
|
+
[print_schema_definition(schema)].compact
|
37
|
+
.concat(directive_definitions)
|
37
38
|
.concat(type_definitions).join("\n\n")
|
38
39
|
end
|
39
40
|
|
40
41
|
def print_schema_definition(schema)
|
42
|
+
if (schema.query.nil? || schema.query.name == 'Query') &&
|
43
|
+
(schema.mutation.nil? || schema.mutation.name == 'Mutation') &&
|
44
|
+
(schema.subscription.nil? || schema.subscription.name == 'Subscription')
|
45
|
+
return
|
46
|
+
end
|
47
|
+
|
41
48
|
operations = [:query, :mutation, :subscription].map do |operation_type|
|
42
49
|
object_type = schema.public_send(operation_type)
|
43
50
|
" #{operation_type}: #{object_type.name}\n" if object_type
|
@@ -84,10 +91,32 @@ module GraphQL
|
|
84
91
|
end
|
85
92
|
end
|
86
93
|
|
94
|
+
module DescriptionPrinter
|
95
|
+
def print_description(definition, indentation='', first_in_block=true)
|
96
|
+
return '' unless definition.description
|
97
|
+
|
98
|
+
description = indentation != '' && !first_in_block ? "\n" : ""
|
99
|
+
description << GraphQL::Language::Comments.commentize(definition.description, indent: indentation)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
87
103
|
module ArgsPrinter
|
88
|
-
|
104
|
+
include DescriptionPrinter
|
105
|
+
def print_args(field, indentation = '')
|
89
106
|
return if field.arguments.empty?
|
90
|
-
|
107
|
+
|
108
|
+
field_arguments = field.arguments.values
|
109
|
+
|
110
|
+
if field_arguments.all?{ |arg| !arg.description }
|
111
|
+
return "(#{field_arguments.map{ |arg| print_input_value(arg) }.join(", ")})"
|
112
|
+
end
|
113
|
+
|
114
|
+
out = "(\n"
|
115
|
+
out << field_arguments.map.with_index{ |arg, i|
|
116
|
+
"#{print_description(arg, " #{indentation}", i == 0)} #{indentation}"\
|
117
|
+
"#{print_input_value(arg)}"
|
118
|
+
}.join("\n")
|
119
|
+
out << "\n)"
|
91
120
|
end
|
92
121
|
|
93
122
|
def print_input_value(arg)
|
@@ -131,64 +160,90 @@ module GraphQL
|
|
131
160
|
module FieldPrinter
|
132
161
|
include DeprecatedPrinter
|
133
162
|
include ArgsPrinter
|
163
|
+
include DescriptionPrinter
|
134
164
|
def print_fields(type)
|
135
|
-
type.all_fields.map{ |field|
|
136
|
-
"
|
165
|
+
type.all_fields.map.with_index{ |field, i|
|
166
|
+
"#{print_description(field, ' ', i == 0)}"\
|
167
|
+
" #{field.name}#{print_args(field, ' ')}: #{field.type}#{print_deprecated(field)}"
|
137
168
|
}.join("\n")
|
138
169
|
end
|
139
170
|
end
|
140
171
|
|
141
172
|
class DirectivePrinter
|
142
173
|
extend ArgsPrinter
|
174
|
+
extend DescriptionPrinter
|
143
175
|
def self.print(directive)
|
176
|
+
"#{print_description(directive)}"\
|
144
177
|
"directive @#{directive.name}#{print_args(directive)} "\
|
145
178
|
"on #{directive.locations.join(' | ')}"
|
146
179
|
end
|
147
180
|
end
|
148
181
|
|
149
182
|
class ScalarPrinter
|
183
|
+
extend DescriptionPrinter
|
150
184
|
def self.print(type)
|
185
|
+
"#{print_description(type)}"\
|
151
186
|
"scalar #{type.name}"
|
152
187
|
end
|
153
188
|
end
|
154
189
|
|
155
190
|
class ObjectPrinter
|
156
191
|
extend FieldPrinter
|
192
|
+
extend DescriptionPrinter
|
157
193
|
def self.print(type)
|
158
194
|
if type.interfaces.any?
|
159
195
|
implementations = " implements #{type.interfaces.map(&:to_s).join(", ")}"
|
160
196
|
else
|
161
197
|
implementations = nil
|
162
198
|
end
|
163
|
-
|
199
|
+
|
200
|
+
"#{print_description(type)}"\
|
201
|
+
"type #{type.name}#{implementations} {\n"\
|
202
|
+
"#{print_fields(type)}\n"\
|
203
|
+
"}"
|
164
204
|
end
|
165
205
|
end
|
166
206
|
|
167
207
|
class InterfacePrinter
|
168
208
|
extend FieldPrinter
|
209
|
+
extend DescriptionPrinter
|
169
210
|
def self.print(type)
|
211
|
+
"#{print_description(type)}"\
|
170
212
|
"interface #{type.name} {\n#{print_fields(type)}\n}"
|
171
213
|
end
|
172
214
|
end
|
173
215
|
|
174
216
|
class UnionPrinter
|
217
|
+
extend DescriptionPrinter
|
175
218
|
def self.print(type)
|
219
|
+
"#{print_description(type)}"\
|
176
220
|
"union #{type.name} = #{type.possible_types.map(&:to_s).join(" | ")}"
|
177
221
|
end
|
178
222
|
end
|
179
223
|
|
180
224
|
class EnumPrinter
|
181
225
|
extend DeprecatedPrinter
|
226
|
+
extend DescriptionPrinter
|
182
227
|
def self.print(type)
|
183
228
|
values = type.values.values.map{ |v| " #{v.name}#{print_deprecated(v)}" }.join("\n")
|
229
|
+
values = type.values.values.map.with_index { |v, i|
|
230
|
+
"#{print_description(v, ' ', i == 0)}"\
|
231
|
+
" #{v.name}#{print_deprecated(v)}"
|
232
|
+
}.join("\n")
|
233
|
+
"#{print_description(type)}"\
|
184
234
|
"enum #{type.name} {\n#{values}\n}"
|
185
235
|
end
|
186
236
|
end
|
187
237
|
|
188
238
|
class InputObjectPrinter
|
189
239
|
extend FieldPrinter
|
240
|
+
extend DescriptionPrinter
|
190
241
|
def self.print(type)
|
191
|
-
fields = type.input_fields.values.map{ |field|
|
242
|
+
fields = type.input_fields.values.map.with_index{ |field, i|
|
243
|
+
"#{print_description(field, " ", i == 0)}"\
|
244
|
+
" #{print_input_value(field)}"
|
245
|
+
}.join("\n")
|
246
|
+
"#{print_description(type)}"\
|
192
247
|
"input #{type.name} {\n#{fields}\n}"
|
193
248
|
end
|
194
249
|
end
|
@@ -50,18 +50,18 @@ module GraphQL
|
|
50
50
|
end
|
51
51
|
err
|
52
52
|
end
|
53
|
-
end
|
54
53
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
54
|
+
# This error is raised when a query exceeds `max_seconds`.
|
55
|
+
# Since it's a child of {GraphQL::ExecutionError},
|
56
|
+
# its message will be added to the response's `errors` key.
|
57
|
+
#
|
58
|
+
# To raise an error that will stop query resolution, use a custom block
|
59
|
+
# to take this error and raise a new one which _doesn't_ descend from {GraphQL::ExecutionError},
|
60
|
+
# such as `RuntimeError`.
|
61
|
+
class TimeoutError < GraphQL::ExecutionError
|
62
|
+
def initialize(parent_type, field_defn)
|
63
|
+
super("Timeout on #{parent_type.name}.#{field_defn.name}")
|
64
|
+
end
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
@@ -24,7 +24,7 @@ module GraphQL
|
|
24
24
|
# @return [Proc] A proc which will validate the input by calling `property_name` and asserting it is an instance of one of `allowed_classes`
|
25
25
|
def self.assert_property(property_name, *allowed_classes)
|
26
26
|
allowed_classes_message = allowed_classes.map(&:name).join(" or ")
|
27
|
-
->
|
27
|
+
->(obj) {
|
28
28
|
property_value = obj.public_send(property_name)
|
29
29
|
is_valid_value = allowed_classes.any? { |allowed_class| property_value.is_a?(allowed_class) }
|
30
30
|
is_valid_value ? nil : "#{property_name} must return #{allowed_classes_message}, not #{property_value.class.name} (#{property_value.inspect})"
|
@@ -36,7 +36,7 @@ module GraphQL
|
|
36
36
|
# @param to_class [Class] The class for values in the return value
|
37
37
|
# @return [Proc] A proc to validate that validates the input by calling `property_name` and asserting that the return value is a Hash of `{from_class => to_class}` pairs
|
38
38
|
def self.assert_property_mapping(property_name, from_class, to_class)
|
39
|
-
->
|
39
|
+
->(obj) {
|
40
40
|
property_value = obj.public_send(property_name)
|
41
41
|
error_message = nil
|
42
42
|
if !property_value.is_a?(Hash)
|
@@ -56,7 +56,7 @@ module GraphQL
|
|
56
56
|
# @param list_member_class [Class] The class which each member of the returned array should be an instance of
|
57
57
|
# @return [Proc] A proc to validate the input by calling `property_name` and asserting that the return is an Array of `list_member_class` instances
|
58
58
|
def self.assert_property_list_of(property_name, list_member_class)
|
59
|
-
->
|
59
|
+
->(obj) {
|
60
60
|
property_value = obj.public_send(property_name)
|
61
61
|
if !property_value.is_a?(Array)
|
62
62
|
"#{property_name} must be an Array of #{list_member_class.name}, not a #{property_value.class.name} (#{property_value.inspect})"
|
@@ -72,7 +72,7 @@ module GraphQL
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def self.assert_named_items_are_valid(item_name, get_items_proc)
|
75
|
-
->
|
75
|
+
->(type) {
|
76
76
|
items = get_items_proc.call(type)
|
77
77
|
error_message = nil
|
78
78
|
items.each do |item|
|
@@ -87,18 +87,18 @@ module GraphQL
|
|
87
87
|
end
|
88
88
|
|
89
89
|
|
90
|
-
FIELDS_ARE_VALID = Rules.assert_named_items_are_valid("field", ->
|
90
|
+
FIELDS_ARE_VALID = Rules.assert_named_items_are_valid("field", ->(type) { type.all_fields })
|
91
91
|
|
92
|
-
HAS_ONE_OR_MORE_POSSIBLE_TYPES = ->
|
92
|
+
HAS_ONE_OR_MORE_POSSIBLE_TYPES = ->(type) {
|
93
93
|
type.possible_types.length >= 1 ? nil : "must have at least one possible type"
|
94
94
|
}
|
95
95
|
|
96
96
|
NAME_IS_STRING = Rules.assert_property(:name, String)
|
97
97
|
DESCRIPTION_IS_STRING_OR_NIL = Rules.assert_property(:description, String, NilClass)
|
98
98
|
ARGUMENTS_ARE_STRING_TO_ARGUMENT = Rules.assert_property_mapping(:arguments, String, GraphQL::Argument)
|
99
|
-
ARGUMENTS_ARE_VALID = Rules.assert_named_items_are_valid("argument", ->
|
99
|
+
ARGUMENTS_ARE_VALID = Rules.assert_named_items_are_valid("argument", ->(type) { type.arguments.values })
|
100
100
|
|
101
|
-
DEFAULT_VALUE_IS_VALID_FOR_TYPE = ->
|
101
|
+
DEFAULT_VALUE_IS_VALID_FOR_TYPE = ->(type) {
|
102
102
|
if !type.default_value.nil?
|
103
103
|
coerced_value = begin
|
104
104
|
type.type.coerce_result(type.default_value)
|
@@ -114,7 +114,7 @@ module GraphQL
|
|
114
114
|
end
|
115
115
|
}
|
116
116
|
|
117
|
-
TYPE_IS_VALID_INPUT_TYPE = ->
|
117
|
+
TYPE_IS_VALID_INPUT_TYPE = ->(type) {
|
118
118
|
outer_type = type.type
|
119
119
|
inner_type = outer_type.is_a?(GraphQL::BaseType) ? outer_type.unwrap : nil
|
120
120
|
|
@@ -126,7 +126,7 @@ module GraphQL
|
|
126
126
|
end
|
127
127
|
}
|
128
128
|
|
129
|
-
SCHEMA_CAN_RESOLVE_TYPES = ->
|
129
|
+
SCHEMA_CAN_RESOLVE_TYPES = ->(schema) {
|
130
130
|
if schema.types.values.any? { |type| type.kind.resolves? } && schema.resolve_type_proc.nil?
|
131
131
|
"schema contains Interfaces or Unions, so you must define a `resolve_type (obj, ctx) -> { ... }` function"
|
132
132
|
else
|
@@ -134,7 +134,7 @@ module GraphQL
|
|
134
134
|
end
|
135
135
|
}
|
136
136
|
|
137
|
-
SCHEMA_CAN_FETCH_IDS = ->
|
137
|
+
SCHEMA_CAN_FETCH_IDS = ->(schema) {
|
138
138
|
has_node_field = schema.query && schema.query.all_fields.any? { |f| f.metadata[:relay_node_field] }
|
139
139
|
if has_node_field && schema.object_from_id_proc.nil?
|
140
140
|
"schema contains `node(id:...)` field, so you must define a `object_from_id (id, ctx) -> { ... }` function"
|
@@ -143,7 +143,7 @@ module GraphQL
|
|
143
143
|
end
|
144
144
|
}
|
145
145
|
|
146
|
-
SCHEMA_CAN_GENERATE_IDS = ->
|
146
|
+
SCHEMA_CAN_GENERATE_IDS = ->(schema) {
|
147
147
|
has_id_field = schema.types.values.any? { |t| t.kind.fields? && t.all_fields.any? { |f| f.resolve_proc.is_a?(GraphQL::Relay::GlobalIdResolve) } }
|
148
148
|
if has_id_field && schema.id_from_object_proc.nil?
|
149
149
|
"schema contains `global_id_field`, so you must define a `id_from_object (obj, type, ctx) -> { ... }` function"
|