graphql 2.6.14 → 2.6.15
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/generators/graphql/templates/graphql_controller.erb +7 -1
- data/lib/graphql/analysis/max_query_complexity.rb +2 -1
- data/lib/graphql/analysis/max_query_depth.rb +2 -1
- data/lib/graphql/analysis/query_complexity.rb +2 -1
- data/lib/graphql/analysis/query_depth.rb +1 -1
- data/lib/graphql/analysis/visitor.rb +14 -2
- data/lib/graphql/analysis.rb +4 -5
- data/lib/graphql/analysis_error.rb +1 -1
- data/lib/graphql/coercion_error.rb +1 -1
- data/lib/graphql/current.rb +5 -1
- data/lib/graphql/dashboard.rb +1 -1
- data/lib/graphql/date_encoding_error.rb +3 -1
- data/lib/graphql/duration_encoding_error.rb +3 -1
- data/lib/graphql/execution/directive_checks.rb +2 -1
- data/lib/graphql/execution/errors.rb +18 -7
- data/lib/graphql/execution/field_resolve_step.rb +3 -3
- data/lib/graphql/execution/input_values.rb +160 -120
- data/lib/graphql/execution/interpreter/runtime.rb +9 -5
- data/lib/graphql/execution/lookahead.rb +19 -8
- data/lib/graphql/execution/next.rb +1 -0
- data/lib/graphql/execution/runner.rb +19 -12
- data/lib/graphql/execution/selections_step.rb +1 -1
- data/lib/graphql/execution/variable_values.rb +248 -0
- data/lib/graphql/float_decoding_error.rb +3 -1
- data/lib/graphql/integer_decoding_error.rb +3 -1
- data/lib/graphql/introspection/base_object.rb +1 -1
- data/lib/graphql/introspection/directive_location_enum.rb +1 -1
- data/lib/graphql/introspection/directive_type.rb +3 -1
- data/lib/graphql/introspection/dynamic_fields.rb +3 -1
- data/lib/graphql/introspection/enum_value_type.rb +3 -1
- data/lib/graphql/introspection/field_type.rb +5 -1
- data/lib/graphql/introspection/type_kind_enum.rb +1 -1
- data/lib/graphql/introspection.rb +2 -1
- data/lib/graphql/language/comment.rb +2 -1
- data/lib/graphql/language/generation.rb +2 -1
- data/lib/graphql/language/lexer.rb +29 -21
- data/lib/graphql/language/parser.rb +10 -7
- data/lib/graphql/language.rb +1 -1
- data/lib/graphql/name_validator.rb +2 -1
- data/lib/graphql/pagination.rb +1 -1
- data/lib/graphql/query/fingerprint.rb +2 -1
- data/lib/graphql/query/partial.rb +4 -0
- data/lib/graphql/query.rb +8 -12
- data/lib/graphql/railtie.rb +1 -1
- data/lib/graphql/relay.rb +1 -1
- data/lib/graphql/rubocop.rb +1 -1
- data/lib/graphql/runtime_error.rb +1 -1
- data/lib/graphql/runtime_type_error.rb +1 -1
- data/lib/graphql/schema/always_visible.rb +3 -1
- data/lib/graphql/schema/base_64_encoder.rb +3 -1
- data/lib/graphql/schema/built_in_types.rb +2 -2
- data/lib/graphql/schema/directive/deprecated.rb +1 -1
- data/lib/graphql/schema/directive/include.rb +2 -1
- data/lib/graphql/schema/directive/skip.rb +2 -1
- data/lib/graphql/schema/directive/specified_by.rb +1 -1
- data/lib/graphql/schema/field/scope_extension.rb +2 -1
- data/lib/graphql/schema/field.rb +3 -0
- data/lib/graphql/schema/find_inherited_value.rb +5 -1
- data/lib/graphql/schema/member/graphql_type_names.rb +1 -1
- data/lib/graphql/schema/member/has_directives.rb +20 -22
- data/lib/graphql/schema/member/has_path.rb +2 -1
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +2 -1
- data/lib/graphql/schema/member.rb +3 -2
- data/lib/graphql/schema/mutation.rb +6 -1
- data/lib/graphql/schema/object.rb +1 -1
- data/lib/graphql/schema/resolver.rb +2 -2
- data/lib/graphql/schema/type_expression.rb +3 -1
- data/lib/graphql/schema/validator/all_validator.rb +6 -3
- data/lib/graphql/static_validation/all_rules.rb +1 -1
- data/lib/graphql/static_validation/base_visitor.rb +125 -53
- data/lib/graphql/static_validation/definition_dependencies.rb +14 -2
- data/lib/graphql/static_validation/interpreter_visitor.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +4 -1
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +8 -4
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -1
- data/lib/graphql/static_validation/rules/fragments_are_named.rb +2 -1
- data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +4 -1
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +6 -3
- data/lib/graphql/static_validation/rules/fragments_are_used.rb +2 -1
- data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +3 -1
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +3 -2
- data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +4 -1
- data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +4 -1
- data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +4 -1
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +9 -2
- data/lib/graphql/static_validation/rules/query_root_exists.rb +3 -2
- data/lib/graphql/static_validation/rules/query_root_exists_error.rb +4 -1
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +10 -4
- data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +8 -6
- data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +4 -1
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +5 -4
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +2 -1
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +2 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +1 -1
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
- data/lib/graphql/static_validation/validation_context.rb +49 -14
- data/lib/graphql/static_validation/validation_timeout_error.rb +4 -1
- data/lib/graphql/static_validation.rb +1 -2
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +14 -13
- data/lib/graphql/testing.rb +1 -1
- data/lib/graphql/tracing/legacy_trace.rb +1 -1
- data/lib/graphql/tracing/null_trace.rb +1 -1
- data/lib/graphql/types/big_int.rb +4 -1
- data/lib/graphql/types/boolean.rb +3 -1
- data/lib/graphql/types/id.rb +3 -1
- data/lib/graphql/types/iso_8601_date.rb +1 -0
- data/lib/graphql/types/iso_8601_date_time.rb +6 -2
- data/lib/graphql/types/iso_8601_duration.rb +3 -0
- data/lib/graphql/types/relay/base_connection.rb +1 -1
- data/lib/graphql/types/relay/base_edge.rb +1 -1
- data/lib/graphql/types/relay/node.rb +1 -1
- data/lib/graphql/types/relay/page_info.rb +1 -1
- data/lib/graphql/types/relay/page_info_behaviors.rb +4 -1
- data/lib/graphql/types/relay.rb +1 -1
- data/lib/graphql/types/string.rb +1 -0
- data/lib/graphql/types.rb +1 -1
- data/lib/graphql/version.rb +2 -2
- metadata +3 -4
- data/lib/graphql/query/variables.rb +0 -99
- data/lib/graphql/static_validation/literal_validator.rb +0 -157
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# typed:
|
|
2
|
+
# typed: strict
|
|
3
3
|
module GraphQL
|
|
4
4
|
module StaticValidation
|
|
5
5
|
class BaseVisitor < GraphQL::Language::StaticVisitor
|
|
6
|
+
#: (GraphQL::Language::Nodes::Document document, GraphQL::StaticValidation::ValidationContext context) -> void
|
|
6
7
|
def initialize(document, context)
|
|
7
|
-
@path = []
|
|
8
|
-
@path_depth = 0
|
|
9
|
-
@current_object_type = nil
|
|
10
|
-
@parent_object_type = nil
|
|
11
|
-
@current_field_definition = nil
|
|
12
|
-
@current_argument_definition = nil
|
|
13
|
-
@parent_argument_definition = nil
|
|
14
|
-
@current_directive_definition = nil
|
|
15
|
-
@context = context
|
|
16
|
-
@types = context.
|
|
17
|
-
@schema = context.schema
|
|
18
|
-
@inline_fragment_paths = {}
|
|
19
|
-
@field_unwrapped_types = {}.compare_by_identity
|
|
20
|
-
@child_positions = {}.compare_by_identity
|
|
8
|
+
@path = [] #: Array[String | Integer]
|
|
9
|
+
@path_depth = 0 #: Integer
|
|
10
|
+
@current_object_type = nil #: GraphQL::Schema::Member::type_definition?
|
|
11
|
+
@parent_object_type = nil #: GraphQL::Schema::Member::type_definition?
|
|
12
|
+
@current_field_definition = nil #: GraphQL::Schema::Field?
|
|
13
|
+
@current_argument_definition = nil #: GraphQL::Schema::Argument?
|
|
14
|
+
@parent_argument_definition = nil #: GraphQL::Schema::Argument?
|
|
15
|
+
@current_directive_definition = nil #: singleton(GraphQL::Schema::Directive)?
|
|
16
|
+
@context = context #: GraphQL::StaticValidation::ValidationContext
|
|
17
|
+
@types = context.types #: GraphQL::Schema::Visibility::Profile | GraphQL::Schema::Warden::VisibilityProfile
|
|
18
|
+
@schema = context.schema #: singleton(GraphQL::Schema)
|
|
19
|
+
@inline_fragment_paths = {} #: Hash[String, String]
|
|
20
|
+
@field_unwrapped_types = {}.compare_by_identity #: Hash[GraphQL::Schema::Field, GraphQL::Schema::Member::type_definition]
|
|
21
|
+
@child_positions = {}.compare_by_identity #: Hash[GraphQL::Language::Nodes::AbstractNode, Hash[GraphQL::Language::Nodes::AbstractNode, Integer]]
|
|
21
22
|
super(document)
|
|
22
23
|
end
|
|
23
24
|
|
|
25
|
+
#: GraphQL::StaticValidation::ValidationContext
|
|
24
26
|
attr_reader :context
|
|
25
27
|
|
|
26
28
|
# **Returns**
|
|
@@ -29,8 +31,9 @@ module GraphQL
|
|
|
29
31
|
#
|
|
30
32
|
# :call-seq:
|
|
31
33
|
# path() -> Array[String]
|
|
34
|
+
#: () -> Array[String | Integer]
|
|
32
35
|
def path
|
|
33
|
-
@path[0, @path_depth]
|
|
36
|
+
@path[0, @path_depth] #: as !nil
|
|
34
37
|
end
|
|
35
38
|
|
|
36
39
|
# Build a class to visit the AST and perform validation,
|
|
@@ -46,6 +49,7 @@ module GraphQL
|
|
|
46
49
|
#
|
|
47
50
|
# :call-seq:
|
|
48
51
|
# including_rules(Array[Module | Class] rules) -> Class
|
|
52
|
+
#: (Array[Module[untyped]]) -> singleton(GraphQL::StaticValidation::BaseVisitor)
|
|
49
53
|
def self.including_rules(rules)
|
|
50
54
|
if rules.empty?
|
|
51
55
|
# It's not doing _anything?!?_
|
|
@@ -69,48 +73,71 @@ module GraphQL
|
|
|
69
73
|
end
|
|
70
74
|
end
|
|
71
75
|
|
|
76
|
+
#--
|
|
77
|
+
# @requires_ancestor: GraphQL::StaticValidation::BaseVisitor
|
|
72
78
|
module ContextMethods
|
|
79
|
+
# BaseVisitor#initialize sets these. They're re-assigned here so Sorbet knows their types in this module,
|
|
80
|
+
# because the hooks below use them directly instead of calling the readers on every node.
|
|
81
|
+
#: (GraphQL::Language::Nodes::Document document, GraphQL::StaticValidation::ValidationContext context) -> void
|
|
82
|
+
def initialize(document, context)
|
|
83
|
+
super
|
|
84
|
+
@path = path_parts #: Array[String | Integer]
|
|
85
|
+
@path_depth = path_depth #: Integer
|
|
86
|
+
@types = types #: GraphQL::Schema::Visibility::Profile | GraphQL::Schema::Warden::VisibilityProfile
|
|
87
|
+
@inline_fragment_paths = inline_fragment_paths #: Hash[String, String]
|
|
88
|
+
@field_unwrapped_types = field_unwrapped_types #: Hash[GraphQL::Schema::Field, GraphQL::Schema::Member::type_definition]
|
|
89
|
+
@child_positions = child_positions_by_parent #: Hash[GraphQL::Language::Nodes::AbstractNode, Hash[GraphQL::Language::Nodes::AbstractNode, Integer]]
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
#: (GraphQL::Language::Nodes::OperationDefinition node, GraphQL::Language::Nodes::AbstractNode? parent) -> void
|
|
73
93
|
def on_operation_definition(node, parent)
|
|
74
|
-
object_type =
|
|
94
|
+
object_type = schema.root_type_for_operation(node.operation_type)
|
|
75
95
|
prev_parent_ot = @parent_object_type
|
|
76
|
-
@parent_object_type = @current_object_type
|
|
77
|
-
@current_object_type = object_type
|
|
78
|
-
|
|
79
|
-
@path_depth
|
|
96
|
+
@parent_object_type = @current_object_type #: GraphQL::Schema::Member::type_definition?
|
|
97
|
+
@current_object_type = object_type #: GraphQL::Schema::Member::type_definition?
|
|
98
|
+
path_depth = @path_depth
|
|
99
|
+
@path[path_depth] = "#{node.operation_type}#{node.name ? " #{node.name}" : ""}"
|
|
100
|
+
@path_depth = path_depth + 1
|
|
80
101
|
super
|
|
81
102
|
@current_object_type = @parent_object_type
|
|
82
103
|
@parent_object_type = prev_parent_ot
|
|
83
|
-
@path_depth
|
|
104
|
+
@path_depth = path_depth
|
|
84
105
|
end
|
|
85
106
|
|
|
107
|
+
#: (GraphQL::Language::Nodes::FragmentDefinition node, GraphQL::Language::Nodes::AbstractNode? parent) -> void
|
|
86
108
|
def on_fragment_definition(node, parent)
|
|
87
|
-
|
|
88
|
-
|
|
109
|
+
# The type is always present when parsed, but may be missing on a hand-built node:
|
|
110
|
+
fragment_type = node.type #: GraphQL::Language::Nodes::TypeName?
|
|
111
|
+
object_type = if fragment_type
|
|
112
|
+
@types.type(fragment_type.name)
|
|
89
113
|
else
|
|
90
114
|
@current_object_type
|
|
91
115
|
end
|
|
92
116
|
prev_parent_ot = @parent_object_type
|
|
93
117
|
@parent_object_type = @current_object_type
|
|
94
118
|
@current_object_type = object_type
|
|
95
|
-
|
|
96
|
-
@path_depth
|
|
119
|
+
path_depth = @path_depth
|
|
120
|
+
@path[path_depth] = "fragment #{node.name}"
|
|
121
|
+
@path_depth = path_depth + 1
|
|
97
122
|
super
|
|
98
123
|
@current_object_type = @parent_object_type
|
|
99
124
|
@parent_object_type = prev_parent_ot
|
|
100
|
-
@path_depth
|
|
125
|
+
@path_depth = path_depth
|
|
101
126
|
end
|
|
102
127
|
|
|
103
|
-
INLINE_FRAGMENT_NO_TYPE = "..."
|
|
128
|
+
INLINE_FRAGMENT_NO_TYPE = "..." #: String
|
|
104
129
|
|
|
130
|
+
#: (GraphQL::Language::Nodes::InlineFragment node, GraphQL::Language::Nodes::AbstractNode? parent) -> void
|
|
105
131
|
def on_inline_fragment(node, parent)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
@path_depth
|
|
132
|
+
path_depth = @path_depth
|
|
133
|
+
if (node_type = node.type)
|
|
134
|
+
object_type = @types.type(node_type.name)
|
|
135
|
+
@path[path_depth] = @inline_fragment_paths[node_type.name] ||= -"... on #{node_type.to_query_string}"
|
|
136
|
+
@path_depth = path_depth + 1
|
|
110
137
|
else
|
|
111
138
|
object_type = @current_object_type
|
|
112
|
-
@path[
|
|
113
|
-
@path_depth
|
|
139
|
+
@path[path_depth] = INLINE_FRAGMENT_NO_TYPE
|
|
140
|
+
@path_depth = path_depth + 1
|
|
114
141
|
end
|
|
115
142
|
prev_parent_ot = @parent_object_type
|
|
116
143
|
@parent_object_type = @current_object_type
|
|
@@ -118,14 +145,15 @@ module GraphQL
|
|
|
118
145
|
super
|
|
119
146
|
@current_object_type = @parent_object_type
|
|
120
147
|
@parent_object_type = prev_parent_ot
|
|
121
|
-
@path_depth
|
|
148
|
+
@path_depth = path_depth
|
|
122
149
|
end
|
|
123
150
|
|
|
151
|
+
#: (GraphQL::Language::Nodes::Field node, GraphQL::Language::Nodes::AbstractNode? parent) -> void
|
|
124
152
|
def on_field(node, parent)
|
|
125
153
|
parent_type = @current_object_type
|
|
126
154
|
field_definition = @types.field(parent_type, node.name)
|
|
127
155
|
prev_field_definition = @current_field_definition
|
|
128
|
-
@current_field_definition = field_definition
|
|
156
|
+
@current_field_definition = field_definition #: GraphQL::Schema::Field?
|
|
129
157
|
prev_parent_ot = @parent_object_type
|
|
130
158
|
@parent_object_type = @current_object_type
|
|
131
159
|
if field_definition
|
|
@@ -133,23 +161,26 @@ module GraphQL
|
|
|
133
161
|
else
|
|
134
162
|
@current_object_type = nil
|
|
135
163
|
end
|
|
136
|
-
|
|
137
|
-
@path_depth
|
|
164
|
+
path_depth = @path_depth
|
|
165
|
+
@path[path_depth] = node.alias || node.name
|
|
166
|
+
@path_depth = path_depth + 1
|
|
138
167
|
super
|
|
139
168
|
@current_field_definition = prev_field_definition
|
|
140
169
|
@current_object_type = @parent_object_type
|
|
141
170
|
@parent_object_type = prev_parent_ot
|
|
142
|
-
@path_depth
|
|
171
|
+
@path_depth = path_depth
|
|
143
172
|
end
|
|
144
173
|
|
|
174
|
+
#: (GraphQL::Language::Nodes::Directive node, GraphQL::Language::Nodes::AbstractNode? parent) -> void
|
|
145
175
|
def on_directive(node, parent)
|
|
146
|
-
directive_defn =
|
|
176
|
+
directive_defn = context.schema_directives[node.name]
|
|
147
177
|
prev_directive_definition = @current_directive_definition
|
|
148
|
-
@current_directive_definition = directive_defn
|
|
178
|
+
@current_directive_definition = directive_defn #: singleton(GraphQL::Schema::Directive)?
|
|
149
179
|
super
|
|
150
180
|
@current_directive_definition = prev_directive_definition
|
|
151
181
|
end
|
|
152
182
|
|
|
183
|
+
#: (GraphQL::Language::Nodes::Argument node, GraphQL::Language::Nodes::AbstractNode? parent) -> void
|
|
153
184
|
def on_argument(node, parent)
|
|
154
185
|
argument_defn = if (arg = @current_argument_definition)
|
|
155
186
|
arg_type = arg.type.unwrap
|
|
@@ -167,39 +198,45 @@ module GraphQL
|
|
|
167
198
|
end
|
|
168
199
|
|
|
169
200
|
prev_parent = @parent_argument_definition
|
|
170
|
-
@parent_argument_definition = @current_argument_definition
|
|
171
|
-
@current_argument_definition = argument_defn
|
|
172
|
-
|
|
173
|
-
@path_depth
|
|
201
|
+
@parent_argument_definition = @current_argument_definition #: GraphQL::Schema::Argument?
|
|
202
|
+
@current_argument_definition = argument_defn #: GraphQL::Schema::Argument?
|
|
203
|
+
path_depth = @path_depth
|
|
204
|
+
@path[path_depth] = node.name
|
|
205
|
+
@path_depth = path_depth + 1
|
|
174
206
|
super
|
|
175
207
|
@current_argument_definition = @parent_argument_definition
|
|
176
208
|
@parent_argument_definition = prev_parent
|
|
177
|
-
@path_depth
|
|
209
|
+
@path_depth = path_depth
|
|
178
210
|
@child_positions.delete(node)
|
|
179
211
|
end
|
|
180
212
|
|
|
213
|
+
#: (GraphQL::Language::Nodes::FragmentSpread node, GraphQL::Language::Nodes::AbstractNode? parent) -> void
|
|
181
214
|
def on_fragment_spread(node, parent)
|
|
182
|
-
|
|
183
|
-
@path_depth
|
|
215
|
+
path_depth = @path_depth
|
|
216
|
+
@path[path_depth] = "... #{node.name}"
|
|
217
|
+
@path_depth = path_depth + 1
|
|
184
218
|
super
|
|
185
|
-
@path_depth
|
|
219
|
+
@path_depth = path_depth
|
|
186
220
|
end
|
|
187
221
|
|
|
222
|
+
#: (GraphQL::Language::Nodes::InputObject node, GraphQL::Language::Nodes::AbstractNode parent) -> void
|
|
188
223
|
def on_input_object(node, parent)
|
|
189
224
|
arg_defn = @current_argument_definition
|
|
190
225
|
if arg_defn && arg_defn.type.list?
|
|
191
|
-
|
|
192
|
-
@path_depth
|
|
226
|
+
path_depth = @path_depth
|
|
227
|
+
@path[path_depth] = child_positions(parent)[node] #: as !nil
|
|
228
|
+
@path_depth = path_depth + 1
|
|
193
229
|
super
|
|
194
|
-
@path_depth
|
|
230
|
+
@path_depth = path_depth
|
|
195
231
|
else
|
|
196
232
|
super
|
|
197
233
|
end
|
|
198
234
|
end
|
|
199
235
|
|
|
236
|
+
#: (GraphQL::Language::Nodes::AbstractNode parent) -> Hash[GraphQL::Language::Nodes::AbstractNode, Integer]
|
|
200
237
|
def child_positions(parent)
|
|
201
238
|
@child_positions[parent] ||= begin
|
|
202
|
-
positions = {}.compare_by_identity
|
|
239
|
+
positions = {}.compare_by_identity #: Hash[GraphQL::Language::Nodes::AbstractNode, Integer]
|
|
203
240
|
parent.children.each_with_index { |child, index| positions[child] ||= index }
|
|
204
241
|
positions
|
|
205
242
|
end
|
|
@@ -211,6 +248,7 @@ module GraphQL
|
|
|
211
248
|
#
|
|
212
249
|
# :call-seq:
|
|
213
250
|
# type_definition() -> GraphQL::BaseType
|
|
251
|
+
#: () -> GraphQL::Schema::Member::type_definition?
|
|
214
252
|
def type_definition
|
|
215
253
|
@current_object_type
|
|
216
254
|
end
|
|
@@ -221,6 +259,7 @@ module GraphQL
|
|
|
221
259
|
#
|
|
222
260
|
# :call-seq:
|
|
223
261
|
# parent_type_definition() -> GraphQL::BaseType
|
|
262
|
+
#: () -> GraphQL::Schema::Member::type_definition?
|
|
224
263
|
def parent_type_definition
|
|
225
264
|
@parent_object_type
|
|
226
265
|
end
|
|
@@ -231,6 +270,7 @@ module GraphQL
|
|
|
231
270
|
#
|
|
232
271
|
# :call-seq:
|
|
233
272
|
# field_definition() -> GraphQL::Field | nil
|
|
273
|
+
#: () -> GraphQL::Schema::Field?
|
|
234
274
|
def field_definition
|
|
235
275
|
@current_field_definition
|
|
236
276
|
end
|
|
@@ -241,6 +281,7 @@ module GraphQL
|
|
|
241
281
|
#
|
|
242
282
|
# :call-seq:
|
|
243
283
|
# directive_definition() -> GraphQL::Directive | nil
|
|
284
|
+
#: () -> singleton(GraphQL::Schema::Directive)?
|
|
244
285
|
def directive_definition
|
|
245
286
|
@current_directive_definition
|
|
246
287
|
end
|
|
@@ -251,6 +292,7 @@ module GraphQL
|
|
|
251
292
|
#
|
|
252
293
|
# :call-seq:
|
|
253
294
|
# argument_definition() -> GraphQL::Argument | nil
|
|
295
|
+
#: () -> GraphQL::Schema::Argument?
|
|
254
296
|
def argument_definition
|
|
255
297
|
# Return the parent argument definition (not the current one).
|
|
256
298
|
@parent_argument_definition
|
|
@@ -262,6 +304,36 @@ module GraphQL
|
|
|
262
304
|
|
|
263
305
|
private
|
|
264
306
|
|
|
307
|
+
# These readers expose the visitor's state to `ContextMethods` and to rule modules.
|
|
308
|
+
# (Sorbet doesn't let a module see a class's instance variables, even with `@requires_ancestor`.)
|
|
309
|
+
|
|
310
|
+
#: GraphQL::Schema::Visibility::Profile | GraphQL::Schema::Warden::VisibilityProfile
|
|
311
|
+
attr_reader :types
|
|
312
|
+
|
|
313
|
+
#: singleton(GraphQL::Schema)
|
|
314
|
+
attr_reader :schema
|
|
315
|
+
|
|
316
|
+
# The path entries for every level visited so far. Only the first `path_depth` of them are current; see [path](rdoc-ref:#path).
|
|
317
|
+
#: () -> Array[String | Integer]
|
|
318
|
+
def path_parts
|
|
319
|
+
@path
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
#: Integer
|
|
323
|
+
attr_accessor :path_depth
|
|
324
|
+
|
|
325
|
+
#: Hash[String, String]
|
|
326
|
+
attr_reader :inline_fragment_paths
|
|
327
|
+
|
|
328
|
+
#: Hash[GraphQL::Schema::Field, GraphQL::Schema::Member::type_definition]
|
|
329
|
+
attr_reader :field_unwrapped_types
|
|
330
|
+
|
|
331
|
+
#: () -> Hash[GraphQL::Language::Nodes::AbstractNode, Hash[GraphQL::Language::Nodes::AbstractNode, Integer]]
|
|
332
|
+
def child_positions_by_parent
|
|
333
|
+
@child_positions
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
#: (GraphQL::StaticValidation::Error error, ?path: Array[String | Integer]?) -> void
|
|
265
337
|
def add_error(error, path: nil)
|
|
266
338
|
if @context.too_many_errors?
|
|
267
339
|
throw :too_many_validation_errors
|
|
@@ -148,6 +148,8 @@ module GraphQL
|
|
|
148
148
|
# with that name has a dependency, we record it.
|
|
149
149
|
independent_fragment_nodes = @defdep_fragment_definitions.values.flatten - @defdep_immediate_dependencies.keys
|
|
150
150
|
visited_fragment_names = Set.new
|
|
151
|
+
# Fragments that share dependencies would otherwise copy them once per path, doubling with each layer.
|
|
152
|
+
recorded_dependencies = Hash.new { |h, k| h[k] = {}.compare_by_identity }.compare_by_identity
|
|
151
153
|
while fragment_node = independent_fragment_nodes.pop
|
|
152
154
|
if visited_fragment_names.add?(fragment_node.name)
|
|
153
155
|
# this is a new fragment name
|
|
@@ -170,8 +172,18 @@ module GraphQL
|
|
|
170
172
|
else
|
|
171
173
|
fragment_usages.each do |definition_node|
|
|
172
174
|
# Register the dependency AND second-order dependencies
|
|
173
|
-
dependency_map[definition_node]
|
|
174
|
-
|
|
175
|
+
definition_dependencies = dependency_map[definition_node]
|
|
176
|
+
recorded = recorded_dependencies[definition_node]
|
|
177
|
+
if !recorded.key?(fragment_node)
|
|
178
|
+
recorded[fragment_node] = true
|
|
179
|
+
definition_dependencies << fragment_node
|
|
180
|
+
end
|
|
181
|
+
dependency_map[fragment_node].each do |transitive_node|
|
|
182
|
+
if !recorded.key?(transitive_node)
|
|
183
|
+
recorded[transitive_node] = true
|
|
184
|
+
definition_dependencies << transitive_node
|
|
185
|
+
end
|
|
186
|
+
end
|
|
175
187
|
# Since we've registered it, remove it from our to-do list
|
|
176
188
|
deps = @defdep_immediate_dependencies[definition_node]
|
|
177
189
|
# Can't find a way to _just_ delete from `deps` and return the deleted entries
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# typed:
|
|
2
|
+
# typed: strict
|
|
3
3
|
module GraphQL
|
|
4
4
|
module StaticValidation
|
|
5
5
|
#--
|
|
@@ -7,16 +7,19 @@ module GraphQL
|
|
|
7
7
|
module ArgumentNamesAreUnique
|
|
8
8
|
include GraphQL::StaticValidation::Error::ErrorHelper
|
|
9
9
|
|
|
10
|
+
#: (GraphQL::Language::Nodes::Field node, GraphQL::Language::Nodes::AbstractNode? parent) -> void
|
|
10
11
|
def on_field(node, parent)
|
|
11
12
|
validate_arguments(node)
|
|
12
13
|
super
|
|
13
14
|
end
|
|
14
15
|
|
|
16
|
+
#: (GraphQL::Language::Nodes::Directive node, GraphQL::Language::Nodes::AbstractNode? parent) -> void
|
|
15
17
|
def on_directive(node, parent)
|
|
16
18
|
validate_arguments(node)
|
|
17
19
|
super
|
|
18
20
|
end
|
|
19
21
|
|
|
22
|
+
#: (GraphQL::Language::Nodes::Field | GraphQL::Language::Nodes::Directive node) -> void
|
|
20
23
|
def validate_arguments(node)
|
|
21
24
|
argument_defns = node.arguments
|
|
22
25
|
if argument_defns.size > 1
|
|
@@ -37,6 +37,8 @@ module GraphQL
|
|
|
37
37
|
|
|
38
38
|
def validate_location(ast_directive, ast_parent, directives)
|
|
39
39
|
directive_defn = directives[ast_directive.name]
|
|
40
|
+
# Undefined directives are reported by DirectivesAreDefined
|
|
41
|
+
return if directive_defn.nil?
|
|
40
42
|
case ast_parent
|
|
41
43
|
when Nodes::OperationDefinition
|
|
42
44
|
required_location = GraphQL::Schema::Directive.const_get(ast_parent.operation_type.upcase)
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# typed:
|
|
2
|
+
# typed: strict
|
|
3
3
|
module GraphQL
|
|
4
4
|
module StaticValidation
|
|
5
5
|
#--
|
|
6
6
|
# @requires_ancestor: GraphQL::StaticValidation::BaseVisitor
|
|
7
|
+
# @requires_ancestor: GraphQL::StaticValidation::BaseVisitor::ContextMethods
|
|
7
8
|
module FieldsAreDefinedOnType
|
|
9
|
+
#: (GraphQL::Language::Nodes::Field node, GraphQL::Language::Nodes::AbstractNode parent) -> void
|
|
8
10
|
def on_field(node, parent)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
# Fields are only visited inside a known type (other rules stop the visit otherwise)
|
|
12
|
+
parent_type = parent_type_definition #: as !nil
|
|
13
|
+
field = context.types.field(parent_type, node.name)
|
|
11
14
|
|
|
12
15
|
if field.nil?
|
|
13
16
|
if parent_type.kind.union?
|
|
@@ -17,7 +20,7 @@ module GraphQL
|
|
|
17
20
|
node_name: parent_type.graphql_name
|
|
18
21
|
))
|
|
19
22
|
else
|
|
20
|
-
suggestion = if
|
|
23
|
+
suggestion = if schema.did_you_mean
|
|
21
24
|
context.did_you_mean_suggestion(node.name, possible_fields(context, parent_type))
|
|
22
25
|
end
|
|
23
26
|
message = "Field '#{node.name}' doesn't exist on type '#{parent_type.graphql_name}'#{suggestion}"
|
|
@@ -35,6 +38,7 @@ module GraphQL
|
|
|
35
38
|
|
|
36
39
|
private
|
|
37
40
|
|
|
41
|
+
#: (GraphQL::StaticValidation::ValidationContext context, GraphQL::Schema::Member::type_definition parent_type) -> Array[String]
|
|
38
42
|
def possible_fields(context, parent_type)
|
|
39
43
|
return EmptyObjects::EMPTY_ARRAY if parent_type.kind.leaf?
|
|
40
44
|
context.types.fields(parent_type).map(&:graphql_name)
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# typed:
|
|
2
|
+
# typed: strict
|
|
3
3
|
module GraphQL
|
|
4
4
|
module StaticValidation
|
|
5
5
|
#--
|
|
6
6
|
# @requires_ancestor: GraphQL::StaticValidation::BaseVisitor
|
|
7
7
|
module FragmentsAreFinite
|
|
8
|
+
#: (GraphQL::Language::Nodes::Document _n, GraphQL::Language::Nodes::AbstractNode? _p) -> void
|
|
8
9
|
def on_document(_n, _p)
|
|
9
10
|
super
|
|
10
11
|
dependency_map = context.dependencies
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# typed:
|
|
2
|
+
# typed: strict
|
|
3
3
|
module GraphQL
|
|
4
4
|
module StaticValidation
|
|
5
5
|
#--
|
|
6
6
|
# @requires_ancestor: GraphQL::StaticValidation::BaseVisitor
|
|
7
7
|
module FragmentsAreNamed
|
|
8
|
+
#: (GraphQL::Language::Nodes::FragmentDefinition node, GraphQL::Language::Nodes::AbstractNode? _parent) -> void
|
|
8
9
|
def on_fragment_definition(node, _parent)
|
|
9
10
|
if node.name.nil?
|
|
10
11
|
add_error(GraphQL::StaticValidation::FragmentsAreNamedError.new(
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# typed:
|
|
2
|
+
# typed: strict
|
|
3
3
|
module GraphQL
|
|
4
4
|
module StaticValidation
|
|
5
5
|
class FragmentsAreNamedError < StaticValidation::Error
|
|
6
6
|
|
|
7
|
+
#: (String message, ?path: Array[String | Integer]?, ?nodes: GraphQL::Language::Nodes::AbstractNode | Array[GraphQL::Language::Nodes::AbstractNode]) -> void
|
|
7
8
|
def initialize(message, path: nil, nodes: [])
|
|
8
9
|
super(message, path: path, nodes: nodes)
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
# A hash representation of this Message
|
|
13
|
+
#: -> Hash[String, untyped]
|
|
12
14
|
def to_h
|
|
13
15
|
extensions = {
|
|
14
16
|
"code" => code,
|
|
@@ -19,6 +21,7 @@ module GraphQL
|
|
|
19
21
|
})
|
|
20
22
|
end
|
|
21
23
|
|
|
24
|
+
#: -> String
|
|
22
25
|
def code
|
|
23
26
|
"anonymousFragment"
|
|
24
27
|
end
|
|
@@ -1,28 +1,31 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# typed:
|
|
2
|
+
# typed: strict
|
|
3
3
|
module GraphQL
|
|
4
4
|
module StaticValidation
|
|
5
5
|
#--
|
|
6
6
|
# @requires_ancestor: GraphQL::StaticValidation::BaseVisitor
|
|
7
7
|
module FragmentsAreOnCompositeTypes
|
|
8
|
+
#: (GraphQL::Language::Nodes::FragmentDefinition node, GraphQL::Language::Nodes::AbstractNode parent) -> void
|
|
8
9
|
def on_fragment_definition(node, parent)
|
|
9
10
|
validate_type_is_composite(node) && super
|
|
10
11
|
end
|
|
11
12
|
|
|
13
|
+
#: (GraphQL::Language::Nodes::InlineFragment node, GraphQL::Language::Nodes::AbstractNode parent) -> void
|
|
12
14
|
def on_inline_fragment(node, parent)
|
|
13
15
|
validate_type_is_composite(node) && super
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
private
|
|
17
19
|
|
|
20
|
+
#: (GraphQL::Language::Nodes::FragmentDefinition | GraphQL::Language::Nodes::InlineFragment node) -> bool
|
|
18
21
|
def validate_type_is_composite(node)
|
|
19
|
-
node_type = node.type
|
|
22
|
+
node_type = node.type #: GraphQL::Language::Nodes::TypeName?
|
|
20
23
|
if node_type.nil?
|
|
21
24
|
# Inline fragment on the same type
|
|
22
25
|
true
|
|
23
26
|
else
|
|
24
27
|
type_name = node_type.to_query_string
|
|
25
|
-
type_def =
|
|
28
|
+
type_def = types.type(type_name)
|
|
26
29
|
if type_def.nil? || !type_def.kind.composite?
|
|
27
30
|
add_error(GraphQL::StaticValidation::FragmentsAreOnCompositeTypesError.new(
|
|
28
31
|
"Invalid fragment on type #{type_name} (must be Union, Interface or Object)",
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# typed:
|
|
2
|
+
# typed: strict
|
|
3
3
|
module GraphQL
|
|
4
4
|
module StaticValidation
|
|
5
5
|
#--
|
|
6
6
|
# @requires_ancestor: GraphQL::StaticValidation::BaseVisitor
|
|
7
7
|
module FragmentsAreUsed
|
|
8
|
+
#: (GraphQL::Language::Nodes::Document node, GraphQL::Language::Nodes::AbstractNode? parent) -> void
|
|
8
9
|
def on_document(node, parent)
|
|
9
10
|
super
|
|
10
11
|
dependency_map = context.dependencies
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# typed:
|
|
2
|
+
# typed: strict
|
|
3
3
|
module GraphQL
|
|
4
4
|
module StaticValidation
|
|
5
5
|
#--
|
|
6
6
|
# @requires_ancestor: GraphQL::StaticValidation::BaseVisitor
|
|
7
7
|
module InputObjectNamesAreUnique
|
|
8
|
+
#: (GraphQL::Language::Nodes::InputObject node, GraphQL::Language::Nodes::AbstractNode? parent) -> void
|
|
8
9
|
def on_input_object(node, parent)
|
|
9
10
|
validate_input_fields(node)
|
|
10
11
|
super
|
|
@@ -12,6 +13,7 @@ module GraphQL
|
|
|
12
13
|
|
|
13
14
|
private
|
|
14
15
|
|
|
16
|
+
#: (GraphQL::Language::Nodes::InputObject node) -> void
|
|
15
17
|
def validate_input_fields(node)
|
|
16
18
|
input_field_defns = node.arguments
|
|
17
19
|
input_fields_by_name = Hash.new { |h, k| h[k] = [] }
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# typed:
|
|
2
|
+
# typed: strict
|
|
3
3
|
module GraphQL
|
|
4
4
|
module StaticValidation
|
|
5
5
|
#--
|
|
6
6
|
# @requires_ancestor: GraphQL::StaticValidation::BaseVisitor
|
|
7
7
|
module MutationRootExists
|
|
8
|
+
#: (GraphQL::Language::Nodes::OperationDefinition node, GraphQL::Language::Nodes::AbstractNode? _parent) -> void
|
|
8
9
|
def on_operation_definition(node, _parent)
|
|
9
|
-
if node.operation_type == 'mutation' && context.
|
|
10
|
+
if node.operation_type == 'mutation' && context.types.mutation_root.nil?
|
|
10
11
|
add_error(GraphQL::StaticValidation::MutationRootExistsError.new(
|
|
11
12
|
'Schema is not configured for mutations',
|
|
12
13
|
nodes: node
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# typed:
|
|
2
|
+
# typed: strict
|
|
3
3
|
module GraphQL
|
|
4
4
|
module StaticValidation
|
|
5
5
|
class MutationRootExistsError < StaticValidation::Error
|
|
6
6
|
|
|
7
|
+
#: (String message, ?path: Array[String | Integer]?, ?nodes: GraphQL::Language::Nodes::AbstractNode | Array[GraphQL::Language::Nodes::AbstractNode]) -> void
|
|
7
8
|
def initialize(message, path: nil, nodes: [])
|
|
8
9
|
super(message, path: path, nodes: nodes)
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
# A hash representation of this Message
|
|
13
|
+
#: -> Hash[String, untyped]
|
|
12
14
|
def to_h
|
|
13
15
|
extensions = {
|
|
14
16
|
"code" => code,
|
|
@@ -19,6 +21,7 @@ module GraphQL
|
|
|
19
21
|
})
|
|
20
22
|
end
|
|
21
23
|
|
|
24
|
+
#: -> String
|
|
22
25
|
def code
|
|
23
26
|
"missingMutationConfiguration"
|
|
24
27
|
end
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# typed:
|
|
2
|
+
# typed: strict
|
|
3
3
|
module GraphQL
|
|
4
4
|
module StaticValidation
|
|
5
5
|
class NoDefinitionsArePresentError < StaticValidation::Error
|
|
6
|
+
#: (String message, ?path: Array[String | Integer]?, ?nodes: GraphQL::Language::Nodes::AbstractNode | Array[GraphQL::Language::Nodes::AbstractNode]) -> void
|
|
6
7
|
def initialize(message, path: nil, nodes: [])
|
|
7
8
|
super(message, path: path, nodes: nodes)
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
# A hash representation of this Message
|
|
12
|
+
#: -> Hash[String, untyped]
|
|
11
13
|
def to_h
|
|
12
14
|
extensions = {
|
|
13
15
|
"code" => code,
|
|
@@ -18,6 +20,7 @@ module GraphQL
|
|
|
18
20
|
})
|
|
19
21
|
end
|
|
20
22
|
|
|
23
|
+
#: -> String
|
|
21
24
|
def code
|
|
22
25
|
"queryContainsSchemaDefinitions"
|
|
23
26
|
end
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# typed:
|
|
2
|
+
# typed: strict
|
|
3
3
|
module GraphQL
|
|
4
4
|
module StaticValidation
|
|
5
5
|
class NotSingleSubscriptionError < StaticValidation::Error
|
|
6
|
+
#: (String message, ?path: Array[String | Integer]?, ?nodes: GraphQL::Language::Nodes::AbstractNode | Array[GraphQL::Language::Nodes::AbstractNode]) -> void
|
|
6
7
|
def initialize(message, path: nil, nodes: [])
|
|
7
8
|
super(message, path: path, nodes: nodes)
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
# A hash representation of this Message
|
|
12
|
+
#: -> Hash[String, untyped]
|
|
11
13
|
def to_h
|
|
12
14
|
extensions = {
|
|
13
15
|
"code" => code,
|
|
@@ -18,6 +20,7 @@ module GraphQL
|
|
|
18
20
|
})
|
|
19
21
|
end
|
|
20
22
|
|
|
23
|
+
#: -> String
|
|
21
24
|
def code
|
|
22
25
|
"notSingleSubscription"
|
|
23
26
|
end
|