graphql 2.0.16 → 2.0.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql/analysis/ast/visitor.rb +42 -35
- data/lib/graphql/execution/interpreter/runtime.rb +14 -4
- data/lib/graphql/execution/interpreter.rb +10 -0
- data/lib/graphql/execution/lazy.rb +4 -8
- data/lib/graphql/introspection/directive_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +2 -2
- data/lib/graphql/introspection/type_type.rb +5 -5
- data/lib/graphql/language/nodes.rb +39 -31
- data/lib/graphql/language/visitor.rb +191 -83
- data/lib/graphql/schema/argument.rb +0 -4
- data/lib/graphql/schema/directive.rb +12 -2
- data/lib/graphql/schema/enum.rb +24 -17
- data/lib/graphql/schema/enum_value.rb +5 -3
- data/lib/graphql/schema/field.rb +22 -26
- data/lib/graphql/schema/interface.rb +0 -10
- data/lib/graphql/schema/late_bound_type.rb +2 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +15 -14
- data/lib/graphql/schema/member/has_arguments.rb +104 -57
- data/lib/graphql/schema/member/has_fields.rb +8 -1
- data/lib/graphql/schema/member/has_interfaces.rb +49 -8
- data/lib/graphql/schema/member/has_validators.rb +31 -5
- data/lib/graphql/schema/member/type_system_helpers.rb +17 -0
- data/lib/graphql/schema/warden.rb +18 -3
- data/lib/graphql/schema.rb +3 -19
- data/lib/graphql/static_validation/literal_validator.rb +15 -1
- data/lib/graphql/subscriptions/event.rb +2 -7
- data/lib/graphql/types/relay/connection_behaviors.rb +0 -4
- data/lib/graphql/types/relay/edge_behaviors.rb +0 -4
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f95232ddde41ec605d304a572989213869296dc3818f15844d86a13f5cfa8c4
|
4
|
+
data.tar.gz: b4850a0d39ccca8d81f0d487e0311b51fba6f2bfe1151461ce39c732743799b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a15e0e17fd99b2c24c0a66f40f54c9909fc56c70d97fba2833bcb4934af65c06c5834b847386caa92100c4bb329c8fb27b799f5628f29cf89e6ff04946c013c
|
7
|
+
data.tar.gz: 92eac476af42ec7222b371ebd87b81b78873a3240fe83ac994b0c603b990f84a082b05dead69d59dff48a58c5762d1d26028e13f57ec55481f86e4b67c92f70b
|
@@ -65,14 +65,41 @@ module GraphQL
|
|
65
65
|
end
|
66
66
|
|
67
67
|
# Visitor Hooks
|
68
|
+
[
|
69
|
+
:operation_definition, :fragment_definition,
|
70
|
+
:inline_fragment, :field, :directive, :argument, :fragment_spread
|
71
|
+
].each do |node_type|
|
72
|
+
module_eval <<-RUBY, __FILE__, __LINE__
|
73
|
+
def call_on_enter_#{node_type}(node, parent)
|
74
|
+
@analyzers.each do |a|
|
75
|
+
begin
|
76
|
+
a.on_enter_#{node_type}(node, parent, self)
|
77
|
+
rescue AnalysisError => err
|
78
|
+
@rescued_errors << err
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def call_on_leave_#{node_type}(node, parent)
|
84
|
+
@analyzers.each do |a|
|
85
|
+
begin
|
86
|
+
a.on_leave_#{node_type}(node, parent, self)
|
87
|
+
rescue AnalysisError => err
|
88
|
+
@rescued_errors << err
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
RUBY
|
94
|
+
end
|
68
95
|
|
69
96
|
def on_operation_definition(node, parent)
|
70
97
|
object_type = @schema.root_type_for_operation(node.operation_type)
|
71
98
|
@object_types.push(object_type)
|
72
99
|
@path.push("#{node.operation_type}#{node.name ? " #{node.name}" : ""}")
|
73
|
-
|
100
|
+
call_on_enter_operation_definition(node, parent)
|
74
101
|
super
|
75
|
-
|
102
|
+
call_on_leave_operation_definition(node, parent)
|
76
103
|
@object_types.pop
|
77
104
|
@path.pop
|
78
105
|
end
|
@@ -81,19 +108,19 @@ module GraphQL
|
|
81
108
|
on_fragment_with_type(node) do
|
82
109
|
@path.push("fragment #{node.name}")
|
83
110
|
@in_fragment_def = false
|
84
|
-
|
111
|
+
call_on_enter_fragment_definition(node, parent)
|
85
112
|
super
|
86
113
|
@in_fragment_def = false
|
87
|
-
|
114
|
+
call_on_leave_fragment_definition(node, parent)
|
88
115
|
end
|
89
116
|
end
|
90
117
|
|
91
118
|
def on_inline_fragment(node, parent)
|
92
119
|
on_fragment_with_type(node) do
|
93
120
|
@path.push("...#{node.type ? " on #{node.type.name}" : ""}")
|
94
|
-
|
121
|
+
call_on_enter_inline_fragment(node, parent)
|
95
122
|
super
|
96
|
-
|
123
|
+
call_on_leave_inline_fragment(node, parent)
|
97
124
|
end
|
98
125
|
end
|
99
126
|
|
@@ -114,12 +141,10 @@ module GraphQL
|
|
114
141
|
@skipping = @skip_stack.last || skip?(node)
|
115
142
|
@skip_stack << @skipping
|
116
143
|
|
117
|
-
|
144
|
+
call_on_enter_field(node, parent)
|
118
145
|
super
|
119
|
-
|
120
146
|
@skipping = @skip_stack.pop
|
121
|
-
|
122
|
-
call_analyzers(:on_leave_field, node, parent)
|
147
|
+
call_on_leave_field(node, parent)
|
123
148
|
@response_path.pop
|
124
149
|
@field_definitions.pop
|
125
150
|
@object_types.pop
|
@@ -129,9 +154,9 @@ module GraphQL
|
|
129
154
|
def on_directive(node, parent)
|
130
155
|
directive_defn = @schema.directives[node.name]
|
131
156
|
@directive_definitions.push(directive_defn)
|
132
|
-
|
157
|
+
call_on_enter_directive(node, parent)
|
133
158
|
super
|
134
|
-
|
159
|
+
call_on_leave_directive(node, parent)
|
135
160
|
@directive_definitions.pop
|
136
161
|
end
|
137
162
|
|
@@ -153,29 +178,23 @@ module GraphQL
|
|
153
178
|
|
154
179
|
@argument_definitions.push(argument_defn)
|
155
180
|
@path.push(node.name)
|
156
|
-
|
181
|
+
call_on_enter_argument(node, parent)
|
157
182
|
super
|
158
|
-
|
183
|
+
call_on_leave_argument(node, parent)
|
159
184
|
@argument_definitions.pop
|
160
185
|
@path.pop
|
161
186
|
end
|
162
187
|
|
163
188
|
def on_fragment_spread(node, parent)
|
164
189
|
@path.push("... #{node.name}")
|
165
|
-
|
190
|
+
call_on_enter_fragment_spread(node, parent)
|
166
191
|
enter_fragment_spread_inline(node)
|
167
192
|
super
|
168
193
|
leave_fragment_spread_inline(node)
|
169
|
-
|
194
|
+
call_on_leave_fragment_spread(node, parent)
|
170
195
|
@path.pop
|
171
196
|
end
|
172
197
|
|
173
|
-
def on_abstract_node(node, parent)
|
174
|
-
call_analyzers(:on_enter_abstract_node, node, parent)
|
175
|
-
super
|
176
|
-
call_analyzers(:on_leave_abstract_node, node, parent)
|
177
|
-
end
|
178
|
-
|
179
198
|
# @return [GraphQL::BaseType] The current object type
|
180
199
|
def type_definition
|
181
200
|
@object_types.last
|
@@ -226,9 +245,7 @@ module GraphQL
|
|
226
245
|
|
227
246
|
object_types << object_type
|
228
247
|
|
229
|
-
fragment_def
|
230
|
-
visit_node(selection, fragment_def)
|
231
|
-
end
|
248
|
+
on_fragment_definition_children(fragment_def)
|
232
249
|
end
|
233
250
|
|
234
251
|
# Visit a fragment spread inline instead of visiting the definition
|
@@ -242,16 +259,6 @@ module GraphQL
|
|
242
259
|
dir.any? && !GraphQL::Execution::DirectiveChecks.include?(dir, query)
|
243
260
|
end
|
244
261
|
|
245
|
-
def call_analyzers(method, node, parent)
|
246
|
-
@analyzers.each do |analyzer|
|
247
|
-
begin
|
248
|
-
analyzer.public_send(method, node, parent, self)
|
249
|
-
rescue AnalysisError => err
|
250
|
-
@rescued_errors << err
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
262
|
def on_fragment_with_type(node)
|
256
263
|
object_type = if node.type
|
257
264
|
@query.warden.get_type(node.type.name)
|
@@ -409,6 +409,7 @@ module GraphQL
|
|
409
409
|
raise "Invariant: no field for #{owner_type}.#{field_name}"
|
410
410
|
end
|
411
411
|
end
|
412
|
+
|
412
413
|
return_type = field_defn.type
|
413
414
|
|
414
415
|
next_path = path + [result_name]
|
@@ -431,17 +432,16 @@ module GraphQL
|
|
431
432
|
total_args_count = field_defn.arguments(context).size
|
432
433
|
if total_args_count == 0
|
433
434
|
resolved_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
|
434
|
-
evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selections_result, parent_object)
|
435
|
+
evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selections_result, parent_object, return_type)
|
435
436
|
else
|
436
437
|
# TODO remove all arguments(...) usages?
|
437
438
|
@query.arguments_cache.dataload_for(ast_node, field_defn, object) do |resolved_arguments|
|
438
|
-
evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selections_result, parent_object)
|
439
|
+
evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selections_result, parent_object, return_type)
|
439
440
|
end
|
440
441
|
end
|
441
442
|
end
|
442
443
|
|
443
|
-
def evaluate_selection_with_args(arguments, field_defn, next_path, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selection_result, parent_object) # rubocop:disable Metrics/ParameterLists
|
444
|
-
return_type = field_defn.type
|
444
|
+
def evaluate_selection_with_args(arguments, field_defn, next_path, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selection_result, parent_object, return_type) # rubocop:disable Metrics/ParameterLists
|
445
445
|
after_lazy(arguments, owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, owner_object: object, arguments: arguments, result_name: result_name, result: selection_result) do |resolved_arguments|
|
446
446
|
if resolved_arguments.is_a?(GraphQL::ExecutionError) || resolved_arguments.is_a?(GraphQL::UnauthorizedError)
|
447
447
|
continue_value(next_path, resolved_arguments, owner_type, field_defn, return_type.non_null?, ast_node, result_name, selection_result)
|
@@ -615,6 +615,16 @@ module GraphQL
|
|
615
615
|
end
|
616
616
|
end
|
617
617
|
HALT
|
618
|
+
elsif value.is_a?(GraphQL::UnauthorizedFieldError)
|
619
|
+
value.field ||= field
|
620
|
+
# this hook might raise & crash, or it might return
|
621
|
+
# a replacement value
|
622
|
+
next_value = begin
|
623
|
+
schema.unauthorized_field(value)
|
624
|
+
rescue GraphQL::ExecutionError => err
|
625
|
+
err
|
626
|
+
end
|
627
|
+
continue_value(path, next_value, parent_type, field, is_non_null, ast_node, result_name, selection_result)
|
618
628
|
elsif value.is_a?(GraphQL::UnauthorizedError)
|
619
629
|
# this hook might raise & crash, or it might return
|
620
630
|
# a replacement value
|
@@ -146,6 +146,16 @@ module GraphQL
|
|
146
146
|
# Assign values here so that the query's `@executed` becomes true
|
147
147
|
queries.map { |q| q.result_values ||= {} }
|
148
148
|
raise
|
149
|
+
ensure
|
150
|
+
queries.map { |query|
|
151
|
+
runtime = query.context.namespace(:interpreter_runtime)[:runtime]
|
152
|
+
if runtime
|
153
|
+
runtime.delete_interpreter_context(:current_path)
|
154
|
+
runtime.delete_interpreter_context(:current_field)
|
155
|
+
runtime.delete_interpreter_context(:current_object)
|
156
|
+
runtime.delete_interpreter_context(:current_arguments)
|
157
|
+
end
|
158
|
+
}
|
149
159
|
end
|
150
160
|
end
|
151
161
|
end
|
@@ -29,15 +29,11 @@ module GraphQL
|
|
29
29
|
def value
|
30
30
|
if !@resolved
|
31
31
|
@resolved = true
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
v = v.value
|
36
|
-
end
|
37
|
-
v
|
38
|
-
rescue GraphQL::ExecutionError => err
|
39
|
-
err
|
32
|
+
v = @get_value_func.call
|
33
|
+
if v.is_a?(Lazy)
|
34
|
+
v = v.value
|
40
35
|
end
|
36
|
+
@value = v
|
41
37
|
end
|
42
38
|
|
43
39
|
# `SKIP` was made into a subclass of `GraphQL::Error` to improve runtime performance
|
@@ -11,8 +11,8 @@ module GraphQL
|
|
11
11
|
"to the executor."
|
12
12
|
field :name, String, null: false, method: :graphql_name
|
13
13
|
field :description, String
|
14
|
-
field :locations, [GraphQL::Schema::LateBoundType.new("__DirectiveLocation")], null: false
|
15
|
-
field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
|
14
|
+
field :locations, [GraphQL::Schema::LateBoundType.new("__DirectiveLocation")], null: false, scope: false
|
15
|
+
field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false, scope: false do
|
16
16
|
argument :include_deprecated, Boolean, required: false, default_value: false
|
17
17
|
end
|
18
18
|
field :on_operation, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_operation?
|
@@ -7,7 +7,7 @@ module GraphQL
|
|
7
7
|
"a name, potentially a list of arguments, and a return type."
|
8
8
|
field :name, String, null: false
|
9
9
|
field :description, String
|
10
|
-
field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
|
10
|
+
field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false, scope: false do
|
11
11
|
argument :include_deprecated, Boolean, required: false, default_value: false
|
12
12
|
end
|
13
13
|
field :type, GraphQL::Schema::LateBoundType.new("__Type"), null: false
|
@@ -8,11 +8,11 @@ module GraphQL
|
|
8
8
|
"available types and directives on the server, as well as the entry points for "\
|
9
9
|
"query, mutation, and subscription operations."
|
10
10
|
|
11
|
-
field :types, [GraphQL::Schema::LateBoundType.new("__Type")], "A list of all types supported by this server.", null: false
|
11
|
+
field :types, [GraphQL::Schema::LateBoundType.new("__Type")], "A list of all types supported by this server.", null: false, scope: false
|
12
12
|
field :query_type, GraphQL::Schema::LateBoundType.new("__Type"), "The type that query operations will be rooted at.", null: false
|
13
13
|
field :mutation_type, GraphQL::Schema::LateBoundType.new("__Type"), "If this server supports mutation, the type that mutation operations will be rooted at."
|
14
14
|
field :subscription_type, GraphQL::Schema::LateBoundType.new("__Type"), "If this server support subscription, the type that subscription operations will be rooted at."
|
15
|
-
field :directives, [GraphQL::Schema::LateBoundType.new("__Directive")], "A list of all directives supported by this server.", null: false
|
15
|
+
field :directives, [GraphQL::Schema::LateBoundType.new("__Directive")], "A list of all directives supported by this server.", null: false, scope: false
|
16
16
|
field :description, String, resolver_method: :schema_description
|
17
17
|
|
18
18
|
def schema_description
|
@@ -14,15 +14,15 @@ module GraphQL
|
|
14
14
|
field :kind, GraphQL::Schema::LateBoundType.new("__TypeKind"), null: false
|
15
15
|
field :name, String, method: :graphql_name
|
16
16
|
field :description, String
|
17
|
-
field :fields, [GraphQL::Schema::LateBoundType.new("__Field")] do
|
17
|
+
field :fields, [GraphQL::Schema::LateBoundType.new("__Field")], scope: false do
|
18
18
|
argument :include_deprecated, Boolean, required: false, default_value: false
|
19
19
|
end
|
20
|
-
field :interfaces, [GraphQL::Schema::LateBoundType.new("__Type")]
|
21
|
-
field :possible_types, [GraphQL::Schema::LateBoundType.new("__Type")]
|
22
|
-
field :enum_values, [GraphQL::Schema::LateBoundType.new("__EnumValue")] do
|
20
|
+
field :interfaces, [GraphQL::Schema::LateBoundType.new("__Type")], scope: false
|
21
|
+
field :possible_types, [GraphQL::Schema::LateBoundType.new("__Type")], scope: false
|
22
|
+
field :enum_values, [GraphQL::Schema::LateBoundType.new("__EnumValue")], scope: false do
|
23
23
|
argument :include_deprecated, Boolean, required: false, default_value: false
|
24
24
|
end
|
25
|
-
field :input_fields, [GraphQL::Schema::LateBoundType.new("__InputValue")] do
|
25
|
+
field :input_fields, [GraphQL::Schema::LateBoundType.new("__InputValue")], scope: false do
|
26
26
|
argument :include_deprecated, Boolean, required: false, default_value: false
|
27
27
|
end
|
28
28
|
field :of_type, GraphQL::Schema::LateBoundType.new("__Type")
|
@@ -141,18 +141,26 @@ module GraphQL
|
|
141
141
|
.gsub(/([a-z])([A-Z])/,'\1_\2') # insert underscores
|
142
142
|
.downcase # remove caps
|
143
143
|
|
144
|
-
child_class.module_eval <<-RUBY
|
144
|
+
child_class.module_eval <<-RUBY, __FILE__, __LINE__
|
145
145
|
def visit_method
|
146
146
|
:on_#{name_underscored}
|
147
147
|
end
|
148
148
|
|
149
149
|
class << self
|
150
150
|
attr_accessor :children_method_name
|
151
|
+
|
152
|
+
def visit_method
|
153
|
+
:on_#{name_underscored}
|
154
|
+
end
|
151
155
|
end
|
152
156
|
self.children_method_name = :#{name_underscored}s
|
153
157
|
RUBY
|
154
158
|
end
|
155
159
|
|
160
|
+
def children_of_type
|
161
|
+
@children_methods
|
162
|
+
end
|
163
|
+
|
156
164
|
private
|
157
165
|
|
158
166
|
# Name accessors which return lists of nodes,
|
@@ -300,7 +308,7 @@ module GraphQL
|
|
300
308
|
# @return [String] the key for this argument
|
301
309
|
|
302
310
|
# @!attribute value
|
303
|
-
# @return [String, Float, Integer, Boolean, Array, InputObject] The value passed for this key
|
311
|
+
# @return [String, Float, Integer, Boolean, Array, InputObject, VariableIdentifier] The value passed for this key
|
304
312
|
|
305
313
|
def children
|
306
314
|
@children ||= Array(value).flatten.select { |v| v.is_a?(AbstractNode) }
|
@@ -325,35 +333,6 @@ module GraphQL
|
|
325
333
|
)
|
326
334
|
end
|
327
335
|
|
328
|
-
# This is the AST root for normal queries
|
329
|
-
#
|
330
|
-
# @example Deriving a document by parsing a string
|
331
|
-
# document = GraphQL.parse(query_string)
|
332
|
-
#
|
333
|
-
# @example Creating a string from a document
|
334
|
-
# document.to_query_string
|
335
|
-
# # { ... }
|
336
|
-
#
|
337
|
-
# @example Creating a custom string from a document
|
338
|
-
# class VariableScrubber < GraphQL::Language::Printer
|
339
|
-
# def print_argument(arg)
|
340
|
-
# "#{arg.name}: <HIDDEN>"
|
341
|
-
# end
|
342
|
-
# end
|
343
|
-
#
|
344
|
-
# document.to_query_string(printer: VariableScrubber.new)
|
345
|
-
#
|
346
|
-
class Document < AbstractNode
|
347
|
-
scalar_methods false
|
348
|
-
children_methods(definitions: nil)
|
349
|
-
# @!attribute definitions
|
350
|
-
# @return [Array<OperationDefinition, FragmentDefinition>] top-level GraphQL units: operations or fragments
|
351
|
-
|
352
|
-
def slice_definition(name)
|
353
|
-
GraphQL::Language::DefinitionSlice.slice(self, name)
|
354
|
-
end
|
355
|
-
end
|
356
|
-
|
357
336
|
# An enum value. The string is available as {#name}.
|
358
337
|
class Enum < NameOnlyNode
|
359
338
|
end
|
@@ -526,6 +505,35 @@ module GraphQL
|
|
526
505
|
self.children_method_name = :definitions
|
527
506
|
end
|
528
507
|
|
508
|
+
# This is the AST root for normal queries
|
509
|
+
#
|
510
|
+
# @example Deriving a document by parsing a string
|
511
|
+
# document = GraphQL.parse(query_string)
|
512
|
+
#
|
513
|
+
# @example Creating a string from a document
|
514
|
+
# document.to_query_string
|
515
|
+
# # { ... }
|
516
|
+
#
|
517
|
+
# @example Creating a custom string from a document
|
518
|
+
# class VariableScrubber < GraphQL::Language::Printer
|
519
|
+
# def print_argument(arg)
|
520
|
+
# "#{arg.name}: <HIDDEN>"
|
521
|
+
# end
|
522
|
+
# end
|
523
|
+
#
|
524
|
+
# document.to_query_string(printer: VariableScrubber.new)
|
525
|
+
#
|
526
|
+
class Document < AbstractNode
|
527
|
+
scalar_methods false
|
528
|
+
children_methods(definitions: nil)
|
529
|
+
# @!attribute definitions
|
530
|
+
# @return [Array<OperationDefinition, FragmentDefinition>] top-level GraphQL units: operations or fragments
|
531
|
+
|
532
|
+
def slice_definition(name)
|
533
|
+
GraphQL::Language::DefinitionSlice.slice(self, name)
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
529
537
|
# A type name, used for variable definitions
|
530
538
|
class TypeName < NameOnlyNode
|
531
539
|
end
|