graphql 1.10.4 → 1.10.5
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.rb +0 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +117 -105
- data/lib/graphql/execution/lookahead.rb +21 -108
- data/lib/graphql/pagination/active_record_relation_connection.rb +7 -1
- data/lib/graphql/pagination/array_connection.rb +2 -2
- data/lib/graphql/pagination/connection.rb +17 -5
- data/lib/graphql/pagination/relation_connection.rb +3 -2
- data/lib/graphql/query/input_validation_result.rb +23 -6
- data/lib/graphql/query/variables.rb +1 -1
- data/lib/graphql/relay/array_connection.rb +8 -10
- data/lib/graphql/relay/base_connection.rb +19 -11
- data/lib/graphql/relay/relation_connection.rb +8 -10
- data/lib/graphql/scalar_type.rb +14 -1
- data/lib/graphql/schema.rb +6 -0
- data/lib/graphql/schema/build_from_definition.rb +3 -0
- data/lib/graphql/schema/scalar.rb +9 -1
- data/lib/graphql/static_validation/literal_validator.rb +47 -22
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +42 -87
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +17 -5
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +25 -20
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +9 -9
- data/lib/graphql/static_validation/validation_context.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- metadata +2 -3
- data/lib/graphql/literal_validation_error.rb +0 -6
@@ -2,108 +2,63 @@
|
|
2
2
|
module GraphQL
|
3
3
|
module StaticValidation
|
4
4
|
module ArgumentLiteralsAreCompatible
|
5
|
-
# TODO dedup with ArgumentsAreDefined
|
6
5
|
def on_argument(node, parent)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
if !arg_ret_type.kind.input_object?
|
15
|
-
nil
|
16
|
-
else
|
17
|
-
arg_ret_type
|
18
|
-
end
|
19
|
-
end
|
20
|
-
when GraphQL::Language::Nodes::Directive
|
21
|
-
context.schema.directives[parent.name]
|
22
|
-
when GraphQL::Language::Nodes::Field
|
23
|
-
context.field_definition
|
24
|
-
else
|
25
|
-
raise "Unexpected argument parent: #{parent.class} (##{parent})"
|
6
|
+
# Check the child arguments first;
|
7
|
+
# don't add a new error if one of them reports an error
|
8
|
+
super
|
9
|
+
|
10
|
+
# Don't validate variables here
|
11
|
+
if node.value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
|
12
|
+
return
|
26
13
|
end
|
27
14
|
|
28
|
-
if
|
29
|
-
|
30
|
-
if arg_defn
|
31
|
-
begin
|
32
|
-
valid = context.valid_literal?(node.value, arg_defn.type)
|
33
|
-
rescue GraphQL::CoercionError => err
|
34
|
-
context.schema.error_bubbling
|
35
|
-
if !context.schema.error_bubbling && !arg_defn.type.unwrap.kind.scalar?
|
36
|
-
# if error bubbling is disabled and the arg that caused this error isn't a scalar then
|
37
|
-
# short-circuit here so we avoid bubbling this up to whatever input_object / array contains us
|
38
|
-
return super
|
39
|
-
end
|
40
|
-
error = GraphQL::StaticValidation::ArgumentLiteralsAreCompatibleError.new(err.message, nodes: parent, type: "CoercionError", extensions: err.extensions)
|
41
|
-
rescue GraphQL::LiteralValidationError => err
|
42
|
-
# check to see if the ast node that caused the error to be raised is
|
43
|
-
# the same as the node we were checking here.
|
44
|
-
arg_type = arg_defn.type
|
45
|
-
if arg_type.kind.non_null?
|
46
|
-
arg_type = arg_type.of_type
|
47
|
-
end
|
15
|
+
if @context.schema.error_bubbling || context.errors.none? { |err| err.path.take(@path.size) == @path }
|
16
|
+
parent_defn = parent_definition(parent)
|
48
17
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
18
|
+
if parent_defn && (arg_defn = parent_defn.arguments[node.name])
|
19
|
+
validation_result = context.validate_literal(node.value, arg_defn.type)
|
20
|
+
if !validation_result.valid?
|
21
|
+
kind_of_node = node_type(parent)
|
22
|
+
error_arg_name = parent_name(parent, parent_defn)
|
23
|
+
string_value = if node.value == Float::INFINITY
|
24
|
+
""
|
55
25
|
else
|
56
|
-
#
|
57
|
-
node.value == err.ast_value
|
26
|
+
" (#{GraphQL::Language::Printer.new.print(node.value)})"
|
58
27
|
end
|
59
|
-
if !matched
|
60
|
-
# This node isn't the node that caused the error,
|
61
|
-
# So halt this visit but continue visiting the rest of the tree
|
62
|
-
return super
|
63
|
-
end
|
64
|
-
end
|
65
28
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
29
|
+
problems = validation_result.problems
|
30
|
+
first_problem = problems && problems.first
|
31
|
+
if first_problem
|
32
|
+
message = first_problem["message"]
|
33
|
+
# This is some legacy stuff from when `CoercionError` was raised thru the stack
|
34
|
+
if message
|
35
|
+
coerce_extensions = first_problem["extensions"] || {
|
36
|
+
"code" => "argumentLiteralsIncompatible"
|
37
|
+
}
|
74
38
|
end
|
75
|
-
|
76
|
-
GraphQL::StaticValidation::ArgumentLiteralsAreCompatibleError.new(
|
77
|
-
"Argument '#{node.name}' on #{kind_of_node} '#{error_arg_name}' has an invalid value#{string_value}. Expected type '#{arg_defn.type.to_type_signature}'.",
|
78
|
-
nodes: parent,
|
79
|
-
type: kind_of_node,
|
80
|
-
argument: node.name
|
81
|
-
)
|
82
39
|
end
|
83
|
-
add_error(error)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
40
|
|
88
|
-
|
89
|
-
|
41
|
+
error_options = {
|
42
|
+
nodes: parent,
|
43
|
+
type: kind_of_node,
|
44
|
+
argument: node.name
|
45
|
+
}
|
46
|
+
if coerce_extensions
|
47
|
+
error_options[:coerce_extensions] = coerce_extensions
|
48
|
+
end
|
90
49
|
|
50
|
+
message ||= "Argument '#{node.name}' on #{kind_of_node} '#{error_arg_name}' has an invalid value#{string_value}. Expected type '#{arg_defn.type.to_type_signature}'."
|
91
51
|
|
92
|
-
|
52
|
+
error = GraphQL::StaticValidation::ArgumentLiteralsAreCompatibleError.new(
|
53
|
+
message,
|
54
|
+
**error_options
|
55
|
+
)
|
93
56
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
elsif parent.is_a?(GraphQL::Language::Nodes::InputObject)
|
98
|
-
type_defn.name
|
99
|
-
else
|
100
|
-
parent.graphql_name
|
57
|
+
add_error(error)
|
58
|
+
end
|
59
|
+
end
|
101
60
|
end
|
102
61
|
end
|
103
|
-
|
104
|
-
def node_type(parent)
|
105
|
-
parent.class.name.split("::").last
|
106
|
-
end
|
107
62
|
end
|
108
63
|
end
|
109
64
|
end
|
@@ -5,19 +5,31 @@ module GraphQL
|
|
5
5
|
attr_reader :type_name
|
6
6
|
attr_reader :argument_name
|
7
7
|
|
8
|
-
def initialize(message, path: nil, nodes: [], type:, argument: nil, extensions: nil)
|
8
|
+
def initialize(message, path: nil, nodes: [], type:, argument: nil, extensions: nil, coerce_extensions: nil)
|
9
9
|
super(message, path: path, nodes: nodes)
|
10
10
|
@type_name = type
|
11
11
|
@argument_name = argument
|
12
12
|
@extensions = extensions
|
13
|
+
@coerce_extensions = coerce_extensions
|
13
14
|
end
|
14
15
|
|
15
16
|
# A hash representation of this Message
|
16
17
|
def to_h
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
if @coerce_extensions
|
19
|
+
extensions = @coerce_extensions
|
20
|
+
# This is for legacy compat -- but this key is supposed to be a GraphQL type name :confounded:
|
21
|
+
extensions["typeName"] = "CoercionError"
|
22
|
+
else
|
23
|
+
extensions = {
|
24
|
+
"code" => code,
|
25
|
+
"typeName" => type_name
|
26
|
+
}
|
27
|
+
|
28
|
+
if argument_name
|
29
|
+
extensions["argumentName"] = argument_name
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
21
33
|
extensions.merge!(@extensions) unless @extensions.nil?
|
22
34
|
super.merge({
|
23
35
|
"extensions" => extensions
|
@@ -3,26 +3,7 @@ module GraphQL
|
|
3
3
|
module StaticValidation
|
4
4
|
module ArgumentsAreDefined
|
5
5
|
def on_argument(node, parent)
|
6
|
-
parent_defn =
|
7
|
-
when GraphQL::Language::Nodes::InputObject
|
8
|
-
arg_defn = context.argument_definition
|
9
|
-
if arg_defn.nil?
|
10
|
-
nil
|
11
|
-
else
|
12
|
-
arg_ret_type = arg_defn.type.unwrap
|
13
|
-
if arg_ret_type.kind.input_object?
|
14
|
-
arg_ret_type
|
15
|
-
else
|
16
|
-
nil
|
17
|
-
end
|
18
|
-
end
|
19
|
-
when GraphQL::Language::Nodes::Directive
|
20
|
-
context.schema.directives[parent.name]
|
21
|
-
when GraphQL::Language::Nodes::Field
|
22
|
-
context.field_definition
|
23
|
-
else
|
24
|
-
raise "Unexpected argument parent: #{parent.class} (##{parent})"
|
25
|
-
end
|
6
|
+
parent_defn = parent_definition(parent)
|
26
7
|
|
27
8
|
if parent_defn && context.warden.arguments(parent_defn).any? { |arg| arg.name == node.name }
|
28
9
|
super
|
@@ -44,6 +25,7 @@ module GraphQL
|
|
44
25
|
|
45
26
|
private
|
46
27
|
|
28
|
+
# TODO smell: these methods are added to all visitors, since they're included in a module.
|
47
29
|
def parent_name(parent, type_defn)
|
48
30
|
case parent
|
49
31
|
when GraphQL::Language::Nodes::Field
|
@@ -60,6 +42,29 @@ module GraphQL
|
|
60
42
|
def node_type(parent)
|
61
43
|
parent.class.name.split("::").last
|
62
44
|
end
|
45
|
+
|
46
|
+
def parent_definition(parent)
|
47
|
+
case parent
|
48
|
+
when GraphQL::Language::Nodes::InputObject
|
49
|
+
arg_defn = context.argument_definition
|
50
|
+
if arg_defn.nil?
|
51
|
+
nil
|
52
|
+
else
|
53
|
+
arg_ret_type = arg_defn.type.unwrap
|
54
|
+
if arg_ret_type.kind.input_object?
|
55
|
+
arg_ret_type
|
56
|
+
else
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
when GraphQL::Language::Nodes::Directive
|
61
|
+
context.schema.directives[parent.name]
|
62
|
+
when GraphQL::Language::Nodes::Field
|
63
|
+
context.field_definition
|
64
|
+
else
|
65
|
+
raise "Unexpected argument parent: #{parent.class} (##{parent})"
|
66
|
+
end
|
67
|
+
end
|
63
68
|
end
|
64
69
|
end
|
65
70
|
end
|
@@ -17,22 +17,22 @@ module GraphQL
|
|
17
17
|
if type.nil?
|
18
18
|
# This is handled by another validator
|
19
19
|
else
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
20
|
+
validation_result = context.validate_literal(value, type)
|
21
|
+
|
22
|
+
if !validation_result.valid?
|
23
|
+
problems = validation_result.problems
|
24
|
+
first_problem = problems && problems.first
|
25
|
+
if first_problem
|
26
|
+
error_message = first_problem["message"]
|
27
|
+
end
|
27
28
|
|
28
|
-
if !valid
|
29
29
|
error_message ||= "Default value for $#{node.name} doesn't match type #{type.to_type_signature}"
|
30
30
|
add_error(GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTypedError.new(
|
31
31
|
error_message,
|
32
32
|
nodes: node,
|
33
33
|
name: node.name,
|
34
34
|
type: type.to_type_signature,
|
35
|
-
error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_TYPE]
|
35
|
+
error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_TYPE],
|
36
36
|
))
|
37
37
|
end
|
38
38
|
end
|
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.10.
|
4
|
+
version: 1.10.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-03-
|
11
|
+
date: 2020-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-ips
|
@@ -482,7 +482,6 @@ files:
|
|
482
482
|
- lib/graphql/language/token.rb
|
483
483
|
- lib/graphql/language/visitor.rb
|
484
484
|
- lib/graphql/list_type.rb
|
485
|
-
- lib/graphql/literal_validation_error.rb
|
486
485
|
- lib/graphql/load_application_object_failed_error.rb
|
487
486
|
- lib/graphql/name_validator.rb
|
488
487
|
- lib/graphql/non_null_type.rb
|