graphql 1.11.6 → 1.11.10
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 +2 -0
- data/lib/graphql/execution/interpreter/arguments.rb +21 -6
- data/lib/graphql/execution/interpreter/arguments_cache.rb +8 -0
- data/lib/graphql/execution/interpreter/runtime.rb +53 -39
- data/lib/graphql/integer_decoding_error.rb +17 -0
- data/lib/graphql/invalid_null_error.rb +1 -1
- data/lib/graphql/query/context.rb +4 -1
- data/lib/graphql/query/validation_pipeline.rb +1 -1
- data/lib/graphql/query.rb +4 -1
- data/lib/graphql/relay/array_connection.rb +2 -2
- data/lib/graphql/schema/default_type_error.rb +2 -0
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +20 -11
- data/lib/graphql/schema/member/has_arguments.rb +51 -52
- data/lib/graphql/schema/relay_classic_mutation.rb +1 -1
- data/lib/graphql/schema.rb +39 -11
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/base_visitor.rb +3 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +29 -21
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
- data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
- data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
- data/lib/graphql/static_validation/validation_context.rb +6 -1
- data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
- data/lib/graphql/static_validation/validator.rb +33 -10
- data/lib/graphql/static_validation.rb +1 -0
- data/lib/graphql/tracing/platform_tracing.rb +1 -1
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
- data/lib/graphql/types/int.rb +9 -2
- data/lib/graphql/types/relay/base_connection.rb +2 -1
- data/lib/graphql/types/relay/base_edge.rb +2 -1
- data/lib/graphql/types/string.rb +7 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +1 -0
- data/readme.md +1 -1
- metadata +10 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: edd6b4edae07b6c52383810319efb2cdd19a8f818639dda22c79308620330274
|
4
|
+
data.tar.gz: '09869b52706e249e6e41282e9e06243547db556d42410c4e2d0cb9abf00d7e3f'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5c8e1b96dea2f3ac9c8c93639e6b0c9763984c9af6ca09201ef89bfbbfd2ff61cd622417d04f5624fb6c679822d8a58c1a148c5139e1e1e51bf03eb5aaaaa4a
|
7
|
+
data.tar.gz: 07c12d4dd5b50d5b36a3c8e298ae663969e203ce6103c449ec0b599c5960c145b34dd9c023986c5d3cb2f0d6169b5395530bca6d07985152fb12505dc1af6036
|
@@ -14,18 +14,33 @@ module GraphQL
|
|
14
14
|
# This hash is the one used at runtime.
|
15
15
|
#
|
16
16
|
# @return [Hash<Symbol, Object>]
|
17
|
-
|
17
|
+
def keyword_arguments
|
18
|
+
@keyword_arguments ||= begin
|
19
|
+
kwargs = {}
|
20
|
+
argument_values.each do |name, arg_val|
|
21
|
+
kwargs[name] = arg_val.value
|
22
|
+
end
|
23
|
+
kwargs
|
24
|
+
end
|
25
|
+
end
|
18
26
|
|
19
|
-
|
20
|
-
|
27
|
+
# @param argument_values [nil, Hash{Symbol => ArgumentValue}]
|
28
|
+
def initialize(argument_values:)
|
21
29
|
@argument_values = argument_values
|
30
|
+
@empty = argument_values.nil? || argument_values.empty?
|
22
31
|
end
|
23
32
|
|
24
33
|
# @return [Hash{Symbol => ArgumentValue}]
|
25
|
-
|
34
|
+
def argument_values
|
35
|
+
@argument_values ||= {}
|
36
|
+
end
|
37
|
+
|
38
|
+
def empty?
|
39
|
+
@empty
|
40
|
+
end
|
26
41
|
|
27
|
-
def_delegators
|
28
|
-
def_delegators
|
42
|
+
def_delegators :keyword_arguments, :key?, :[], :fetch, :keys, :each, :values
|
43
|
+
def_delegators :argument_values, :each_value
|
29
44
|
|
30
45
|
def inspect
|
31
46
|
"#<#{self.class} @keyword_arguments=#{keyword_arguments.inspect}>"
|
@@ -29,11 +29,16 @@ module GraphQL
|
|
29
29
|
|
30
30
|
private
|
31
31
|
|
32
|
+
NO_ARGUMENTS = {}.freeze
|
33
|
+
|
32
34
|
NO_VALUE_GIVEN = Object.new
|
33
35
|
|
34
36
|
def prepare_args_hash(ast_arg_or_hash_or_value)
|
35
37
|
case ast_arg_or_hash_or_value
|
36
38
|
when Hash
|
39
|
+
if ast_arg_or_hash_or_value.empty?
|
40
|
+
return NO_ARGUMENTS
|
41
|
+
end
|
37
42
|
args_hash = {}
|
38
43
|
ast_arg_or_hash_or_value.each do |k, v|
|
39
44
|
args_hash[k] = prepare_args_hash(v)
|
@@ -42,6 +47,9 @@ module GraphQL
|
|
42
47
|
when Array
|
43
48
|
ast_arg_or_hash_or_value.map { |v| prepare_args_hash(v) }
|
44
49
|
when GraphQL::Language::Nodes::Field, GraphQL::Language::Nodes::InputObject, GraphQL::Language::Nodes::Directive
|
50
|
+
if ast_arg_or_hash_or_value.arguments.empty?
|
51
|
+
return NO_ARGUMENTS
|
52
|
+
end
|
45
53
|
args_hash = {}
|
46
54
|
ast_arg_or_hash_or_value.arguments.each do |arg|
|
47
55
|
v = prepare_args_hash(arg.value)
|
@@ -47,8 +47,7 @@ module GraphQL
|
|
47
47
|
root_op_type = root_operation.operation_type || "query"
|
48
48
|
root_type = schema.root_type_for_operation(root_op_type)
|
49
49
|
path = []
|
50
|
-
|
51
|
-
set_interpreter_context(:current_path, path)
|
50
|
+
set_all_interpreter_context(query.root_value, nil, nil, path)
|
52
51
|
object_proxy = authorized_new(root_type, query.root_value, context, path)
|
53
52
|
object_proxy = schema.sync_lazy(object_proxy)
|
54
53
|
if object_proxy.nil?
|
@@ -118,9 +117,10 @@ module GraphQL
|
|
118
117
|
end
|
119
118
|
end
|
120
119
|
|
120
|
+
NO_ARGS = {}.freeze
|
121
|
+
|
121
122
|
def evaluate_selections(path, scoped_context, owner_object, owner_type, selections, root_operation_type: nil)
|
122
|
-
|
123
|
-
set_interpreter_context(:current_path, path)
|
123
|
+
set_all_interpreter_context(owner_object, nil, nil, path)
|
124
124
|
selections_by_name = {}
|
125
125
|
gather_selections(owner_object, owner_type, selections, selections_by_name)
|
126
126
|
selections_by_name.each do |result_name, field_ast_nodes_or_ast_node|
|
@@ -159,8 +159,7 @@ module GraphQL
|
|
159
159
|
# to propagate `null`
|
160
160
|
set_type_at_path(next_path, return_type)
|
161
161
|
# Set this before calling `run_with_directives`, so that the directive can have the latest path
|
162
|
-
|
163
|
-
set_interpreter_context(:current_field, field_defn)
|
162
|
+
set_all_interpreter_context(nil, field_defn, nil, next_path)
|
164
163
|
|
165
164
|
context.scoped_context = scoped_context
|
166
165
|
object = owner_object
|
@@ -171,44 +170,50 @@ module GraphQL
|
|
171
170
|
|
172
171
|
begin
|
173
172
|
kwarg_arguments = arguments(object, field_defn, ast_node)
|
174
|
-
rescue GraphQL::ExecutionError => e
|
173
|
+
rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => e
|
175
174
|
continue_value(next_path, e, owner_type, field_defn, return_type.non_null?, ast_node)
|
176
175
|
next
|
177
176
|
end
|
178
177
|
|
179
178
|
after_lazy(kwarg_arguments, owner: owner_type, field: field_defn, path: next_path, scoped_context: context.scoped_context, owner_object: object, arguments: kwarg_arguments) do |resolved_arguments|
|
180
|
-
|
179
|
+
case resolved_arguments
|
180
|
+
when GraphQL::ExecutionError, GraphQL::UnauthorizedError
|
181
181
|
continue_value(next_path, resolved_arguments, owner_type, field_defn, return_type.non_null?, ast_node)
|
182
182
|
next
|
183
183
|
end
|
184
184
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
185
|
+
if resolved_arguments.empty? && field_defn.extras.empty?
|
186
|
+
# We can avoid allocating the `{ Symbol => Object }` hash in this case
|
187
|
+
kwarg_arguments = NO_ARGS
|
188
|
+
else
|
189
|
+
kwarg_arguments = resolved_arguments.keyword_arguments
|
190
|
+
|
191
|
+
field_defn.extras.each do |extra|
|
192
|
+
case extra
|
193
|
+
when :ast_node
|
194
|
+
kwarg_arguments[:ast_node] = ast_node
|
195
|
+
when :execution_errors
|
196
|
+
kwarg_arguments[:execution_errors] = ExecutionErrors.new(context, ast_node, next_path)
|
197
|
+
when :path
|
198
|
+
kwarg_arguments[:path] = next_path
|
199
|
+
when :lookahead
|
200
|
+
if !field_ast_nodes
|
201
|
+
field_ast_nodes = [ast_node]
|
202
|
+
end
|
203
|
+
kwarg_arguments[:lookahead] = Execution::Lookahead.new(
|
204
|
+
query: query,
|
205
|
+
ast_nodes: field_ast_nodes,
|
206
|
+
field: field_defn,
|
207
|
+
)
|
208
|
+
when :argument_details
|
209
|
+
kwarg_arguments[:argument_details] = resolved_arguments
|
210
|
+
else
|
211
|
+
kwarg_arguments[extra] = field_defn.fetch_extra(extra, context)
|
198
212
|
end
|
199
|
-
kwarg_arguments[:lookahead] = Execution::Lookahead.new(
|
200
|
-
query: query,
|
201
|
-
ast_nodes: field_ast_nodes,
|
202
|
-
field: field_defn,
|
203
|
-
)
|
204
|
-
when :argument_details
|
205
|
-
kwarg_arguments[:argument_details] = resolved_arguments
|
206
|
-
else
|
207
|
-
kwarg_arguments[extra] = field_defn.fetch_extra(extra, context)
|
208
213
|
end
|
209
214
|
end
|
210
215
|
|
211
|
-
|
216
|
+
set_all_interpreter_context(nil, nil, kwarg_arguments, nil)
|
212
217
|
|
213
218
|
# Optimize for the case that field is selected only once
|
214
219
|
if field_ast_nodes.nil? || field_ast_nodes.size == 1
|
@@ -414,6 +419,21 @@ module GraphQL
|
|
414
419
|
true
|
415
420
|
end
|
416
421
|
|
422
|
+
def set_all_interpreter_context(object, field, arguments, path)
|
423
|
+
if object
|
424
|
+
@context[:current_object] = @interpreter_context[:current_object] = object
|
425
|
+
end
|
426
|
+
if field
|
427
|
+
@context[:current_field] = @interpreter_context[:current_field] = field
|
428
|
+
end
|
429
|
+
if arguments
|
430
|
+
@context[:current_arguments] = @interpreter_context[:current_arguments] = arguments
|
431
|
+
end
|
432
|
+
if path
|
433
|
+
@context[:current_path] = @interpreter_context[:current_path] = path
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
417
437
|
# @param obj [Object] Some user-returned value that may want to be batched
|
418
438
|
# @param path [Array<String>]
|
419
439
|
# @param field [GraphQL::Schema::Field]
|
@@ -421,16 +441,10 @@ module GraphQL
|
|
421
441
|
# @param trace [Boolean] If `false`, don't wrap this with field tracing
|
422
442
|
# @return [GraphQL::Execution::Lazy, Object] If loading `object` will be deferred, it's a wrapper over it.
|
423
443
|
def after_lazy(lazy_obj, owner:, field:, path:, scoped_context:, owner_object:, arguments:, eager: false, trace: true, &block)
|
424
|
-
|
425
|
-
set_interpreter_context(:current_arguments, arguments)
|
426
|
-
set_interpreter_context(:current_path, path)
|
427
|
-
set_interpreter_context(:current_field, field)
|
444
|
+
set_all_interpreter_context(owner_object, field, arguments, path)
|
428
445
|
if schema.lazy?(lazy_obj)
|
429
446
|
lazy = GraphQL::Execution::Lazy.new(path: path, field: field) do
|
430
|
-
|
431
|
-
set_interpreter_context(:current_field, field)
|
432
|
-
set_interpreter_context(:current_object, owner_object)
|
433
|
-
set_interpreter_context(:current_arguments, arguments)
|
447
|
+
set_all_interpreter_context(owner_object, field, arguments, path)
|
434
448
|
context.scoped_context = scoped_context
|
435
449
|
# Wrap the execution of _this_ method with tracing,
|
436
450
|
# but don't wrap the continuation below
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
# This error is raised when `Types::Int` is given an input value outside of 32-bit integer range.
|
4
|
+
#
|
5
|
+
# For really big integer values, consider `GraphQL::Types::BigInt`
|
6
|
+
#
|
7
|
+
# @see GraphQL::Types::Int which raises this error
|
8
|
+
class IntegerDecodingError < GraphQL::RuntimeTypeError
|
9
|
+
# The value which couldn't be decoded
|
10
|
+
attr_reader :integer_value
|
11
|
+
|
12
|
+
def initialize(value)
|
13
|
+
@integer_value = value
|
14
|
+
super("Integer out of bounds: #{value}. \nConsider using GraphQL::Types::BigInt instead.")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -39,7 +39,7 @@ module GraphQL
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def inspect
|
42
|
-
if name.nil? && parent_class.respond_to?(:mutation) && (mutation = parent_class.mutation)
|
42
|
+
if (name.nil? || parent_class.name.nil?) && parent_class.respond_to?(:mutation) && (mutation = parent_class.mutation)
|
43
43
|
"#{mutation.inspect}::#{parent_class.graphql_name}::InvalidNullError"
|
44
44
|
else
|
45
45
|
super
|
@@ -167,7 +167,10 @@ module GraphQL
|
|
167
167
|
# @api private
|
168
168
|
attr_accessor :scoped_context
|
169
169
|
|
170
|
-
|
170
|
+
def []=(key, value)
|
171
|
+
@provided_values[key] = value
|
172
|
+
end
|
173
|
+
|
171
174
|
def_delegators :@query, :trace, :interpreter?
|
172
175
|
|
173
176
|
# @!method []=(key, value)
|
@@ -72,7 +72,7 @@ module GraphQL
|
|
72
72
|
elsif @operation_name_error
|
73
73
|
@validation_errors << @operation_name_error
|
74
74
|
else
|
75
|
-
validation_result = @schema.static_validator.validate(@query, validate: @validate)
|
75
|
+
validation_result = @schema.static_validator.validate(@query, validate: @validate, timeout: @schema.validate_timeout, max_errors: @schema.validate_max_errors)
|
76
76
|
@validation_errors.concat(validation_result[:errors])
|
77
77
|
@internal_representation = validation_result[:irep]
|
78
78
|
|
data/lib/graphql/query.rb
CHANGED
@@ -88,6 +88,7 @@ module GraphQL
|
|
88
88
|
schema = schema.graphql_definition
|
89
89
|
end
|
90
90
|
@schema = schema
|
91
|
+
@interpreter = @schema.interpreter?
|
91
92
|
@filter = schema.default_filter.merge(except: except, only: only)
|
92
93
|
@context = schema.context_class.new(query: self, object: root_value, values: context)
|
93
94
|
@warden = warden
|
@@ -148,7 +149,9 @@ module GraphQL
|
|
148
149
|
@query_string ||= (document ? document.to_query_string : nil)
|
149
150
|
end
|
150
151
|
|
151
|
-
|
152
|
+
def interpreter?
|
153
|
+
@interpreter
|
154
|
+
end
|
152
155
|
|
153
156
|
def subscription_update?
|
154
157
|
@subscription_topic && subscription?
|
@@ -31,8 +31,6 @@ module GraphQL
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
private
|
35
|
-
|
36
34
|
def first
|
37
35
|
@first ||= begin
|
38
36
|
capped = limit_pagination_argument(arguments[:first], max_page_size)
|
@@ -47,6 +45,8 @@ module GraphQL
|
|
47
45
|
@last ||= limit_pagination_argument(arguments[:last], max_page_size)
|
48
46
|
end
|
49
47
|
|
48
|
+
private
|
49
|
+
|
50
50
|
# apply first / last limit results
|
51
51
|
def paged_nodes
|
52
52
|
@paged_nodes ||= begin
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -725,33 +725,42 @@ module GraphQL
|
|
725
725
|
if @extensions.empty?
|
726
726
|
yield(obj, args)
|
727
727
|
else
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
value = run_extensions_before_resolve(
|
733
|
-
extended_obj = obj
|
734
|
-
extended_args = args
|
728
|
+
# This is a hack to get the _last_ value for extended obj and args,
|
729
|
+
# in case one of the extensions doesn't `yield`.
|
730
|
+
# (There's another implementation that uses multiple-return, but I'm wary of the perf cost of the extra arrays)
|
731
|
+
extended = { args: args, obj: obj, memos: nil }
|
732
|
+
value = run_extensions_before_resolve(obj, args, ctx, extended) do |obj, args|
|
735
733
|
yield(obj, args)
|
736
734
|
end
|
737
735
|
|
736
|
+
extended_obj = extended[:obj]
|
737
|
+
extended_args = extended[:args]
|
738
|
+
memos = extended[:memos] || EMPTY_HASH
|
739
|
+
|
738
740
|
ctx.schema.after_lazy(value) do |resolved_value|
|
739
|
-
|
741
|
+
idx = 0
|
742
|
+
@extensions.each do |ext|
|
740
743
|
memo = memos[idx]
|
741
744
|
# TODO after_lazy?
|
742
745
|
resolved_value = ext.after_resolve(object: extended_obj, arguments: extended_args, context: ctx, value: resolved_value, memo: memo)
|
746
|
+
idx += 1
|
743
747
|
end
|
744
748
|
resolved_value
|
745
749
|
end
|
746
750
|
end
|
747
751
|
end
|
748
752
|
|
749
|
-
def run_extensions_before_resolve(
|
753
|
+
def run_extensions_before_resolve(obj, args, ctx, extended, idx: 0)
|
750
754
|
extension = @extensions[idx]
|
751
755
|
if extension
|
752
756
|
extension.resolve(object: obj, arguments: args, context: ctx) do |extended_obj, extended_args, memo|
|
753
|
-
|
754
|
-
|
757
|
+
if memo
|
758
|
+
memos = extended[:memos] ||= {}
|
759
|
+
memos[idx] = memo
|
760
|
+
end
|
761
|
+
extended[:obj] = extended_obj
|
762
|
+
extended[:args] = extended_args
|
763
|
+
run_extensions_before_resolve(extended_obj, extended_args, ctx, extended, idx: idx + 1) { |o, a| yield(o, a) }
|
755
764
|
end
|
756
765
|
else
|
757
766
|
yield(obj, args)
|
@@ -85,70 +85,69 @@ module GraphQL
|
|
85
85
|
# @param context [GraphQL::Query::Context]
|
86
86
|
# @return [Hash<Symbol, Object>, Execution::Lazy<Hash>]
|
87
87
|
def coerce_arguments(parent_object, values, context)
|
88
|
-
argument_values = {}
|
89
|
-
kwarg_arguments = {}
|
90
88
|
# Cache this hash to avoid re-merging it
|
91
89
|
arg_defns = self.arguments
|
92
90
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
has_value =
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
loads = arg_defn.loads
|
112
|
-
loaded_value = nil
|
113
|
-
if loads && !arg_defn.from_resolver?
|
114
|
-
loaded_value = if arg_defn.type.list?
|
115
|
-
loaded_values = value.map { |val| load_application_object(arg_defn, loads, val, context) }
|
116
|
-
context.schema.after_any_lazies(loaded_values) { |result| result }
|
117
|
-
else
|
118
|
-
load_application_object(arg_defn, loads, value, context)
|
119
|
-
end
|
91
|
+
if arg_defns.empty?
|
92
|
+
GraphQL::Execution::Interpreter::Arguments.new(argument_values: nil)
|
93
|
+
else
|
94
|
+
argument_values = {}
|
95
|
+
arg_lazies = arg_defns.map do |arg_name, arg_defn|
|
96
|
+
arg_key = arg_defn.keyword
|
97
|
+
has_value = false
|
98
|
+
default_used = false
|
99
|
+
if values.key?(arg_name)
|
100
|
+
has_value = true
|
101
|
+
value = values[arg_name]
|
102
|
+
elsif values.key?(arg_key)
|
103
|
+
has_value = true
|
104
|
+
value = values[arg_key]
|
105
|
+
elsif arg_defn.default_value?
|
106
|
+
has_value = true
|
107
|
+
value = arg_defn.default_value
|
108
|
+
default_used = true
|
120
109
|
end
|
121
110
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
arg_defn.type.
|
111
|
+
if has_value
|
112
|
+
loads = arg_defn.loads
|
113
|
+
loaded_value = nil
|
114
|
+
if loads && !arg_defn.from_resolver?
|
115
|
+
loaded_value = if arg_defn.type.list?
|
116
|
+
loaded_values = value.map { |val| load_application_object(arg_defn, loads, val, context) }
|
117
|
+
context.schema.after_any_lazies(loaded_values) { |result| result }
|
118
|
+
else
|
119
|
+
load_application_object(arg_defn, loads, value, context)
|
120
|
+
end
|
127
121
|
end
|
128
|
-
end
|
129
122
|
|
130
|
-
|
131
|
-
|
132
|
-
|
123
|
+
coerced_value = if loaded_value
|
124
|
+
loaded_value
|
125
|
+
else
|
126
|
+
context.schema.error_handler.with_error_handling(context) do
|
127
|
+
arg_defn.type.coerce_input(value, context)
|
128
|
+
end
|
133
129
|
end
|
134
130
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
131
|
+
context.schema.after_lazy(coerced_value) do |coerced_value|
|
132
|
+
prepared_value = context.schema.error_handler.with_error_handling(context) do
|
133
|
+
arg_defn.prepare_value(parent_object, coerced_value, context: context)
|
134
|
+
end
|
135
|
+
|
136
|
+
# TODO code smell to access such a deeply-nested constant in a distant module
|
137
|
+
argument_values[arg_key] = GraphQL::Execution::Interpreter::ArgumentValue.new(
|
138
|
+
value: prepared_value,
|
139
|
+
definition: arg_defn,
|
140
|
+
default_used: default_used,
|
141
|
+
)
|
142
|
+
end
|
142
143
|
end
|
143
144
|
end
|
144
|
-
end
|
145
145
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
)
|
146
|
+
context.schema.after_any_lazies(arg_lazies) do
|
147
|
+
GraphQL::Execution::Interpreter::Arguments.new(
|
148
|
+
argument_values: argument_values,
|
149
|
+
)
|
150
|
+
end
|
152
151
|
end
|
153
152
|
end
|
154
153
|
|
@@ -105,7 +105,7 @@ module GraphQL
|
|
105
105
|
sig = super
|
106
106
|
# Arguments were added at the root, but they should be nested
|
107
107
|
sig[:arguments].clear
|
108
|
-
sig[:arguments][:input] = { type: input_type, required: true }
|
108
|
+
sig[:arguments][:input] = { type: input_type, required: true, description: "Parameters for #{graphql_name}" }
|
109
109
|
sig
|
110
110
|
end
|
111
111
|
|
data/lib/graphql/schema.rb
CHANGED
@@ -157,7 +157,7 @@ module GraphQL
|
|
157
157
|
|
158
158
|
accepts_definitions \
|
159
159
|
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
160
|
-
:max_depth, :max_complexity, :default_max_page_size,
|
160
|
+
:validate_timeout, :validate_max_errors, :max_depth, :max_complexity, :default_max_page_size,
|
161
161
|
:orphan_types, :resolve_type, :type_error, :parse_error,
|
162
162
|
:error_bubbling,
|
163
163
|
:raise_definition_error,
|
@@ -196,7 +196,7 @@ module GraphQL
|
|
196
196
|
attr_accessor \
|
197
197
|
:query, :mutation, :subscription,
|
198
198
|
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
199
|
-
:max_depth, :max_complexity, :default_max_page_size,
|
199
|
+
:validate_timeout, :validate_max_errors, :max_depth, :max_complexity, :default_max_page_size,
|
200
200
|
:orphan_types, :directives,
|
201
201
|
:query_analyzers, :multiplex_analyzers, :instrumenters, :lazy_methods,
|
202
202
|
:cursor_encoder,
|
@@ -366,7 +366,7 @@ module GraphQL
|
|
366
366
|
validator_opts = { schema: self }
|
367
367
|
rules && (validator_opts[:rules] = rules)
|
368
368
|
validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
|
369
|
-
res = validator.validate(query)
|
369
|
+
res = validator.validate(query, timeout: validate_timeout, max_errors: validate_max_errors)
|
370
370
|
res[:errors]
|
371
371
|
end
|
372
372
|
|
@@ -950,6 +950,8 @@ module GraphQL
|
|
950
950
|
schema_defn.query = query && query.graphql_definition
|
951
951
|
schema_defn.mutation = mutation && mutation.graphql_definition
|
952
952
|
schema_defn.subscription = subscription && subscription.graphql_definition
|
953
|
+
schema_defn.validate_timeout = validate_timeout
|
954
|
+
schema_defn.validate_max_errors = validate_max_errors
|
953
955
|
schema_defn.max_complexity = max_complexity
|
954
956
|
schema_defn.error_bubbling = error_bubbling
|
955
957
|
schema_defn.max_depth = max_depth
|
@@ -1118,14 +1120,15 @@ module GraphQL
|
|
1118
1120
|
type.possible_types(context: context)
|
1119
1121
|
else
|
1120
1122
|
stored_possible_types = own_possible_types[type.graphql_name]
|
1121
|
-
visible_possible_types = stored_possible_types
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1123
|
+
visible_possible_types = if stored_possible_types && type.kind.interface?
|
1124
|
+
stored_possible_types.select do |possible_type|
|
1125
|
+
# Use `.graphql_name` comparison to match legacy vs class-based types.
|
1126
|
+
# When we don't need to support legacy `.define` types, use `.include?(type)` instead.
|
1127
|
+
possible_type.interfaces(context).any? { |interface| interface.graphql_name == type.graphql_name }
|
1128
|
+
end
|
1129
|
+
else
|
1130
|
+
stored_possible_types
|
1131
|
+
end
|
1129
1132
|
visible_possible_types ||
|
1130
1133
|
introspection_system.possible_types[type.graphql_name] ||
|
1131
1134
|
(
|
@@ -1272,6 +1275,31 @@ module GraphQL
|
|
1272
1275
|
end
|
1273
1276
|
end
|
1274
1277
|
|
1278
|
+
attr_writer :validate_timeout
|
1279
|
+
|
1280
|
+
def validate_timeout(new_validate_timeout = nil)
|
1281
|
+
if new_validate_timeout
|
1282
|
+
@validate_timeout = new_validate_timeout
|
1283
|
+
elsif defined?(@validate_timeout)
|
1284
|
+
@validate_timeout
|
1285
|
+
else
|
1286
|
+
find_inherited_value(:validate_timeout)
|
1287
|
+
end
|
1288
|
+
end
|
1289
|
+
|
1290
|
+
attr_writer :validate_max_errors
|
1291
|
+
|
1292
|
+
def validate_max_errors(new_validate_max_errors = nil)
|
1293
|
+
if new_validate_max_errors
|
1294
|
+
@validate_max_errors = new_validate_max_errors
|
1295
|
+
elsif defined?(@validate_max_errors)
|
1296
|
+
@validate_max_errors
|
1297
|
+
else
|
1298
|
+
find_inherited_value(:validate_max_errors)
|
1299
|
+
end
|
1300
|
+
end
|
1301
|
+
|
1302
|
+
|
1275
1303
|
attr_writer :max_complexity
|
1276
1304
|
|
1277
1305
|
def max_complexity(max_complexity = nil)
|
@@ -193,25 +193,26 @@ module GraphQL
|
|
193
193
|
if node1.name != node2.name
|
194
194
|
errored_nodes = [node1.name, node2.name].sort.join(" or ")
|
195
195
|
msg = "Field '#{response_key}' has a field conflict: #{errored_nodes}?"
|
196
|
-
|
196
|
+
add_error(GraphQL::StaticValidation::FieldsWillMergeError.new(
|
197
197
|
msg,
|
198
198
|
nodes: [node1, node2],
|
199
199
|
path: [],
|
200
200
|
field_name: response_key,
|
201
201
|
conflicts: errored_nodes
|
202
|
-
)
|
202
|
+
))
|
203
203
|
end
|
204
204
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
205
|
+
if !same_arguments?(node1, node2)
|
206
|
+
args = [serialize_field_args(node1), serialize_field_args(node2)]
|
207
|
+
conflicts = args.map { |arg| GraphQL::Language.serialize(arg) }.join(" or ")
|
208
|
+
msg = "Field '#{response_key}' has an argument conflict: #{conflicts}?"
|
209
|
+
add_error(GraphQL::StaticValidation::FieldsWillMergeError.new(
|
209
210
|
msg,
|
210
211
|
nodes: [node1, node2],
|
211
212
|
path: [],
|
212
213
|
field_name: response_key,
|
213
|
-
conflicts:
|
214
|
-
)
|
214
|
+
conflicts: conflicts
|
215
|
+
))
|
215
216
|
end
|
216
217
|
end
|
217
218
|
|
@@ -326,20 +327,19 @@ module GraphQL
|
|
326
327
|
[fields, fragment_spreads]
|
327
328
|
end
|
328
329
|
|
329
|
-
def
|
330
|
+
def same_arguments?(field1, field2)
|
330
331
|
# Check for incompatible / non-identical arguments on this node:
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
end.uniq
|
332
|
+
arguments1 = field1.arguments
|
333
|
+
arguments2 = field2.arguments
|
334
|
+
|
335
|
+
return false if arguments1.length != arguments2.length
|
336
|
+
|
337
|
+
arguments1.all? do |argument1|
|
338
|
+
argument2 = arguments2.find { |argument| argument.name == argument1.name }
|
339
|
+
return false if argument2.nil?
|
340
|
+
|
341
|
+
serialize_arg(argument1.value) == serialize_arg(argument2.value)
|
342
|
+
end
|
343
343
|
end
|
344
344
|
|
345
345
|
def serialize_arg(arg_value)
|
@@ -353,6 +353,14 @@ module GraphQL
|
|
353
353
|
end
|
354
354
|
end
|
355
355
|
|
356
|
+
def serialize_field_args(field)
|
357
|
+
serialized_args = {}
|
358
|
+
field.arguments.each do |argument|
|
359
|
+
serialized_args[argument.name] = serialize_arg(argument.value)
|
360
|
+
end
|
361
|
+
serialized_args
|
362
|
+
end
|
363
|
+
|
356
364
|
def compared_fragments_key(frag1, frag2, exclusive)
|
357
365
|
# Cache key to not compare two fragments more than once.
|
358
366
|
# The key includes both fragment names sorted (this way we
|
@@ -7,12 +7,12 @@ module GraphQL
|
|
7
7
|
dependency_map = context.dependencies
|
8
8
|
dependency_map.cyclical_definitions.each do |defn|
|
9
9
|
if defn.node.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
|
10
|
-
|
10
|
+
add_error(GraphQL::StaticValidation::FragmentsAreFiniteError.new(
|
11
11
|
"Fragment #{defn.name} contains an infinite loop",
|
12
12
|
nodes: defn.node,
|
13
13
|
path: defn.path,
|
14
14
|
name: defn.name
|
15
|
-
)
|
15
|
+
))
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module StaticValidation
|
4
|
+
module InputObjectNamesAreUnique
|
5
|
+
def on_input_object(node, parent)
|
6
|
+
validate_input_fields(node)
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def validate_input_fields(node)
|
13
|
+
input_field_defns = node.arguments
|
14
|
+
input_fields_by_name = Hash.new { |h, k| h[k] = [] }
|
15
|
+
input_field_defns.each { |a| input_fields_by_name[a.name] << a }
|
16
|
+
|
17
|
+
input_fields_by_name.each do |name, defns|
|
18
|
+
if defns.size > 1
|
19
|
+
error = GraphQL::StaticValidation::InputObjectNamesAreUniqueError.new(
|
20
|
+
"There can be only one input field named \"#{name}\"",
|
21
|
+
nodes: defns,
|
22
|
+
name: name
|
23
|
+
)
|
24
|
+
add_error(error)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module StaticValidation
|
4
|
+
class InputObjectNamesAreUniqueError < StaticValidation::Error
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
def initialize(message, path: nil, nodes: [], name:)
|
8
|
+
super(message, path: path, nodes: nodes)
|
9
|
+
@name = name
|
10
|
+
end
|
11
|
+
|
12
|
+
# A hash representation of this Message
|
13
|
+
def to_h
|
14
|
+
extensions = {
|
15
|
+
"code" => code,
|
16
|
+
"name" => name
|
17
|
+
}
|
18
|
+
|
19
|
+
super.merge({
|
20
|
+
"extensions" => extensions
|
21
|
+
})
|
22
|
+
end
|
23
|
+
|
24
|
+
def code
|
25
|
+
"inputFieldNotUnique"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -19,10 +19,11 @@ module GraphQL
|
|
19
19
|
|
20
20
|
def_delegators :@query, :schema, :document, :fragments, :operations, :warden
|
21
21
|
|
22
|
-
def initialize(query, visitor_class)
|
22
|
+
def initialize(query, visitor_class, max_errors)
|
23
23
|
@query = query
|
24
24
|
@literal_validator = LiteralValidator.new(context: query.context)
|
25
25
|
@errors = []
|
26
|
+
@max_errors = max_errors || Float::INFINITY
|
26
27
|
@on_dependency_resolve_handlers = []
|
27
28
|
@visitor = visitor_class.new(document, self)
|
28
29
|
end
|
@@ -38,6 +39,10 @@ module GraphQL
|
|
38
39
|
def validate_literal(ast_value, type)
|
39
40
|
@literal_validator.validate(ast_value, type)
|
40
41
|
end
|
42
|
+
|
43
|
+
def too_many_errors?
|
44
|
+
@errors.length >= @max_errors
|
45
|
+
end
|
41
46
|
end
|
42
47
|
end
|
43
48
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module StaticValidation
|
4
|
+
class ValidationTimeoutError < StaticValidation::Error
|
5
|
+
def initialize(message, path: nil, nodes: [])
|
6
|
+
super(message, path: path, nodes: nodes)
|
7
|
+
end
|
8
|
+
|
9
|
+
# A hash representation of this Message
|
10
|
+
def to_h
|
11
|
+
extensions = {
|
12
|
+
"code" => code
|
13
|
+
}
|
14
|
+
|
15
|
+
super.merge({
|
16
|
+
"extensions" => extensions
|
17
|
+
})
|
18
|
+
end
|
19
|
+
|
20
|
+
def code
|
21
|
+
"validationTimeout"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -20,8 +20,11 @@ module GraphQL
|
|
20
20
|
|
21
21
|
# Validate `query` against the schema. Returns an array of message hashes.
|
22
22
|
# @param query [GraphQL::Query]
|
23
|
+
# @param validate [Boolean]
|
24
|
+
# @param timeout [Float] Number of seconds to wait before aborting validation. Any positive number may be used, including Floats to specify fractional seconds.
|
25
|
+
# @param max_errors [Integer] Maximum number of errors before aborting validation. Any positive number will limit the number of errors. Defaults to nil for no limit.
|
23
26
|
# @return [Array<Hash>]
|
24
|
-
def validate(query, validate: true)
|
27
|
+
def validate(query, validate: true, timeout: nil, max_errors: nil)
|
25
28
|
query.trace("validate", { validate: validate, query: query }) do
|
26
29
|
can_skip_rewrite = query.context.interpreter? && query.schema.using_ast_analysis? && query.schema.is_a?(Class)
|
27
30
|
errors = if validate == false && can_skip_rewrite
|
@@ -30,23 +33,34 @@ module GraphQL
|
|
30
33
|
rules_to_use = validate ? @rules : []
|
31
34
|
visitor_class = BaseVisitor.including_rules(rules_to_use, rewrite: !can_skip_rewrite)
|
32
35
|
|
33
|
-
context = GraphQL::StaticValidation::ValidationContext.new(query, visitor_class)
|
36
|
+
context = GraphQL::StaticValidation::ValidationContext.new(query, visitor_class, max_errors)
|
34
37
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
begin
|
39
|
+
# CAUTION: Usage of the timeout module makes the assumption that validation rules are stateless Ruby code that requires no cleanup if process was interrupted. This means no blocking IO calls, native gems, locks, or `rescue` clauses that must be reached.
|
40
|
+
# A timeout value of 0 or nil will execute the block without any timeout.
|
41
|
+
Timeout::timeout(timeout) do
|
42
|
+
|
43
|
+
catch(:too_many_validation_errors) do
|
44
|
+
# Attach legacy-style rules.
|
45
|
+
# Only loop through rules if it has legacy-style rules
|
46
|
+
unless (legacy_rules = rules_to_use - GraphQL::StaticValidation::ALL_RULES).empty?
|
47
|
+
legacy_rules.each do |rule_class_or_module|
|
48
|
+
if rule_class_or_module.method_defined?(:validate)
|
49
|
+
rule_class_or_module.new.validate(context)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context.visitor.visit
|
41
55
|
end
|
42
56
|
end
|
57
|
+
rescue Timeout::Error
|
58
|
+
handle_timeout(query, context)
|
43
59
|
end
|
44
60
|
|
45
|
-
context.visitor.visit
|
46
61
|
context.errors
|
47
62
|
end
|
48
63
|
|
49
|
-
|
50
64
|
irep = if errors.empty? && context
|
51
65
|
# Only return this if there are no errors and validation was actually run
|
52
66
|
context.visitor.rewrite_document
|
@@ -60,6 +74,15 @@ module GraphQL
|
|
60
74
|
}
|
61
75
|
end
|
62
76
|
end
|
77
|
+
|
78
|
+
# Invoked when static validation times out.
|
79
|
+
# @param query [GraphQL::Query]
|
80
|
+
# @param context [GraphQL::StaticValidation::ValidationContext]
|
81
|
+
def handle_timeout(query, context)
|
82
|
+
context.errors << GraphQL::StaticValidation::ValidationTimeoutError.new(
|
83
|
+
"Timeout on validation of query"
|
84
|
+
)
|
85
|
+
end
|
63
86
|
end
|
64
87
|
end
|
65
88
|
end
|
@@ -4,6 +4,7 @@ require "graphql/static_validation/definition_dependencies"
|
|
4
4
|
require "graphql/static_validation/type_stack"
|
5
5
|
require "graphql/static_validation/validator"
|
6
6
|
require "graphql/static_validation/validation_context"
|
7
|
+
require "graphql/static_validation/validation_timeout_error"
|
7
8
|
require "graphql/static_validation/literal_validator"
|
8
9
|
require "graphql/static_validation/base_visitor"
|
9
10
|
require "graphql/static_validation/no_validate_visitor"
|
@@ -16,7 +16,10 @@ module GraphQL
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def collect(object)
|
19
|
-
|
19
|
+
default_labels = { key: object['key'], platform_key: object['platform_key'] }
|
20
|
+
custom = object['custom_labels']
|
21
|
+
labels = custom.nil? ? default_labels : default_labels.merge(custom)
|
22
|
+
|
20
23
|
@graphql_gauge.observe object['duration'], labels
|
21
24
|
end
|
22
25
|
|
data/lib/graphql/types/int.rb
CHANGED
@@ -9,8 +9,15 @@ module GraphQL
|
|
9
9
|
MIN = -(2**31)
|
10
10
|
MAX = (2**31) - 1
|
11
11
|
|
12
|
-
def self.coerce_input(value,
|
13
|
-
value.is_a?(Integer)
|
12
|
+
def self.coerce_input(value, ctx)
|
13
|
+
return if !value.is_a?(Integer)
|
14
|
+
|
15
|
+
if value >= MIN && value <= MAX
|
16
|
+
value
|
17
|
+
else
|
18
|
+
err = GraphQL::IntegerDecodingError.new(value)
|
19
|
+
ctx.schema.type_error(err, ctx)
|
20
|
+
end
|
14
21
|
end
|
15
22
|
|
16
23
|
def self.coerce_result(value, ctx)
|
@@ -33,7 +33,8 @@ module GraphQL
|
|
33
33
|
if node_type
|
34
34
|
@node_type = node_type
|
35
35
|
# Add a default `node` field
|
36
|
-
field :node, node_type, null: null, description: "The item at the end of the edge."
|
36
|
+
field :node, node_type, null: null, description: "The item at the end of the edge.",
|
37
|
+
connection: false
|
37
38
|
end
|
38
39
|
@node_type
|
39
40
|
end
|
data/lib/graphql/types/string.rb
CHANGED
@@ -7,7 +7,13 @@ module GraphQL
|
|
7
7
|
|
8
8
|
def self.coerce_result(value, ctx)
|
9
9
|
str = value.to_s
|
10
|
-
str.encoding == Encoding::UTF_8
|
10
|
+
if str.encoding == Encoding::UTF_8
|
11
|
+
str
|
12
|
+
elsif str.frozen?
|
13
|
+
str.encode(Encoding::UTF_8)
|
14
|
+
else
|
15
|
+
str.encode!(Encoding::UTF_8)
|
16
|
+
end
|
11
17
|
rescue EncodingError
|
12
18
|
err = GraphQL::StringEncodingError.new(str)
|
13
19
|
ctx.schema.type_error(err, ctx)
|
data/lib/graphql/version.rb
CHANGED
data/lib/graphql.rb
CHANGED
@@ -129,6 +129,7 @@ require "graphql/introspection"
|
|
129
129
|
require "graphql/analysis_error"
|
130
130
|
require "graphql/coercion_error"
|
131
131
|
require "graphql/invalid_name_error"
|
132
|
+
require "graphql/integer_decoding_error"
|
132
133
|
require "graphql/integer_encoding_error"
|
133
134
|
require "graphql/string_encoding_error"
|
134
135
|
require "graphql/internal_representation"
|
data/readme.md
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
A Ruby implementation of [GraphQL](https://graphql.org/).
|
10
10
|
|
11
11
|
- [Website](https://graphql-ruby.org/)
|
12
|
-
- [API Documentation](https://www.rubydoc.info/
|
12
|
+
- [API Documentation](https://www.rubydoc.info/github/rmosolgo/graphql-ruby)
|
13
13
|
- [Newsletter](https://tinyletter.com/graphql-ruby)
|
14
14
|
|
15
15
|
## Installation
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.11.
|
4
|
+
version: 1.11.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-11-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-ips
|
@@ -445,6 +445,7 @@ files:
|
|
445
445
|
- lib/graphql/id_type.rb
|
446
446
|
- lib/graphql/input_object_type.rb
|
447
447
|
- lib/graphql/int_type.rb
|
448
|
+
- lib/graphql/integer_decoding_error.rb
|
448
449
|
- lib/graphql/integer_encoding_error.rb
|
449
450
|
- lib/graphql/interface_type.rb
|
450
451
|
- lib/graphql/internal_representation.rb
|
@@ -650,6 +651,8 @@ files:
|
|
650
651
|
- lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb
|
651
652
|
- lib/graphql/static_validation/rules/fragments_are_used.rb
|
652
653
|
- lib/graphql/static_validation/rules/fragments_are_used_error.rb
|
654
|
+
- lib/graphql/static_validation/rules/input_object_names_are_unique.rb
|
655
|
+
- lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb
|
653
656
|
- lib/graphql/static_validation/rules/mutation_root_exists.rb
|
654
657
|
- lib/graphql/static_validation/rules/mutation_root_exists_error.rb
|
655
658
|
- lib/graphql/static_validation/rules/no_definitions_are_present.rb
|
@@ -676,6 +679,7 @@ files:
|
|
676
679
|
- lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb
|
677
680
|
- lib/graphql/static_validation/type_stack.rb
|
678
681
|
- lib/graphql/static_validation/validation_context.rb
|
682
|
+
- lib/graphql/static_validation/validation_timeout_error.rb
|
679
683
|
- lib/graphql/static_validation/validator.rb
|
680
684
|
- lib/graphql/string_encoding_error.rb
|
681
685
|
- lib/graphql/string_type.rb
|
@@ -737,7 +741,7 @@ metadata:
|
|
737
741
|
source_code_uri: https://github.com/rmosolgo/graphql-ruby
|
738
742
|
bug_tracker_uri: https://github.com/rmosolgo/graphql-ruby/issues
|
739
743
|
mailing_list_uri: https://tinyletter.com/graphql-ruby
|
740
|
-
post_install_message:
|
744
|
+
post_install_message:
|
741
745
|
rdoc_options: []
|
742
746
|
require_paths:
|
743
747
|
- lib
|
@@ -752,8 +756,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
752
756
|
- !ruby/object:Gem::Version
|
753
757
|
version: '0'
|
754
758
|
requirements: []
|
755
|
-
rubygems_version: 3.
|
756
|
-
signing_key:
|
759
|
+
rubygems_version: 3.2.22
|
760
|
+
signing_key:
|
757
761
|
specification_version: 4
|
758
762
|
summary: A GraphQL language and runtime for Ruby
|
759
763
|
test_files: []
|