graphql 1.11.11 → 1.11.12
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/query/validation_pipeline.rb +1 -1
- data/lib/graphql/schema.rb +26 -11
- data/lib/graphql/static_validation/base_visitor.rb +3 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +4 -4
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
- data/lib/graphql/static_validation/validation_context.rb +6 -1
- data/lib/graphql/static_validation/validator.rb +14 -10
- data/lib/graphql/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee8b1fd3f821af97c7baeab840141edf4251ad4cf2edd538d204b230d73d3388
|
4
|
+
data.tar.gz: a72a7d21e223f349f75f66e28e0a3cb421dceb21ad9085aca804ed912cba142f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71bf8a12a950c16ca7f2fdd5ffc752a469088926bab9955bf6df406dd2a264994506ed98f144ca0b1c5e6dea45f387f3e8c97091bfb1e9e829f2d815c10beac8
|
7
|
+
data.tar.gz: ef9a2d5ca4e871099e11f39601431968c38f8af288f92de0c50e571dc5088171b9dbbee55602e9d68000036ab6c530a297c57b1945d1b96eff76136b0142531d
|
@@ -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, timeout: @schema.validate_timeout)
|
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/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
|
-
:validate_timeout, :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
|
-
:validate_timeout, :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, timeout: validate_timeout)
|
369
|
+
res = validator.validate(query, timeout: validate_timeout, max_errors: validate_max_errors)
|
370
370
|
res[:errors]
|
371
371
|
end
|
372
372
|
|
@@ -951,6 +951,7 @@ module GraphQL
|
|
951
951
|
schema_defn.mutation = mutation && mutation.graphql_definition
|
952
952
|
schema_defn.subscription = subscription && subscription.graphql_definition
|
953
953
|
schema_defn.validate_timeout = validate_timeout
|
954
|
+
schema_defn.validate_max_errors = validate_max_errors
|
954
955
|
schema_defn.max_complexity = max_complexity
|
955
956
|
schema_defn.error_bubbling = error_bubbling
|
956
957
|
schema_defn.max_depth = max_depth
|
@@ -1119,14 +1120,15 @@ module GraphQL
|
|
1119
1120
|
type.possible_types(context: context)
|
1120
1121
|
else
|
1121
1122
|
stored_possible_types = own_possible_types[type.graphql_name]
|
1122
|
-
visible_possible_types = stored_possible_types
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
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
|
1130
1132
|
visible_possible_types ||
|
1131
1133
|
introspection_system.possible_types[type.graphql_name] ||
|
1132
1134
|
(
|
@@ -1285,6 +1287,19 @@ module GraphQL
|
|
1285
1287
|
end
|
1286
1288
|
end
|
1287
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
|
+
|
1288
1303
|
attr_writer :max_complexity
|
1289
1304
|
|
1290
1305
|
def max_complexity(max_complexity = nil)
|
@@ -193,26 +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
205
|
if !same_arguments?(node1, node2)
|
206
206
|
args = [serialize_field_args(node1), serialize_field_args(node2)]
|
207
207
|
conflicts = args.map { |arg| GraphQL::Language.serialize(arg) }.join(" or ")
|
208
208
|
msg = "Field '#{response_key}' has an argument conflict: #{conflicts}?"
|
209
|
-
|
209
|
+
add_error(GraphQL::StaticValidation::FieldsWillMergeError.new(
|
210
210
|
msg,
|
211
211
|
nodes: [node1, node2],
|
212
212
|
path: [],
|
213
213
|
field_name: response_key,
|
214
214
|
conflicts: conflicts
|
215
|
-
)
|
215
|
+
))
|
216
216
|
end
|
217
217
|
end
|
218
218
|
|
@@ -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
|
@@ -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
|
@@ -22,8 +22,9 @@ module GraphQL
|
|
22
22
|
# @param query [GraphQL::Query]
|
23
23
|
# @param validate [Boolean]
|
24
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.
|
25
26
|
# @return [Array<Hash>]
|
26
|
-
def validate(query, validate: true, timeout: nil)
|
27
|
+
def validate(query, validate: true, timeout: nil, max_errors: nil)
|
27
28
|
query.trace("validate", { validate: validate, query: query }) do
|
28
29
|
can_skip_rewrite = query.context.interpreter? && query.schema.using_ast_analysis? && query.schema.is_a?(Class)
|
29
30
|
errors = if validate == false && can_skip_rewrite
|
@@ -32,23 +33,26 @@ module GraphQL
|
|
32
33
|
rules_to_use = validate ? @rules : []
|
33
34
|
visitor_class = BaseVisitor.including_rules(rules_to_use, rewrite: !can_skip_rewrite)
|
34
35
|
|
35
|
-
context = GraphQL::StaticValidation::ValidationContext.new(query, visitor_class)
|
36
|
+
context = GraphQL::StaticValidation::ValidationContext.new(query, visitor_class, max_errors)
|
36
37
|
|
37
38
|
begin
|
38
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.
|
39
40
|
# A timeout value of 0 or nil will execute the block without any timeout.
|
40
41
|
Timeout::timeout(timeout) do
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
47
51
|
end
|
48
52
|
end
|
49
|
-
end
|
50
53
|
|
51
|
-
|
54
|
+
context.visitor.visit
|
55
|
+
end
|
52
56
|
end
|
53
57
|
rescue Timeout::Error
|
54
58
|
handle_timeout(query, context)
|
data/lib/graphql/version.rb
CHANGED
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.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-03-
|
11
|
+
date: 2025-03-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-ips
|