graphql 2.4.3 → 2.4.13
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/analysis/analyzer.rb +2 -1
- data/lib/graphql/analysis/visitor.rb +38 -41
- data/lib/graphql/analysis.rb +15 -12
- data/lib/graphql/autoload.rb +38 -0
- data/lib/graphql/backtrace/table.rb +95 -55
- data/lib/graphql/backtrace.rb +1 -19
- data/lib/graphql/current.rb +6 -1
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.css +6 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.js +7 -0
- data/lib/graphql/dashboard/statics/dashboard.css +3 -0
- data/lib/graphql/dashboard/statics/dashboard.js +78 -0
- data/lib/graphql/dashboard/statics/header-icon.png +0 -0
- data/lib/graphql/dashboard/statics/icon.png +0 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/landings/show.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/traces/index.html.erb +63 -0
- data/lib/graphql/dashboard/views/layouts/graphql/dashboard/application.html.erb +60 -0
- data/lib/graphql/dashboard.rb +142 -0
- data/lib/graphql/dataloader/active_record_association_source.rb +64 -0
- data/lib/graphql/dataloader/active_record_source.rb +26 -0
- data/lib/graphql/dataloader/async_dataloader.rb +21 -9
- data/lib/graphql/dataloader/null_dataloader.rb +1 -1
- data/lib/graphql/dataloader/source.rb +3 -3
- data/lib/graphql/dataloader.rb +43 -14
- data/lib/graphql/execution/interpreter/resolve.rb +3 -3
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +11 -4
- data/lib/graphql/execution/interpreter/runtime.rb +67 -40
- data/lib/graphql/execution/interpreter.rb +16 -6
- data/lib/graphql/execution/multiplex.rb +0 -4
- data/lib/graphql/introspection/directive_location_enum.rb +1 -1
- data/lib/graphql/invalid_name_error.rb +1 -1
- data/lib/graphql/invalid_null_error.rb +5 -15
- data/lib/graphql/language/cache.rb +13 -0
- data/lib/graphql/language/document_from_schema_definition.rb +8 -7
- data/lib/graphql/language/lexer.rb +11 -4
- data/lib/graphql/language/nodes.rb +3 -0
- data/lib/graphql/language/parser.rb +2 -2
- data/lib/graphql/language/printer.rb +8 -8
- data/lib/graphql/language/static_visitor.rb +37 -33
- data/lib/graphql/language/visitor.rb +59 -55
- data/lib/graphql/pagination/connection.rb +1 -1
- data/lib/graphql/query/context/scoped_context.rb +1 -1
- data/lib/graphql/query/context.rb +6 -5
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query.rb +20 -22
- data/lib/graphql/railtie.rb +7 -0
- data/lib/graphql/schema/addition.rb +1 -1
- data/lib/graphql/schema/argument.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +8 -7
- data/lib/graphql/schema/directive/flagged.rb +1 -1
- data/lib/graphql/schema/directive.rb +2 -2
- data/lib/graphql/schema/enum.rb +36 -1
- data/lib/graphql/schema/enum_value.rb +1 -1
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +12 -12
- data/lib/graphql/schema/field_extension.rb +1 -1
- data/lib/graphql/schema/has_single_input_argument.rb +3 -1
- data/lib/graphql/schema/input_object.rb +70 -34
- data/lib/graphql/schema/interface.rb +3 -2
- data/lib/graphql/schema/loader.rb +1 -1
- data/lib/graphql/schema/member/has_arguments.rb +25 -17
- data/lib/graphql/schema/member/has_dataloader.rb +60 -0
- data/lib/graphql/schema/member/has_directives.rb +4 -4
- data/lib/graphql/schema/member/has_fields.rb +19 -1
- data/lib/graphql/schema/member/has_interfaces.rb +5 -5
- data/lib/graphql/schema/member/has_validators.rb +1 -1
- data/lib/graphql/schema/member/scoped.rb +1 -1
- data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
- data/lib/graphql/schema/member.rb +1 -0
- data/lib/graphql/schema/object.rb +25 -8
- data/lib/graphql/schema/relay_classic_mutation.rb +0 -1
- data/lib/graphql/schema/resolver.rb +11 -10
- data/lib/graphql/schema/subscription.rb +52 -6
- data/lib/graphql/schema/union.rb +1 -1
- data/lib/graphql/schema/validator/required_validator.rb +23 -6
- data/lib/graphql/schema/validator.rb +1 -1
- data/lib/graphql/schema/visibility/migration.rb +1 -0
- data/lib/graphql/schema/visibility/profile.rb +69 -237
- data/lib/graphql/schema/visibility/visit.rb +190 -0
- data/lib/graphql/schema/visibility.rb +169 -28
- data/lib/graphql/schema/warden.rb +18 -5
- data/lib/graphql/schema.rb +90 -43
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +1 -1
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -1
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +1 -1
- data/lib/graphql/static_validation/validation_context.rb +1 -0
- data/lib/graphql/static_validation/validator.rb +6 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +1 -1
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +12 -10
- data/lib/graphql/subscriptions/event.rb +12 -1
- data/lib/graphql/subscriptions/serialize.rb +1 -1
- data/lib/graphql/subscriptions.rb +1 -1
- data/lib/graphql/testing/helpers.rb +2 -2
- data/lib/graphql/tracing/active_support_notifications_trace.rb +7 -3
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +1 -1
- data/lib/graphql/tracing/appoptics_trace.rb +9 -1
- data/lib/graphql/tracing/appoptics_tracing.rb +2 -0
- data/lib/graphql/tracing/appsignal_trace.rb +12 -0
- data/lib/graphql/tracing/appsignal_tracing.rb +2 -0
- data/lib/graphql/tracing/call_legacy_tracers.rb +66 -0
- data/lib/graphql/tracing/data_dog_trace.rb +11 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
- data/lib/graphql/tracing/detailed_trace/memory_backend.rb +60 -0
- data/lib/graphql/tracing/detailed_trace/redis_backend.rb +72 -0
- data/lib/graphql/tracing/detailed_trace.rb +93 -0
- data/lib/graphql/tracing/legacy_hooks_trace.rb +1 -0
- data/lib/graphql/tracing/legacy_trace.rb +4 -61
- data/lib/graphql/tracing/new_relic_trace.rb +164 -41
- data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
- data/lib/graphql/tracing/notifications_trace.rb +4 -0
- data/lib/graphql/tracing/notifications_tracing.rb +2 -0
- data/lib/graphql/tracing/null_trace.rb +9 -0
- data/lib/graphql/tracing/perfetto_trace/trace.proto +141 -0
- data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +33 -0
- data/lib/graphql/tracing/perfetto_trace.rb +737 -0
- data/lib/graphql/tracing/platform_trace.rb +5 -0
- data/lib/graphql/tracing/prometheus_trace/graphql_collector.rb +2 -0
- data/lib/graphql/tracing/prometheus_trace.rb +31 -0
- data/lib/graphql/tracing/prometheus_tracing.rb +2 -0
- data/lib/graphql/tracing/scout_trace.rb +11 -0
- data/lib/graphql/tracing/scout_tracing.rb +2 -0
- data/lib/graphql/tracing/sentry_trace.rb +11 -0
- data/lib/graphql/tracing/statsd_trace.rb +15 -0
- data/lib/graphql/tracing/statsd_tracing.rb +2 -0
- data/lib/graphql/tracing/trace.rb +128 -1
- data/lib/graphql/tracing.rb +30 -30
- data/lib/graphql/types/relay/connection_behaviors.rb +3 -3
- data/lib/graphql/types/relay/edge_behaviors.rb +2 -2
- data/lib/graphql/types.rb +18 -11
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +55 -47
- metadata +152 -10
- data/lib/graphql/backtrace/inspect_result.rb +0 -38
- data/lib/graphql/backtrace/trace.rb +0 -93
- data/lib/graphql/backtrace/tracer.rb +0 -80
- data/lib/graphql/schema/null_mask.rb +0 -11
@@ -22,39 +22,6 @@ module GraphQL
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
# We don't use `alias` here because it breaks `super`
|
26
|
-
def self.make_visit_methods(ast_node_class)
|
27
|
-
node_method = ast_node_class.visit_method
|
28
|
-
children_of_type = ast_node_class.children_of_type
|
29
|
-
child_visit_method = :"#{node_method}_children"
|
30
|
-
|
31
|
-
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
32
|
-
# The default implementation for visiting an AST node.
|
33
|
-
# It doesn't _do_ anything, but it continues to visiting the node's children.
|
34
|
-
# To customize this hook, override one of its make_visit_methods (or the base method?)
|
35
|
-
# in your subclasses.
|
36
|
-
#
|
37
|
-
# @param node [GraphQL::Language::Nodes::AbstractNode] the node being visited
|
38
|
-
# @param parent [GraphQL::Language::Nodes::AbstractNode, nil] the previously-visited node, or `nil` if this is the root node.
|
39
|
-
# @return [void]
|
40
|
-
def #{node_method}(node, parent)
|
41
|
-
#{
|
42
|
-
if method_defined?(child_visit_method)
|
43
|
-
"#{child_visit_method}(node)"
|
44
|
-
elsif children_of_type
|
45
|
-
children_of_type.map do |child_accessor, child_class|
|
46
|
-
"node.#{child_accessor}.each do |child_node|
|
47
|
-
#{child_class.visit_method}(child_node, node)
|
48
|
-
end"
|
49
|
-
end.join("\n")
|
50
|
-
else
|
51
|
-
""
|
52
|
-
end
|
53
|
-
}
|
54
|
-
end
|
55
|
-
RUBY
|
56
|
-
end
|
57
|
-
|
58
25
|
def on_document_children(document_node)
|
59
26
|
document_node.children.each do |child_node|
|
60
27
|
visit_method = child_node.visit_method
|
@@ -123,6 +90,41 @@ module GraphQL
|
|
123
90
|
end
|
124
91
|
end
|
125
92
|
|
93
|
+
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
94
|
+
|
95
|
+
# We don't use `alias` here because it breaks `super`
|
96
|
+
def self.make_visit_methods(ast_node_class)
|
97
|
+
node_method = ast_node_class.visit_method
|
98
|
+
children_of_type = ast_node_class.children_of_type
|
99
|
+
child_visit_method = :"#{node_method}_children"
|
100
|
+
|
101
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
102
|
+
# The default implementation for visiting an AST node.
|
103
|
+
# It doesn't _do_ anything, but it continues to visiting the node's children.
|
104
|
+
# To customize this hook, override one of its make_visit_methods (or the base method?)
|
105
|
+
# in your subclasses.
|
106
|
+
#
|
107
|
+
# @param node [GraphQL::Language::Nodes::AbstractNode] the node being visited
|
108
|
+
# @param parent [GraphQL::Language::Nodes::AbstractNode, nil] the previously-visited node, or `nil` if this is the root node.
|
109
|
+
# @return [void]
|
110
|
+
def #{node_method}(node, parent)
|
111
|
+
#{
|
112
|
+
if method_defined?(child_visit_method)
|
113
|
+
"#{child_visit_method}(node)"
|
114
|
+
elsif children_of_type
|
115
|
+
children_of_type.map do |child_accessor, child_class|
|
116
|
+
"node.#{child_accessor}.each do |child_node|
|
117
|
+
#{child_class.visit_method}(child_node, node)
|
118
|
+
end"
|
119
|
+
end.join("\n")
|
120
|
+
else
|
121
|
+
""
|
122
|
+
end
|
123
|
+
}
|
124
|
+
end
|
125
|
+
RUBY
|
126
|
+
end
|
127
|
+
|
126
128
|
[
|
127
129
|
Language::Nodes::Argument,
|
128
130
|
Language::Nodes::Directive,
|
@@ -162,6 +164,8 @@ module GraphQL
|
|
162
164
|
].each do |ast_node_class|
|
163
165
|
make_visit_methods(ast_node_class)
|
164
166
|
end
|
167
|
+
|
168
|
+
# rubocop:disable Development/NoEvalCop
|
165
169
|
end
|
166
170
|
end
|
167
171
|
end
|
@@ -61,61 +61,6 @@ module GraphQL
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
# We don't use `alias` here because it breaks `super`
|
65
|
-
def self.make_visit_methods(ast_node_class)
|
66
|
-
node_method = ast_node_class.visit_method
|
67
|
-
children_of_type = ast_node_class.children_of_type
|
68
|
-
child_visit_method = :"#{node_method}_children"
|
69
|
-
|
70
|
-
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
71
|
-
# The default implementation for visiting an AST node.
|
72
|
-
# It doesn't _do_ anything, but it continues to visiting the node's children.
|
73
|
-
# To customize this hook, override one of its make_visit_methods (or the base method?)
|
74
|
-
# in your subclasses.
|
75
|
-
#
|
76
|
-
# @param node [GraphQL::Language::Nodes::AbstractNode] the node being visited
|
77
|
-
# @param parent [GraphQL::Language::Nodes::AbstractNode, nil] the previously-visited node, or `nil` if this is the root node.
|
78
|
-
# @return [Array, nil] If there were modifications, it returns an array of new nodes, otherwise, it returns `nil`.
|
79
|
-
def #{node_method}(node, parent)
|
80
|
-
if node.equal?(DELETE_NODE)
|
81
|
-
# This might be passed to `super(DELETE_NODE, ...)`
|
82
|
-
# by a user hook, don't want to keep visiting in that case.
|
83
|
-
[node, parent]
|
84
|
-
else
|
85
|
-
new_node = node
|
86
|
-
#{
|
87
|
-
if method_defined?(child_visit_method)
|
88
|
-
"new_node = #{child_visit_method}(new_node)"
|
89
|
-
elsif children_of_type
|
90
|
-
children_of_type.map do |child_accessor, child_class|
|
91
|
-
"node.#{child_accessor}.each do |child_node|
|
92
|
-
new_child_and_node = #{child_class.visit_method}_with_modifications(child_node, new_node)
|
93
|
-
# Reassign `node` in case the child hook makes a modification
|
94
|
-
if new_child_and_node.is_a?(Array)
|
95
|
-
new_node = new_child_and_node[1]
|
96
|
-
end
|
97
|
-
end"
|
98
|
-
end.join("\n")
|
99
|
-
else
|
100
|
-
""
|
101
|
-
end
|
102
|
-
}
|
103
|
-
|
104
|
-
if new_node.equal?(node)
|
105
|
-
[node, parent]
|
106
|
-
else
|
107
|
-
[new_node, parent]
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def #{node_method}_with_modifications(node, parent)
|
113
|
-
new_node_and_new_parent = #{node_method}(node, parent)
|
114
|
-
apply_modifications(node, parent, new_node_and_new_parent)
|
115
|
-
end
|
116
|
-
RUBY
|
117
|
-
end
|
118
|
-
|
119
64
|
def on_document_children(document_node)
|
120
65
|
new_node = document_node
|
121
66
|
document_node.children.each do |child_node|
|
@@ -216,6 +161,63 @@ module GraphQL
|
|
216
161
|
new_node
|
217
162
|
end
|
218
163
|
|
164
|
+
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
165
|
+
|
166
|
+
# We don't use `alias` here because it breaks `super`
|
167
|
+
def self.make_visit_methods(ast_node_class)
|
168
|
+
node_method = ast_node_class.visit_method
|
169
|
+
children_of_type = ast_node_class.children_of_type
|
170
|
+
child_visit_method = :"#{node_method}_children"
|
171
|
+
|
172
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
173
|
+
# The default implementation for visiting an AST node.
|
174
|
+
# It doesn't _do_ anything, but it continues to visiting the node's children.
|
175
|
+
# To customize this hook, override one of its make_visit_methods (or the base method?)
|
176
|
+
# in your subclasses.
|
177
|
+
#
|
178
|
+
# @param node [GraphQL::Language::Nodes::AbstractNode] the node being visited
|
179
|
+
# @param parent [GraphQL::Language::Nodes::AbstractNode, nil] the previously-visited node, or `nil` if this is the root node.
|
180
|
+
# @return [Array, nil] If there were modifications, it returns an array of new nodes, otherwise, it returns `nil`.
|
181
|
+
def #{node_method}(node, parent)
|
182
|
+
if node.equal?(DELETE_NODE)
|
183
|
+
# This might be passed to `super(DELETE_NODE, ...)`
|
184
|
+
# by a user hook, don't want to keep visiting in that case.
|
185
|
+
[node, parent]
|
186
|
+
else
|
187
|
+
new_node = node
|
188
|
+
#{
|
189
|
+
if method_defined?(child_visit_method)
|
190
|
+
"new_node = #{child_visit_method}(new_node)"
|
191
|
+
elsif children_of_type
|
192
|
+
children_of_type.map do |child_accessor, child_class|
|
193
|
+
"node.#{child_accessor}.each do |child_node|
|
194
|
+
new_child_and_node = #{child_class.visit_method}_with_modifications(child_node, new_node)
|
195
|
+
# Reassign `node` in case the child hook makes a modification
|
196
|
+
if new_child_and_node.is_a?(Array)
|
197
|
+
new_node = new_child_and_node[1]
|
198
|
+
end
|
199
|
+
end"
|
200
|
+
end.join("\n")
|
201
|
+
else
|
202
|
+
""
|
203
|
+
end
|
204
|
+
}
|
205
|
+
|
206
|
+
if new_node.equal?(node)
|
207
|
+
[node, parent]
|
208
|
+
else
|
209
|
+
[new_node, parent]
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def #{node_method}_with_modifications(node, parent)
|
215
|
+
new_node_and_new_parent = #{node_method}(node, parent)
|
216
|
+
apply_modifications(node, parent, new_node_and_new_parent)
|
217
|
+
end
|
218
|
+
RUBY
|
219
|
+
end
|
220
|
+
|
219
221
|
[
|
220
222
|
Language::Nodes::Argument,
|
221
223
|
Language::Nodes::Directive,
|
@@ -256,6 +258,8 @@ module GraphQL
|
|
256
258
|
make_visit_methods(ast_node_class)
|
257
259
|
end
|
258
260
|
|
261
|
+
# rubocop:enable Development/NoEvalCop
|
262
|
+
|
259
263
|
private
|
260
264
|
|
261
265
|
def apply_modifications(node, parent, new_node_and_new_parent)
|
@@ -223,7 +223,7 @@ module GraphQL
|
|
223
223
|
|
224
224
|
def detect_was_authorized_by_scope_items
|
225
225
|
if @context &&
|
226
|
-
(current_runtime_state =
|
226
|
+
(current_runtime_state = Fiber[:__graphql_runtime_info]) &&
|
227
227
|
(query_runtime_state = current_runtime_state[@context.query])
|
228
228
|
query_runtime_state.was_authorized_by_scope_items
|
229
229
|
else
|
@@ -1,5 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require "graphql/query/context/scoped_context"
|
3
2
|
|
4
3
|
module GraphQL
|
5
4
|
class Query
|
@@ -104,7 +103,7 @@ module GraphQL
|
|
104
103
|
if key == :current_path
|
105
104
|
current_path
|
106
105
|
else
|
107
|
-
(current_runtime_state =
|
106
|
+
(current_runtime_state = Fiber[:__graphql_runtime_info]) &&
|
108
107
|
(query_runtime_state = current_runtime_state[@query]) &&
|
109
108
|
(query_runtime_state.public_send(key))
|
110
109
|
end
|
@@ -144,7 +143,7 @@ module GraphQL
|
|
144
143
|
end
|
145
144
|
|
146
145
|
def current_path
|
147
|
-
current_runtime_state =
|
146
|
+
current_runtime_state = Fiber[:__graphql_runtime_info]
|
148
147
|
query_runtime_state = current_runtime_state && current_runtime_state[@query]
|
149
148
|
|
150
149
|
path = query_runtime_state &&
|
@@ -169,7 +168,7 @@ module GraphQL
|
|
169
168
|
|
170
169
|
def fetch(key, default = UNSPECIFIED_FETCH_DEFAULT)
|
171
170
|
if RUNTIME_METADATA_KEYS.include?(key)
|
172
|
-
(runtime =
|
171
|
+
(runtime = Fiber[:__graphql_runtime_info]) &&
|
173
172
|
(query_runtime_state = runtime[@query]) &&
|
174
173
|
(query_runtime_state.public_send(key))
|
175
174
|
elsif @scoped_context.key?(key)
|
@@ -187,7 +186,7 @@ module GraphQL
|
|
187
186
|
|
188
187
|
def dig(key, *other_keys)
|
189
188
|
if RUNTIME_METADATA_KEYS.include?(key)
|
190
|
-
(current_runtime_state =
|
189
|
+
(current_runtime_state = Fiber[:__graphql_runtime_info]) &&
|
191
190
|
(query_runtime_state = current_runtime_state[@query]) &&
|
192
191
|
(obj = query_runtime_state.public_send(key)) &&
|
193
192
|
if other_keys.empty?
|
@@ -289,3 +288,5 @@ module GraphQL
|
|
289
288
|
end
|
290
289
|
end
|
291
290
|
end
|
291
|
+
|
292
|
+
require "graphql/query/context/scoped_context"
|
data/lib/graphql/query.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require "graphql/query/context"
|
3
|
-
require "graphql/query/fingerprint"
|
4
|
-
require "graphql/query/null_context"
|
5
|
-
require "graphql/query/result"
|
6
|
-
require "graphql/query/variables"
|
7
|
-
require "graphql/query/input_validation_result"
|
8
|
-
require "graphql/query/variable_validation_error"
|
9
|
-
require "graphql/query/validation_pipeline"
|
10
2
|
|
11
3
|
module GraphQL
|
12
4
|
# A combination of query string and {Schema} instance which can be reduced to a {#result}.
|
13
5
|
class Query
|
6
|
+
extend Autoload
|
14
7
|
include Tracing::Traceable
|
15
8
|
extend Forwardable
|
16
9
|
|
10
|
+
autoload :Context, "graphql/query/context"
|
11
|
+
autoload :Fingerprint, "graphql/query/fingerprint"
|
12
|
+
autoload :NullContext, "graphql/query/null_context"
|
13
|
+
autoload :Result, "graphql/query/result"
|
14
|
+
autoload :Variables, "graphql/query/variables"
|
15
|
+
autoload :InputValidationResult, "graphql/query/input_validation_result"
|
16
|
+
autoload :VariableValidationError, "graphql/query/variable_validation_error"
|
17
|
+
autoload :ValidationPipeline, "graphql/query/validation_pipeline"
|
18
|
+
|
17
19
|
class OperationNameMissingError < GraphQL::ExecutionError
|
18
20
|
def initialize(name)
|
19
21
|
msg = if name.nil?
|
@@ -95,21 +97,22 @@ module GraphQL
|
|
95
97
|
# @param root_value [Object] the object used to resolve fields on the root type
|
96
98
|
# @param max_depth [Numeric] the maximum number of nested selections allowed for this query (falls back to schema-level value)
|
97
99
|
# @param max_complexity [Numeric] the maximum field complexity for this query (falls back to schema-level value)
|
98
|
-
# @param visibility_profile [Symbol]
|
100
|
+
# @param visibility_profile [Symbol] Another way to assign `context[:visibility_profile]`
|
99
101
|
def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, validate: true, static_validator: nil, visibility_profile: nil, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, warden: nil, use_visibility_profile: nil)
|
100
102
|
# Even if `variables: nil` is passed, use an empty hash for simpler logic
|
101
103
|
variables ||= {}
|
102
104
|
@schema = schema
|
103
105
|
@context = schema.context_class.new(query: self, values: context)
|
106
|
+
if visibility_profile
|
107
|
+
@context[:visibility_profile] ||= visibility_profile
|
108
|
+
end
|
104
109
|
|
105
110
|
if use_visibility_profile.nil?
|
106
111
|
use_visibility_profile = warden ? false : schema.use_visibility_profile?
|
107
112
|
end
|
108
113
|
|
109
|
-
@visibility_profile = visibility_profile
|
110
|
-
|
111
114
|
if use_visibility_profile
|
112
|
-
@visibility_profile = @schema.visibility.profile_for(@context
|
115
|
+
@visibility_profile = @schema.visibility.profile_for(@context)
|
113
116
|
@warden = Schema::Warden::NullWarden.new(context: @context, schema: @schema)
|
114
117
|
else
|
115
118
|
@visibility_profile = nil
|
@@ -125,15 +128,7 @@ module GraphQL
|
|
125
128
|
context_tracers = (context ? context.fetch(:tracers, []) : [])
|
126
129
|
@tracers = schema.tracers + context_tracers
|
127
130
|
|
128
|
-
|
129
|
-
if context && context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
|
130
|
-
if schema.trace_class <= GraphQL::Tracing::CallLegacyTracers
|
131
|
-
context_tracers += [GraphQL::Backtrace::Tracer]
|
132
|
-
@tracers << GraphQL::Backtrace::Tracer
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
if context_tracers.any? && !(schema.trace_class <= GraphQL::Tracing::CallLegacyTracers)
|
131
|
+
if !context_tracers.empty? && !(schema.trace_class <= GraphQL::Tracing::CallLegacyTracers)
|
137
132
|
raise ArgumentError, "context[:tracers] are not supported without `trace_with(GraphQL::Tracing::CallLegacyTracers)` in the schema configuration, please add it."
|
138
133
|
end
|
139
134
|
|
@@ -446,6 +441,7 @@ module GraphQL
|
|
446
441
|
@warden ||= @schema.warden_class.new(schema: @schema, context: @context)
|
447
442
|
parse_error = nil
|
448
443
|
@document ||= begin
|
444
|
+
current_trace.begin_parse(query_string)
|
449
445
|
if query_string
|
450
446
|
GraphQL.parse(query_string, trace: self.current_trace, max_tokens: @schema.max_query_string_tokens)
|
451
447
|
end
|
@@ -453,6 +449,8 @@ module GraphQL
|
|
453
449
|
parse_error = err
|
454
450
|
@schema.parse_error(err, @context)
|
455
451
|
nil
|
452
|
+
ensure
|
453
|
+
current_trace.end_parse(query_string)
|
456
454
|
end
|
457
455
|
|
458
456
|
@fragments = {}
|
@@ -479,7 +477,7 @@ module GraphQL
|
|
479
477
|
@mutation = false
|
480
478
|
@subscription = false
|
481
479
|
operation_name_error = nil
|
482
|
-
if
|
480
|
+
if !@operations.empty?
|
483
481
|
@selected_operation = find_operation(@operations, @operation_name)
|
484
482
|
if @selected_operation.nil?
|
485
483
|
operation_name_error = GraphQL::Query::OperationNameMissingError.new(@operation_name)
|
data/lib/graphql/railtie.rb
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module GraphQL
|
4
|
+
# Support {GraphQL::Parser::Cache} and {GraphQL.eager_load!}
|
5
|
+
#
|
6
|
+
# @example Enable the parser cache with default directory
|
7
|
+
#
|
8
|
+
# config.graphql.parser_cache = true
|
9
|
+
#
|
4
10
|
class Railtie < Rails::Railtie
|
5
11
|
config.graphql = ActiveSupport::OrderedOptions.new
|
6
12
|
config.graphql.parser_cache = false
|
13
|
+
config.eager_load_namespaces << GraphQL
|
7
14
|
|
8
15
|
initializer("graphql.cache") do |app|
|
9
16
|
if config.graphql.parser_cache
|
@@ -53,6 +53,7 @@ module GraphQL
|
|
53
53
|
def initialize(arg_name = nil, type_expr = nil, desc = nil, required: true, type: nil, name: nil, loads: nil, description: nil, comment: nil, ast_node: nil, default_value: NOT_CONFIGURED, as: nil, from_resolver: false, camelize: true, prepare: nil, owner:, validates: nil, directives: nil, deprecation_reason: nil, replace_null_with_default: false, &definition_block)
|
54
54
|
arg_name ||= name
|
55
55
|
@name = -(camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s)
|
56
|
+
NameValidator.validate!(@name)
|
56
57
|
@type_expr = type_expr || type
|
57
58
|
@description = desc || description
|
58
59
|
@comment = comment
|
@@ -89,11 +90,8 @@ module GraphQL
|
|
89
90
|
end
|
90
91
|
|
91
92
|
if definition_block
|
92
|
-
|
93
|
-
|
94
|
-
else
|
95
|
-
instance_eval(&definition_block)
|
96
|
-
end
|
93
|
+
# `self` will still be self, it will also be the first argument to the block:
|
94
|
+
instance_exec(self, &definition_block)
|
97
95
|
end
|
98
96
|
end
|
99
97
|
|
@@ -467,17 +467,18 @@ module GraphQL
|
|
467
467
|
|
468
468
|
# Don't do this for interfaces
|
469
469
|
if default_resolve
|
470
|
-
owner
|
471
|
-
# frozen_string_literal: true
|
472
|
-
def #{resolve_method_name}(**args)
|
473
|
-
field_instance = self.class.get_field("#{field_definition.name}")
|
474
|
-
context.schema.definition_default_resolve.call(self.class, field_instance, object, args, context)
|
475
|
-
end
|
476
|
-
RUBY
|
470
|
+
define_field_resolve_method(owner, resolve_method_name, field_definition.name)
|
477
471
|
end
|
478
472
|
end
|
479
473
|
end
|
480
474
|
|
475
|
+
def define_field_resolve_method(owner, method_name, field_name)
|
476
|
+
owner.define_method(method_name) { |**args|
|
477
|
+
field_instance = self.class.get_field(field_name)
|
478
|
+
context.schema.definition_default_resolve.call(self.class, field_instance, object, args, context)
|
479
|
+
}
|
480
|
+
end
|
481
|
+
|
481
482
|
def build_resolve_type(lookup_hash, directives, missing_type_handler)
|
482
483
|
resolve_type_proc = nil
|
483
484
|
resolve_type_proc = ->(ast_node) {
|
@@ -45,7 +45,7 @@ module GraphQL
|
|
45
45
|
def visible?(context)
|
46
46
|
if dir = self.directives.find { |d| d.is_a?(Flagged) }
|
47
47
|
relevant_flags = (f = context[:flags]) && dir.arguments[:by] & f # rubocop:disable Development/ContextIsPassedCop -- definition-related
|
48
|
-
relevant_flags && relevant_flags.
|
48
|
+
relevant_flags && !relevant_flags.empty? && super
|
49
49
|
else
|
50
50
|
super
|
51
51
|
end
|
@@ -29,7 +29,7 @@ module GraphQL
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def locations(*new_locations)
|
32
|
-
if new_locations.
|
32
|
+
if !new_locations.empty?
|
33
33
|
new_locations.each do |new_loc|
|
34
34
|
if !LOCATIONS.include?(new_loc.to_sym)
|
35
35
|
raise ArgumentError, "#{self} (#{self.graphql_name}) has an invalid directive location: `locations #{new_loc}` "
|
@@ -99,7 +99,7 @@ module GraphQL
|
|
99
99
|
|
100
100
|
def inherited(subclass)
|
101
101
|
super
|
102
|
-
subclass.
|
102
|
+
subclass.class_exec do
|
103
103
|
@default_graphql_name ||= nil
|
104
104
|
end
|
105
105
|
end
|
data/lib/graphql/schema/enum.rb
CHANGED
@@ -61,12 +61,19 @@ module GraphQL
|
|
61
61
|
# @option kwargs [String] :description, the GraphQL description for this value, present in documentation
|
62
62
|
# @option kwargs [String] :comment, the GraphQL comment for this value, present in documentation
|
63
63
|
# @option kwargs [::Object] :value the translated Ruby value for this object (defaults to `graphql_name`)
|
64
|
+
# @option kwargs [::Object] :value_method, the method name to fetch `graphql_name` (defaults to `graphql_name.downcase`)
|
64
65
|
# @option kwargs [String] :deprecation_reason if this object is deprecated, include a message here
|
66
|
+
# @param value_method [Symbol, false] A method to generate for this value, or `false` to skip generation
|
65
67
|
# @return [void]
|
66
68
|
# @see {Schema::EnumValue} which handles these inputs by default
|
67
|
-
def value(*args, **kwargs, &block)
|
69
|
+
def value(*args, value_method: nil, **kwargs, &block)
|
68
70
|
kwargs[:owner] = self
|
69
71
|
value = enum_value_class.new(*args, **kwargs, &block)
|
72
|
+
|
73
|
+
if value_method || (value_methods && value_method != false)
|
74
|
+
generate_value_method(value, value_method)
|
75
|
+
end
|
76
|
+
|
70
77
|
key = value.graphql_name
|
71
78
|
prev_value = own_values[key]
|
72
79
|
case prev_value
|
@@ -154,6 +161,18 @@ module GraphQL
|
|
154
161
|
end
|
155
162
|
end
|
156
163
|
|
164
|
+
def value_methods(new_value = NOT_CONFIGURED)
|
165
|
+
if NOT_CONFIGURED.equal?(new_value)
|
166
|
+
if @value_methods != nil
|
167
|
+
@value_methods
|
168
|
+
else
|
169
|
+
find_inherited_value(:value_methods, false)
|
170
|
+
end
|
171
|
+
else
|
172
|
+
@value_methods = new_value
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
157
176
|
def kind
|
158
177
|
GraphQL::TypeKinds::ENUM
|
159
178
|
end
|
@@ -215,6 +234,7 @@ module GraphQL
|
|
215
234
|
# because they would end up with names like `#<Class0x1234>::UnresolvedValueError` which messes up bug trackers
|
216
235
|
child_class.const_set(:UnresolvedValueError, Class.new(Schema::Enum::UnresolvedValueError))
|
217
236
|
end
|
237
|
+
child_class.class_exec { @value_methods = nil }
|
218
238
|
super
|
219
239
|
end
|
220
240
|
|
@@ -223,6 +243,21 @@ module GraphQL
|
|
223
243
|
def own_values
|
224
244
|
@own_values ||= {}
|
225
245
|
end
|
246
|
+
|
247
|
+
def generate_value_method(value, configured_value_method)
|
248
|
+
return if configured_value_method == false
|
249
|
+
|
250
|
+
value_method_name = configured_value_method || value.graphql_name.downcase
|
251
|
+
|
252
|
+
if respond_to?(value_method_name.to_sym)
|
253
|
+
warn "Failed to define value method for :#{value_method_name}, because " \
|
254
|
+
"#{value.owner.name || value.owner.graphql_name} already responds to that method. Use `value_method:` to override the method name " \
|
255
|
+
"or `value_method: false` to disable Enum value method generation."
|
256
|
+
return
|
257
|
+
end
|
258
|
+
|
259
|
+
define_singleton_method(value_method_name) { value.graphql_name }
|
260
|
+
end
|
226
261
|
end
|
227
262
|
|
228
263
|
enum_value_class(GraphQL::Schema::EnumValue)
|
@@ -12,7 +12,7 @@ module GraphQL
|
|
12
12
|
if ret_type.respond_to?(:scope_items)
|
13
13
|
scoped_items = ret_type.scope_items(value, context)
|
14
14
|
if !scoped_items.equal?(value) && !ret_type.reauthorize_scoped_objects
|
15
|
-
if (current_runtime_state =
|
15
|
+
if (current_runtime_state = Fiber[:__graphql_runtime_info]) &&
|
16
16
|
(query_runtime_state = current_runtime_state[context.query])
|
17
17
|
query_runtime_state.was_authorized_by_scope_items = true
|
18
18
|
end
|