graphql 1.11.2 → 1.11.7
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.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/generators/graphql/core.rb +8 -0
- data/lib/generators/graphql/object_generator.rb +2 -0
- data/lib/generators/graphql/templates/base_argument.erb +2 -0
- data/lib/generators/graphql/templates/base_enum.erb +2 -0
- data/lib/generators/graphql/templates/base_field.erb +2 -0
- data/lib/generators/graphql/templates/base_input_object.erb +2 -0
- data/lib/generators/graphql/templates/base_interface.erb +2 -0
- data/lib/generators/graphql/templates/base_mutation.erb +2 -0
- data/lib/generators/graphql/templates/base_object.erb +2 -0
- data/lib/generators/graphql/templates/base_scalar.erb +2 -0
- data/lib/generators/graphql/templates/base_union.erb +2 -0
- data/lib/generators/graphql/templates/enum.erb +2 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
- data/lib/generators/graphql/templates/interface.erb +2 -0
- data/lib/generators/graphql/templates/loader.erb +2 -0
- data/lib/generators/graphql/templates/mutation.erb +2 -0
- data/lib/generators/graphql/templates/mutation_type.erb +2 -0
- data/lib/generators/graphql/templates/object.erb +2 -0
- data/lib/generators/graphql/templates/query_type.erb +2 -0
- data/lib/generators/graphql/templates/scalar.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +2 -0
- data/lib/generators/graphql/templates/union.erb +3 -1
- data/lib/graphql.rb +17 -0
- data/lib/graphql/argument.rb +3 -3
- data/lib/graphql/backtrace/tracer.rb +2 -1
- data/lib/graphql/define/assign_global_id_field.rb +2 -2
- data/lib/graphql/execution/interpreter.rb +10 -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 +94 -67
- data/lib/graphql/integer_decoding_error.rb +17 -0
- data/lib/graphql/introspection.rb +96 -0
- data/lib/graphql/introspection/field_type.rb +7 -3
- data/lib/graphql/introspection/input_value_type.rb +6 -0
- data/lib/graphql/introspection/introspection_query.rb +6 -92
- data/lib/graphql/introspection/type_type.rb +7 -3
- data/lib/graphql/invalid_null_error.rb +1 -1
- data/lib/graphql/language/block_string.rb +24 -5
- data/lib/graphql/language/lexer.rb +7 -3
- data/lib/graphql/language/lexer.rl +7 -3
- data/lib/graphql/language/nodes.rb +1 -1
- data/lib/graphql/language/parser.rb +107 -103
- data/lib/graphql/language/parser.y +4 -0
- data/lib/graphql/language/sanitized_printer.rb +59 -26
- data/lib/graphql/name_validator.rb +6 -7
- data/lib/graphql/pagination/connections.rb +11 -3
- data/lib/graphql/query.rb +6 -3
- data/lib/graphql/query/context.rb +34 -4
- data/lib/graphql/query/fingerprint.rb +2 -0
- data/lib/graphql/query/validation_pipeline.rb +4 -1
- data/lib/graphql/relay/array_connection.rb +2 -2
- data/lib/graphql/relay/range_add.rb +14 -5
- data/lib/graphql/schema.rb +49 -18
- data/lib/graphql/schema/argument.rb +56 -10
- data/lib/graphql/schema/build_from_definition.rb +67 -38
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +3 -1
- data/lib/graphql/schema/default_type_error.rb +2 -0
- data/lib/graphql/schema/directive/deprecated.rb +1 -1
- data/lib/graphql/schema/field.rb +32 -16
- data/lib/graphql/schema/field/connection_extension.rb +44 -37
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/input_object.rb +5 -3
- data/lib/graphql/schema/interface.rb +1 -1
- data/lib/graphql/schema/late_bound_type.rb +2 -2
- data/lib/graphql/schema/loader.rb +1 -0
- data/lib/graphql/schema/member/build_type.rb +14 -4
- data/lib/graphql/schema/member/has_arguments.rb +54 -53
- data/lib/graphql/schema/member/has_fields.rb +17 -7
- data/lib/graphql/schema/member/type_system_helpers.rb +2 -2
- data/lib/graphql/schema/mutation.rb +4 -0
- data/lib/graphql/schema/relay_classic_mutation.rb +4 -2
- data/lib/graphql/schema/resolver.rb +6 -0
- data/lib/graphql/schema/resolver/has_payload_type.rb +2 -1
- data/lib/graphql/schema/subscription.rb +2 -12
- data/lib/graphql/schema/timeout.rb +29 -15
- data/lib/graphql/schema/unique_within_type.rb +1 -2
- data/lib/graphql/schema/validation.rb +8 -0
- data/lib/graphql/schema/warden.rb +2 -3
- data/lib/graphql/static_validation.rb +1 -0
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +25 -17
- 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_timeout_error.rb +25 -0
- data/lib/graphql/static_validation/validator.rb +29 -7
- data/lib/graphql/subscriptions.rb +32 -22
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +21 -7
- data/lib/graphql/tracing/appoptics_tracing.rb +10 -2
- 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/iso_8601_date_time.rb +2 -1
- data/lib/graphql/types/relay/base_connection.rb +8 -6
- data/lib/graphql/types/relay/base_edge.rb +2 -1
- data/lib/graphql/types/string.rb +7 -1
- data/lib/graphql/unauthorized_error.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- 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: af3eaf2a85e27ab7a366e27a98d42e4372b93c7590c99fb6fb12fccb48ef37f9
|
4
|
+
data.tar.gz: 62be23c2f74539be298db79081b148db5d004325ef6ae6f1b007711659110a01
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f12858fd3c28da572082443e022ed2a5281bda7eda01a35b4c6bee65273b5744ae43904c5bf6202a5d461d67de6ee1ec9d1210a121181d5876a3aee3f37b4f1e
|
7
|
+
data.tar.gz: ed4f7ba1b52e9526d4f4a630f2ca06234816bd6be7522e29a98015a8bfa94a8bccdf98a03139ef9f45b266a8f62cb9d922c93ddebf797125d91d04a2203a4aec
|
@@ -1,3 +1,4 @@
|
|
1
|
+
<% module_namespacing_when_supported do -%>
|
1
2
|
class GraphqlController < ApplicationController
|
2
3
|
# If accessing from outside this domain, nullify the session
|
3
4
|
# This allows for outside API access while preventing CSRF attacks,
|
@@ -48,3 +49,4 @@ class GraphqlController < ApplicationController
|
|
48
49
|
render json: { errors: [{ message: e.message, backtrace: e.backtrace }], data: {} }, status: 500
|
49
50
|
end
|
50
51
|
end
|
52
|
+
<% end -%>
|
@@ -1,6 +1,8 @@
|
|
1
|
+
<% module_namespacing_when_supported do -%>
|
1
2
|
module Types
|
2
3
|
class <%= type_ruby_name.split('::')[-1] %> < Types::BaseObject
|
3
4
|
<% if options.node %> implements GraphQL::Relay::Node.interface
|
4
5
|
<% end %><% normalized_fields.each do |f| %> <%= f.to_ruby %>
|
5
6
|
<% end %> end
|
6
7
|
end
|
8
|
+
<% end -%>
|
@@ -1,5 +1,7 @@
|
|
1
|
+
<% module_namespacing_when_supported do -%>
|
1
2
|
module Types
|
2
3
|
class <%= type_ruby_name.split('::')[-1] %> < Types::BaseUnion
|
3
|
-
<% if possible_types.any? %> possible_types
|
4
|
+
<% if possible_types.any? %> possible_types <%= normalized_possible_types.join(", ") %>
|
4
5
|
<% end %> end
|
5
6
|
end
|
7
|
+
<% end -%>
|
data/lib/graphql.rb
CHANGED
@@ -21,6 +21,14 @@ module GraphQL
|
|
21
21
|
class RequiredImplementationMissingError < Error
|
22
22
|
end
|
23
23
|
|
24
|
+
class << self
|
25
|
+
def default_parser
|
26
|
+
@default_parser ||= GraphQL::Language::Parser
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_writer :default_parser
|
30
|
+
end
|
31
|
+
|
24
32
|
# Turn a query string or schema definition into an AST
|
25
33
|
# @param graphql_string [String] a GraphQL query string or schema definition
|
26
34
|
# @return [GraphQL::Language::Nodes::Document]
|
@@ -61,6 +69,14 @@ module GraphQL
|
|
61
69
|
end
|
62
70
|
end
|
63
71
|
end
|
72
|
+
|
73
|
+
module StringMatchBackport
|
74
|
+
refine String do
|
75
|
+
def match?(pattern)
|
76
|
+
self =~ pattern
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
64
80
|
end
|
65
81
|
|
66
82
|
# Order matters for these:
|
@@ -113,6 +129,7 @@ require "graphql/introspection"
|
|
113
129
|
require "graphql/analysis_error"
|
114
130
|
require "graphql/coercion_error"
|
115
131
|
require "graphql/invalid_name_error"
|
132
|
+
require "graphql/integer_decoding_error"
|
116
133
|
require "graphql/integer_encoding_error"
|
117
134
|
require "graphql/string_encoding_error"
|
118
135
|
require "graphql/internal_representation"
|
data/lib/graphql/argument.rb
CHANGED
@@ -3,14 +3,14 @@ module GraphQL
|
|
3
3
|
# @api deprecated
|
4
4
|
class Argument
|
5
5
|
include GraphQL::Define::InstanceDefinable
|
6
|
-
accepts_definitions :name, :type, :description, :default_value, :as, :prepare, :method_access
|
6
|
+
accepts_definitions :name, :type, :description, :default_value, :as, :prepare, :method_access, :deprecation_reason
|
7
7
|
attr_reader :default_value
|
8
|
-
attr_accessor :description, :name, :as
|
8
|
+
attr_accessor :description, :name, :as, :deprecation_reason
|
9
9
|
attr_accessor :ast_node
|
10
10
|
attr_accessor :method_access
|
11
11
|
alias :graphql_name :name
|
12
12
|
|
13
|
-
ensure_defined(:name, :description, :default_value, :type=, :type, :as, :expose_as, :prepare, :method_access)
|
13
|
+
ensure_defined(:name, :description, :default_value, :type=, :type, :as, :expose_as, :prepare, :method_access, :deprecation_reason)
|
14
14
|
|
15
15
|
# @api private
|
16
16
|
module DefaultPrepare
|
@@ -15,7 +15,8 @@ module GraphQL
|
|
15
15
|
when "validate", "analyze_query", "execute_query", "execute_query_lazy"
|
16
16
|
metadata[:query] || metadata[:queries]
|
17
17
|
when "execute_field", "execute_field_lazy"
|
18
|
-
|
18
|
+
# The interpreter passes `query:`, legacy passes `context:`
|
19
|
+
metadata[:context] || ((q = metadata[:query]) && q.context)
|
19
20
|
else
|
20
21
|
# Custom key, no backtrace data for this
|
21
22
|
nil
|
@@ -2,9 +2,9 @@
|
|
2
2
|
module GraphQL
|
3
3
|
module Define
|
4
4
|
module AssignGlobalIdField
|
5
|
-
def self.call(type_defn, field_name)
|
5
|
+
def self.call(type_defn, field_name, **field_kwargs)
|
6
6
|
resolve = GraphQL::Relay::GlobalIdResolve.new(type: type_defn)
|
7
|
-
GraphQL::Define::AssignObjectField.call(type_defn, field_name, type: GraphQL::ID_TYPE.to_non_null_type, resolve: resolve)
|
7
|
+
GraphQL::Define::AssignObjectField.call(type_defn, field_name, **field_kwargs, type: GraphQL::ID_TYPE.to_non_null_type, resolve: resolve)
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
@@ -93,6 +93,16 @@ module GraphQL
|
|
93
93
|
tracer.trace("execute_query_lazy", {multiplex: multiplex, query: query}) do
|
94
94
|
Interpreter::Resolve.resolve_all(final_values)
|
95
95
|
end
|
96
|
+
queries.each do |query|
|
97
|
+
runtime = query.context.namespace(:interpreter)[:runtime]
|
98
|
+
if runtime
|
99
|
+
runtime.delete_interpreter_context(:current_path)
|
100
|
+
runtime.delete_interpreter_context(:current_field)
|
101
|
+
runtime.delete_interpreter_context(:current_object)
|
102
|
+
runtime.delete_interpreter_context(:current_arguments)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
nil
|
96
106
|
end
|
97
107
|
|
98
108
|
class ListResultFailedError < GraphQL::Error
|
@@ -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)
|
@@ -43,23 +43,24 @@ module GraphQL
|
|
43
43
|
# might be stored up in lazies.
|
44
44
|
# @return [void]
|
45
45
|
def run_eager
|
46
|
-
|
47
46
|
root_operation = query.selected_operation
|
48
47
|
root_op_type = root_operation.operation_type || "query"
|
49
48
|
root_type = schema.root_type_for_operation(root_op_type)
|
50
49
|
path = []
|
51
|
-
|
52
|
-
@interpreter_context[:current_path] = path
|
50
|
+
set_all_interpreter_context(query.root_value, nil, nil, path)
|
53
51
|
object_proxy = authorized_new(root_type, query.root_value, context, path)
|
54
52
|
object_proxy = schema.sync_lazy(object_proxy)
|
55
53
|
if object_proxy.nil?
|
56
54
|
# Root .authorized? returned false.
|
57
55
|
write_in_response(path, nil)
|
58
|
-
nil
|
59
56
|
else
|
60
57
|
evaluate_selections(path, context.scoped_context, object_proxy, root_type, root_operation.selections, root_operation_type: root_op_type)
|
61
|
-
nil
|
62
58
|
end
|
59
|
+
delete_interpreter_context(:current_path)
|
60
|
+
delete_interpreter_context(:current_field)
|
61
|
+
delete_interpreter_context(:current_object)
|
62
|
+
delete_interpreter_context(:current_arguments)
|
63
|
+
nil
|
63
64
|
end
|
64
65
|
|
65
66
|
def gather_selections(owner_object, owner_type, selections, selections_by_name)
|
@@ -116,9 +117,10 @@ module GraphQL
|
|
116
117
|
end
|
117
118
|
end
|
118
119
|
|
120
|
+
NO_ARGS = {}.freeze
|
121
|
+
|
119
122
|
def evaluate_selections(path, scoped_context, owner_object, owner_type, selections, root_operation_type: nil)
|
120
|
-
|
121
|
-
@interpreter_context[:current_path] = path
|
123
|
+
set_all_interpreter_context(owner_object, nil, nil, path)
|
122
124
|
selections_by_name = {}
|
123
125
|
gather_selections(owner_object, owner_type, selections, selections_by_name)
|
124
126
|
selections_by_name.each do |result_name, field_ast_nodes_or_ast_node|
|
@@ -157,8 +159,7 @@ module GraphQL
|
|
157
159
|
# to propagate `null`
|
158
160
|
set_type_at_path(next_path, return_type)
|
159
161
|
# Set this before calling `run_with_directives`, so that the directive can have the latest path
|
160
|
-
|
161
|
-
@interpreter_context[:current_field] = field_defn
|
162
|
+
set_all_interpreter_context(nil, field_defn, nil, next_path)
|
162
163
|
|
163
164
|
context.scoped_context = scoped_context
|
164
165
|
object = owner_object
|
@@ -169,44 +170,50 @@ module GraphQL
|
|
169
170
|
|
170
171
|
begin
|
171
172
|
kwarg_arguments = arguments(object, field_defn, ast_node)
|
172
|
-
rescue GraphQL::ExecutionError => e
|
173
|
-
continue_value(next_path, e, field_defn, return_type.non_null?, ast_node)
|
173
|
+
rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => e
|
174
|
+
continue_value(next_path, e, owner_type, field_defn, return_type.non_null?, ast_node)
|
174
175
|
next
|
175
176
|
end
|
176
177
|
|
177
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|
|
178
|
-
|
179
|
-
|
179
|
+
case resolved_arguments
|
180
|
+
when GraphQL::ExecutionError, GraphQL::UnauthorizedError
|
181
|
+
continue_value(next_path, resolved_arguments, owner_type, field_defn, return_type.non_null?, ast_node)
|
180
182
|
next
|
181
183
|
end
|
182
184
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
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)
|
196
212
|
end
|
197
|
-
kwarg_arguments[:lookahead] = Execution::Lookahead.new(
|
198
|
-
query: query,
|
199
|
-
ast_nodes: field_ast_nodes,
|
200
|
-
field: field_defn,
|
201
|
-
)
|
202
|
-
when :argument_details
|
203
|
-
kwarg_arguments[:argument_details] = resolved_arguments
|
204
|
-
else
|
205
|
-
kwarg_arguments[extra] = field_defn.fetch_extra(extra, context)
|
206
213
|
end
|
207
214
|
end
|
208
215
|
|
209
|
-
|
216
|
+
set_all_interpreter_context(nil, nil, kwarg_arguments, nil)
|
210
217
|
|
211
218
|
# Optimize for the case that field is selected only once
|
212
219
|
if field_ast_nodes.nil? || field_ast_nodes.size == 1
|
@@ -228,12 +235,12 @@ module GraphQL
|
|
228
235
|
err
|
229
236
|
end
|
230
237
|
after_lazy(app_result, owner: owner_type, field: field_defn, path: next_path, scoped_context: context.scoped_context, owner_object: object, arguments: kwarg_arguments) do |inner_result|
|
231
|
-
continue_value = continue_value(next_path, inner_result, field_defn, return_type.non_null?, ast_node)
|
238
|
+
continue_value = continue_value(next_path, inner_result, owner_type, field_defn, return_type.non_null?, ast_node)
|
232
239
|
if RawValue === continue_value
|
233
240
|
# Write raw value directly to the response without resolving nested objects
|
234
241
|
write_in_response(next_path, continue_value.resolve)
|
235
242
|
elsif HALT != continue_value
|
236
|
-
continue_field(next_path, continue_value, field_defn, return_type, ast_node, next_selections, false, object, kwarg_arguments)
|
243
|
+
continue_field(next_path, continue_value, owner_type, field_defn, return_type, ast_node, next_selections, false, object, kwarg_arguments)
|
237
244
|
end
|
238
245
|
end
|
239
246
|
end
|
@@ -251,10 +258,9 @@ module GraphQL
|
|
251
258
|
end
|
252
259
|
|
253
260
|
HALT = Object.new
|
254
|
-
def continue_value(path, value, field, is_non_null, ast_node)
|
261
|
+
def continue_value(path, value, parent_type, field, is_non_null, ast_node)
|
255
262
|
if value.nil?
|
256
263
|
if is_non_null
|
257
|
-
parent_type = field.owner_type
|
258
264
|
err = parent_type::InvalidNullError.new(parent_type, field, value)
|
259
265
|
write_invalid_null_in_response(path, err)
|
260
266
|
else
|
@@ -282,7 +288,7 @@ module GraphQL
|
|
282
288
|
err
|
283
289
|
end
|
284
290
|
|
285
|
-
continue_value(path, next_value, field, is_non_null, ast_node)
|
291
|
+
continue_value(path, next_value, parent_type, field, is_non_null, ast_node)
|
286
292
|
elsif GraphQL::Execution::Execute::SKIP == value
|
287
293
|
HALT
|
288
294
|
else
|
@@ -298,49 +304,49 @@ module GraphQL
|
|
298
304
|
# Location information from `path` and `ast_node`.
|
299
305
|
#
|
300
306
|
# @return [Lazy, Array, Hash, Object] Lazy, Array, and Hash are all traversed to resolve lazy values later
|
301
|
-
def continue_field(path, value, field,
|
302
|
-
case
|
307
|
+
def continue_field(path, value, owner_type, field, current_type, ast_node, next_selections, is_non_null, owner_object, arguments) # rubocop:disable Metrics/ParameterLists
|
308
|
+
case current_type.kind.name
|
303
309
|
when "SCALAR", "ENUM"
|
304
|
-
r =
|
310
|
+
r = current_type.coerce_result(value, context)
|
305
311
|
write_in_response(path, r)
|
306
312
|
r
|
307
313
|
when "UNION", "INTERFACE"
|
308
|
-
resolved_type_or_lazy, resolved_value = resolve_type(
|
314
|
+
resolved_type_or_lazy, resolved_value = resolve_type(current_type, value, path)
|
309
315
|
resolved_value ||= value
|
310
316
|
|
311
|
-
after_lazy(resolved_type_or_lazy, owner:
|
312
|
-
possible_types = query.possible_types(
|
317
|
+
after_lazy(resolved_type_or_lazy, owner: current_type, path: path, scoped_context: context.scoped_context, field: field, owner_object: owner_object, arguments: arguments, trace: false) do |resolved_type|
|
318
|
+
possible_types = query.possible_types(current_type)
|
313
319
|
|
314
320
|
if !possible_types.include?(resolved_type)
|
315
321
|
parent_type = field.owner_type
|
316
|
-
err_class =
|
322
|
+
err_class = current_type::UnresolvedTypeError
|
317
323
|
type_error = err_class.new(resolved_value, field, parent_type, resolved_type, possible_types)
|
318
324
|
schema.type_error(type_error, context)
|
319
325
|
write_in_response(path, nil)
|
320
326
|
nil
|
321
327
|
else
|
322
|
-
continue_field(path, resolved_value, field, resolved_type, ast_node, next_selections, is_non_null, owner_object, arguments)
|
328
|
+
continue_field(path, resolved_value, owner_type, field, resolved_type, ast_node, next_selections, is_non_null, owner_object, arguments)
|
323
329
|
end
|
324
330
|
end
|
325
331
|
when "OBJECT"
|
326
332
|
object_proxy = begin
|
327
|
-
authorized_new(
|
333
|
+
authorized_new(current_type, value, context, path)
|
328
334
|
rescue GraphQL::ExecutionError => err
|
329
335
|
err
|
330
336
|
end
|
331
|
-
after_lazy(object_proxy, owner:
|
332
|
-
continue_value = continue_value(path, inner_object, field, is_non_null, ast_node)
|
337
|
+
after_lazy(object_proxy, owner: current_type, path: path, scoped_context: context.scoped_context, field: field, owner_object: owner_object, arguments: arguments, trace: false) do |inner_object|
|
338
|
+
continue_value = continue_value(path, inner_object, owner_type, field, is_non_null, ast_node)
|
333
339
|
if HALT != continue_value
|
334
340
|
response_hash = {}
|
335
341
|
write_in_response(path, response_hash)
|
336
|
-
evaluate_selections(path, context.scoped_context, continue_value,
|
342
|
+
evaluate_selections(path, context.scoped_context, continue_value, current_type, next_selections)
|
337
343
|
response_hash
|
338
344
|
end
|
339
345
|
end
|
340
346
|
when "LIST"
|
341
347
|
response_list = []
|
342
348
|
write_in_response(path, response_list)
|
343
|
-
inner_type =
|
349
|
+
inner_type = current_type.of_type
|
344
350
|
idx = 0
|
345
351
|
scoped_context = context.scoped_context
|
346
352
|
begin
|
@@ -352,9 +358,9 @@ module GraphQL
|
|
352
358
|
set_type_at_path(next_path, inner_type)
|
353
359
|
# This will update `response_list` with the lazy
|
354
360
|
after_lazy(inner_value, owner: inner_type, path: next_path, scoped_context: scoped_context, field: field, owner_object: owner_object, arguments: arguments) do |inner_inner_value|
|
355
|
-
continue_value = continue_value(next_path, inner_inner_value, field, inner_type.non_null?, ast_node)
|
361
|
+
continue_value = continue_value(next_path, inner_inner_value, owner_type, field, inner_type.non_null?, ast_node)
|
356
362
|
if HALT != continue_value
|
357
|
-
continue_field(next_path, continue_value, field, inner_type, ast_node, next_selections, false, owner_object, arguments)
|
363
|
+
continue_field(next_path, continue_value, owner_type, field, inner_type, ast_node, next_selections, false, owner_object, arguments)
|
358
364
|
end
|
359
365
|
end
|
360
366
|
end
|
@@ -371,12 +377,12 @@ module GraphQL
|
|
371
377
|
|
372
378
|
response_list
|
373
379
|
when "NON_NULL"
|
374
|
-
inner_type =
|
380
|
+
inner_type = current_type.of_type
|
375
381
|
# Don't `set_type_at_path` because we want the static type,
|
376
382
|
# we're going to use that to determine whether a `nil` should be propagated or not.
|
377
|
-
continue_field(path, value, field, inner_type, ast_node, next_selections, true, owner_object, arguments)
|
383
|
+
continue_field(path, value, owner_type, field, inner_type, ast_node, next_selections, true, owner_object, arguments)
|
378
384
|
else
|
379
|
-
raise "Invariant: Unhandled type kind #{
|
385
|
+
raise "Invariant: Unhandled type kind #{current_type.kind} (#{current_type})"
|
380
386
|
end
|
381
387
|
end
|
382
388
|
|
@@ -413,6 +419,21 @@ module GraphQL
|
|
413
419
|
true
|
414
420
|
end
|
415
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
|
+
|
416
437
|
# @param obj [Object] Some user-returned value that may want to be batched
|
417
438
|
# @param path [Array<String>]
|
418
439
|
# @param field [GraphQL::Schema::Field]
|
@@ -420,16 +441,10 @@ module GraphQL
|
|
420
441
|
# @param trace [Boolean] If `false`, don't wrap this with field tracing
|
421
442
|
# @return [GraphQL::Execution::Lazy, Object] If loading `object` will be deferred, it's a wrapper over it.
|
422
443
|
def after_lazy(lazy_obj, owner:, field:, path:, scoped_context:, owner_object:, arguments:, eager: false, trace: true, &block)
|
423
|
-
|
424
|
-
@interpreter_context[:current_arguments] = arguments
|
425
|
-
@interpreter_context[:current_path] = path
|
426
|
-
@interpreter_context[:current_field] = field
|
444
|
+
set_all_interpreter_context(owner_object, field, arguments, path)
|
427
445
|
if schema.lazy?(lazy_obj)
|
428
446
|
lazy = GraphQL::Execution::Lazy.new(path: path, field: field) do
|
429
|
-
|
430
|
-
@interpreter_context[:current_field] = field
|
431
|
-
@interpreter_context[:current_object] = owner_object
|
432
|
-
@interpreter_context[:current_arguments] = arguments
|
447
|
+
set_all_interpreter_context(owner_object, field, arguments, path)
|
433
448
|
context.scoped_context = scoped_context
|
434
449
|
# Wrap the execution of _this_ method with tracing,
|
435
450
|
# but don't wrap the continuation below
|
@@ -540,6 +555,18 @@ module GraphQL
|
|
540
555
|
res && res[:__dead]
|
541
556
|
end
|
542
557
|
|
558
|
+
# Set this pair in the Query context, but also in the interpeter namespace,
|
559
|
+
# for compatibility.
|
560
|
+
def set_interpreter_context(key, value)
|
561
|
+
@interpreter_context[key] = value
|
562
|
+
@context[key] = value
|
563
|
+
end
|
564
|
+
|
565
|
+
def delete_interpreter_context(key)
|
566
|
+
@interpreter_context.delete(key)
|
567
|
+
@context.delete(key)
|
568
|
+
end
|
569
|
+
|
543
570
|
def resolve_type(type, value, path)
|
544
571
|
trace_payload = { context: context, type: type, object: value, path: path }
|
545
572
|
resolved_type, resolved_value = query.trace("resolve_type", trace_payload) do
|