graphql 2.0.13 → 2.3.10
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/install/mutation_root_generator.rb +2 -2
- data/lib/generators/graphql/install/templates/base_mutation.erb +2 -0
- data/lib/generators/graphql/install/templates/mutation_type.erb +2 -0
- data/lib/generators/graphql/install_generator.rb +3 -0
- data/lib/generators/graphql/mutation_delete_generator.rb +1 -1
- data/lib/generators/graphql/mutation_update_generator.rb +1 -1
- data/lib/generators/graphql/relay.rb +18 -1
- data/lib/generators/graphql/templates/base_argument.erb +2 -0
- data/lib/generators/graphql/templates/base_connection.erb +2 -0
- data/lib/generators/graphql/templates/base_edge.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_object.erb +2 -0
- data/lib/generators/graphql/templates/base_resolver.erb +6 -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/graphql_controller.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/node_type.erb +2 -0
- data/lib/generators/graphql/templates/query_type.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +8 -0
- data/lib/graphql/analysis/analyzer.rb +89 -0
- data/lib/graphql/analysis/field_usage.rb +82 -0
- data/lib/graphql/analysis/max_query_complexity.rb +20 -0
- data/lib/graphql/analysis/max_query_depth.rb +20 -0
- data/lib/graphql/analysis/query_complexity.rb +183 -0
- data/lib/graphql/analysis/query_depth.rb +58 -0
- data/lib/graphql/analysis/visitor.rb +283 -0
- data/lib/graphql/analysis.rb +92 -1
- data/lib/graphql/backtrace/inspect_result.rb +0 -12
- data/lib/graphql/backtrace/table.rb +2 -2
- data/lib/graphql/backtrace/trace.rb +93 -0
- data/lib/graphql/backtrace/tracer.rb +1 -1
- data/lib/graphql/backtrace.rb +2 -1
- data/lib/graphql/coercion_error.rb +1 -9
- data/lib/graphql/dataloader/async_dataloader.rb +88 -0
- data/lib/graphql/dataloader/null_dataloader.rb +1 -1
- data/lib/graphql/dataloader/request.rb +5 -0
- data/lib/graphql/dataloader/source.rb +89 -45
- data/lib/graphql/dataloader.rb +115 -142
- data/lib/graphql/duration_encoding_error.rb +16 -0
- data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
- data/lib/graphql/execution/interpreter/arguments.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +33 -33
- data/lib/graphql/execution/interpreter/resolve.rb +19 -0
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +175 -0
- data/lib/graphql/execution/interpreter/runtime.rb +331 -455
- data/lib/graphql/execution/interpreter.rb +125 -61
- data/lib/graphql/execution/lazy.rb +6 -12
- data/lib/graphql/execution/lookahead.rb +124 -46
- data/lib/graphql/execution/multiplex.rb +3 -117
- data/lib/graphql/execution.rb +0 -1
- data/lib/graphql/introspection/directive_type.rb +3 -3
- data/lib/graphql/introspection/dynamic_fields.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +11 -5
- data/lib/graphql/introspection/field_type.rb +2 -2
- data/lib/graphql/introspection/schema_type.rb +10 -13
- data/lib/graphql/introspection/type_type.rb +17 -10
- data/lib/graphql/introspection.rb +3 -2
- data/lib/graphql/language/block_string.rb +34 -18
- data/lib/graphql/language/definition_slice.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +75 -59
- data/lib/graphql/language/lexer.rb +358 -1506
- data/lib/graphql/language/nodes.rb +166 -93
- data/lib/graphql/language/parser.rb +795 -1953
- data/lib/graphql/language/printer.rb +340 -160
- data/lib/graphql/language/sanitized_printer.rb +21 -23
- data/lib/graphql/language/static_visitor.rb +167 -0
- data/lib/graphql/language/visitor.rb +188 -141
- data/lib/graphql/language.rb +61 -1
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
- data/lib/graphql/pagination/array_connection.rb +6 -6
- data/lib/graphql/pagination/connection.rb +33 -6
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
- data/lib/graphql/query/context/scoped_context.rb +101 -0
- data/lib/graphql/query/context.rb +117 -112
- data/lib/graphql/query/null_context.rb +12 -25
- data/lib/graphql/query/validation_pipeline.rb +6 -5
- data/lib/graphql/query/variables.rb +3 -3
- data/lib/graphql/query.rb +86 -30
- data/lib/graphql/railtie.rb +9 -6
- data/lib/graphql/rake_task.rb +29 -11
- data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
- data/lib/graphql/schema/addition.rb +59 -23
- data/lib/graphql/schema/always_visible.rb +11 -0
- data/lib/graphql/schema/argument.rb +55 -26
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +56 -32
- data/lib/graphql/schema/directive/one_of.rb +24 -0
- data/lib/graphql/schema/directive/specified_by.rb +14 -0
- data/lib/graphql/schema/directive/transform.rb +1 -1
- data/lib/graphql/schema/directive.rb +15 -3
- data/lib/graphql/schema/enum.rb +35 -24
- data/lib/graphql/schema/enum_value.rb +2 -3
- data/lib/graphql/schema/field/connection_extension.rb +2 -16
- data/lib/graphql/schema/field/scope_extension.rb +8 -1
- data/lib/graphql/schema/field.rb +147 -107
- data/lib/graphql/schema/field_extension.rb +1 -4
- data/lib/graphql/schema/find_inherited_value.rb +2 -7
- data/lib/graphql/schema/has_single_input_argument.rb +158 -0
- data/lib/graphql/schema/input_object.rb +47 -11
- data/lib/graphql/schema/interface.rb +15 -21
- data/lib/graphql/schema/introspection_system.rb +7 -17
- data/lib/graphql/schema/late_bound_type.rb +10 -0
- data/lib/graphql/schema/list.rb +2 -2
- data/lib/graphql/schema/loader.rb +2 -3
- data/lib/graphql/schema/member/base_dsl_methods.rb +18 -14
- data/lib/graphql/schema/member/build_type.rb +11 -3
- data/lib/graphql/schema/member/has_arguments.rb +170 -130
- data/lib/graphql/schema/member/has_ast_node.rb +12 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
- data/lib/graphql/schema/member/has_directives.rb +81 -61
- data/lib/graphql/schema/member/has_fields.rb +100 -38
- data/lib/graphql/schema/member/has_interfaces.rb +65 -10
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
- data/lib/graphql/schema/member/has_validators.rb +32 -6
- data/lib/graphql/schema/member/relay_shortcuts.rb +19 -0
- data/lib/graphql/schema/member/scoped.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +16 -0
- data/lib/graphql/schema/member/validates_input.rb +3 -3
- data/lib/graphql/schema/mutation.rb +7 -0
- data/lib/graphql/schema/object.rb +16 -5
- data/lib/graphql/schema/printer.rb +11 -8
- data/lib/graphql/schema/relay_classic_mutation.rb +7 -129
- data/lib/graphql/schema/resolver/has_payload_type.rb +9 -9
- data/lib/graphql/schema/resolver.rb +47 -32
- data/lib/graphql/schema/scalar.rb +3 -3
- data/lib/graphql/schema/subscription.rb +11 -4
- data/lib/graphql/schema/subset.rb +397 -0
- data/lib/graphql/schema/timeout.rb +25 -29
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/type_membership.rb +3 -0
- data/lib/graphql/schema/union.rb +11 -2
- data/lib/graphql/schema/unique_within_type.rb +1 -1
- data/lib/graphql/schema/validator/all_validator.rb +60 -0
- data/lib/graphql/schema/validator.rb +4 -2
- data/lib/graphql/schema/warden.rb +238 -93
- data/lib/graphql/schema.rb +498 -103
- data/lib/graphql/static_validation/all_rules.rb +2 -1
- data/lib/graphql/static_validation/base_visitor.rb +7 -6
- data/lib/graphql/static_validation/definition_dependencies.rb +7 -1
- data/lib/graphql/static_validation/literal_validator.rb +24 -7
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -2
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +10 -10
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
- data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -4
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
- 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 +5 -5
- data/lib/graphql/static_validation/validator.rb +4 -1
- data/lib/graphql/static_validation.rb +0 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +11 -4
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
- data/lib/graphql/subscriptions/event.rb +11 -10
- data/lib/graphql/subscriptions/serialize.rb +2 -0
- data/lib/graphql/subscriptions.rb +20 -13
- data/lib/graphql/testing/helpers.rb +151 -0
- data/lib/graphql/testing.rb +2 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
- data/lib/graphql/tracing/appoptics_trace.rb +251 -0
- data/lib/graphql/tracing/appoptics_tracing.rb +2 -2
- data/lib/graphql/tracing/appsignal_trace.rb +77 -0
- data/lib/graphql/tracing/data_dog_trace.rb +183 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +9 -21
- data/lib/graphql/{execution/instrumentation.rb → tracing/legacy_hooks_trace.rb} +10 -28
- data/lib/graphql/tracing/legacy_trace.rb +69 -0
- data/lib/graphql/tracing/new_relic_trace.rb +75 -0
- data/lib/graphql/tracing/notifications_trace.rb +45 -0
- data/lib/graphql/tracing/platform_trace.rb +118 -0
- data/lib/graphql/tracing/platform_tracing.rb +17 -3
- data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +4 -2
- data/lib/graphql/tracing/prometheus_trace.rb +89 -0
- data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
- data/lib/graphql/tracing/scout_trace.rb +72 -0
- data/lib/graphql/tracing/sentry_trace.rb +112 -0
- data/lib/graphql/tracing/statsd_trace.rb +56 -0
- data/lib/graphql/tracing/trace.rb +76 -0
- data/lib/graphql/tracing.rb +20 -40
- data/lib/graphql/type_kinds.rb +7 -4
- data/lib/graphql/types/iso_8601_duration.rb +77 -0
- data/lib/graphql/types/relay/base_connection.rb +1 -1
- data/lib/graphql/types/relay/connection_behaviors.rb +68 -6
- data/lib/graphql/types/relay/edge_behaviors.rb +33 -5
- data/lib/graphql/types/relay/node_behaviors.rb +8 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +11 -2
- data/lib/graphql/types/relay.rb +0 -1
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/types.rb +1 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +27 -20
- data/readme.md +13 -3
- metadata +96 -47
- data/lib/graphql/analysis/ast/analyzer.rb +0 -84
- data/lib/graphql/analysis/ast/field_usage.rb +0 -57
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -22
- data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
- data/lib/graphql/analysis/ast/query_complexity.rb +0 -230
- data/lib/graphql/analysis/ast/query_depth.rb +0 -55
- data/lib/graphql/analysis/ast/visitor.rb +0 -269
- data/lib/graphql/analysis/ast.rb +0 -81
- data/lib/graphql/deprecation.rb +0 -9
- data/lib/graphql/filter.rb +0 -53
- data/lib/graphql/language/lexer.rl +0 -280
- data/lib/graphql/language/parser.y +0 -554
- data/lib/graphql/language/token.rb +0 -34
- data/lib/graphql/schema/base_64_bp.rb +0 -26
- data/lib/graphql/schema/invalid_type_error.rb +0 -7
- data/lib/graphql/static_validation/type_stack.rb +0 -216
- data/lib/graphql/subscriptions/instrumentation.rb +0 -28
- data/lib/graphql/types/relay/default_relay.rb +0 -21
@@ -40,7 +40,7 @@ module GraphQL
|
|
40
40
|
case node
|
41
41
|
when FalseClass, Float, Integer, String, TrueClass
|
42
42
|
if @current_argument && redact_argument_value?(@current_argument, node)
|
43
|
-
redacted_argument_value(@current_argument)
|
43
|
+
print_string(redacted_argument_value(@current_argument))
|
44
44
|
else
|
45
45
|
super
|
46
46
|
end
|
@@ -51,9 +51,8 @@ module GraphQL
|
|
51
51
|
@current_input_type = @current_input_type.of_type if @current_input_type.non_null?
|
52
52
|
end
|
53
53
|
|
54
|
-
|
54
|
+
super
|
55
55
|
@current_input_type = old_input_type
|
56
|
-
res
|
57
56
|
else
|
58
57
|
super
|
59
58
|
end
|
@@ -89,11 +88,12 @@ module GraphQL
|
|
89
88
|
else
|
90
89
|
argument.value
|
91
90
|
end
|
92
|
-
|
91
|
+
|
92
|
+
print_string("#{argument.name}: ")
|
93
|
+
print_node(argument_value)
|
93
94
|
|
94
95
|
@current_input_type = old_input_type
|
95
96
|
@current_argument = old_current_argument
|
96
|
-
res
|
97
97
|
end
|
98
98
|
|
99
99
|
def coerce_argument_value_to_list?(type, value)
|
@@ -113,12 +113,11 @@ module GraphQL
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def print_field(field, indent: "")
|
116
|
-
@current_field = query.
|
116
|
+
@current_field = query.types.field(@current_type, field.name)
|
117
117
|
old_type = @current_type
|
118
118
|
@current_type = @current_field.type.unwrap
|
119
|
-
|
119
|
+
super
|
120
120
|
@current_type = old_type
|
121
|
-
res
|
122
121
|
end
|
123
122
|
|
124
123
|
def print_inline_fragment(inline_fragment, indent: "")
|
@@ -128,31 +127,26 @@ module GraphQL
|
|
128
127
|
@current_type = query.get_type(inline_fragment.type.name)
|
129
128
|
end
|
130
129
|
|
131
|
-
|
130
|
+
super
|
132
131
|
|
133
132
|
@current_type = old_type
|
134
|
-
|
135
|
-
res
|
136
133
|
end
|
137
134
|
|
138
135
|
def print_fragment_definition(fragment_def, indent: "")
|
139
136
|
old_type = @current_type
|
140
137
|
@current_type = query.get_type(fragment_def.type.name)
|
141
138
|
|
142
|
-
|
139
|
+
super
|
143
140
|
|
144
141
|
@current_type = old_type
|
145
|
-
|
146
|
-
res
|
147
142
|
end
|
148
143
|
|
149
144
|
def print_directive(directive)
|
150
145
|
@current_directive = query.schema.directives[directive.name]
|
151
146
|
|
152
|
-
|
147
|
+
super
|
153
148
|
|
154
149
|
@current_directive = nil
|
155
|
-
res
|
156
150
|
end
|
157
151
|
|
158
152
|
# Print the operation definition but do not include the variable
|
@@ -162,16 +156,15 @@ module GraphQL
|
|
162
156
|
@current_type = query.schema.public_send(operation_definition.operation_type)
|
163
157
|
|
164
158
|
if @inline_variables
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
159
|
+
print_string("#{indent}#{operation_definition.operation_type}")
|
160
|
+
print_string(" #{operation_definition.name}") if operation_definition.name
|
161
|
+
print_directives(operation_definition.directives)
|
162
|
+
print_selections(operation_definition.selections, indent: indent)
|
169
163
|
else
|
170
|
-
|
164
|
+
super
|
171
165
|
end
|
172
166
|
|
173
167
|
@current_type = old_type
|
174
|
-
out
|
175
168
|
end
|
176
169
|
|
177
170
|
private
|
@@ -210,7 +203,12 @@ module GraphQL
|
|
210
203
|
[value].map { |v| value_to_ast(v, type.of_type) }
|
211
204
|
end
|
212
205
|
when "ENUM"
|
213
|
-
GraphQL::Language::Nodes::Enum
|
206
|
+
if value.is_a?(GraphQL::Language::Nodes::Enum)
|
207
|
+
# if it was a default value, it's already wrapped
|
208
|
+
value
|
209
|
+
else
|
210
|
+
GraphQL::Language::Nodes::Enum.new(name: value)
|
211
|
+
end
|
214
212
|
else
|
215
213
|
value
|
216
214
|
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Language
|
4
|
+
# Like `GraphQL::Language::Visitor` except it doesn't support
|
5
|
+
# making changes to the document -- only visiting it as-is.
|
6
|
+
class StaticVisitor
|
7
|
+
def initialize(document)
|
8
|
+
@document = document
|
9
|
+
end
|
10
|
+
|
11
|
+
# Visit `document` and all children
|
12
|
+
# @return [void]
|
13
|
+
def visit
|
14
|
+
# `@document` may be any kind of node:
|
15
|
+
visit_method = @document.visit_method
|
16
|
+
result = public_send(visit_method, @document, nil)
|
17
|
+
@result = if result.is_a?(Array)
|
18
|
+
result.first
|
19
|
+
else
|
20
|
+
# The node wasn't modified
|
21
|
+
@document
|
22
|
+
end
|
23
|
+
end
|
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
|
+
def on_document_children(document_node)
|
59
|
+
document_node.children.each do |child_node|
|
60
|
+
visit_method = child_node.visit_method
|
61
|
+
public_send(visit_method, child_node, document_node)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def on_field_children(new_node)
|
66
|
+
new_node.arguments.each do |arg_node| # rubocop:disable Development/ContextIsPassedCop
|
67
|
+
on_argument(arg_node, new_node)
|
68
|
+
end
|
69
|
+
visit_directives(new_node)
|
70
|
+
visit_selections(new_node)
|
71
|
+
end
|
72
|
+
|
73
|
+
def visit_directives(new_node)
|
74
|
+
new_node.directives.each do |dir_node|
|
75
|
+
on_directive(dir_node, new_node)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def visit_selections(new_node)
|
80
|
+
new_node.selections.each do |selection|
|
81
|
+
case selection
|
82
|
+
when GraphQL::Language::Nodes::Field
|
83
|
+
on_field(selection, new_node)
|
84
|
+
when GraphQL::Language::Nodes::InlineFragment
|
85
|
+
on_inline_fragment(selection, new_node)
|
86
|
+
when GraphQL::Language::Nodes::FragmentSpread
|
87
|
+
on_fragment_spread(selection, new_node)
|
88
|
+
else
|
89
|
+
raise ArgumentError, "Invariant: unexpected field selection #{selection.class} (#{selection.inspect})"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def on_fragment_definition_children(new_node)
|
95
|
+
visit_directives(new_node)
|
96
|
+
visit_selections(new_node)
|
97
|
+
end
|
98
|
+
|
99
|
+
alias :on_inline_fragment_children :on_fragment_definition_children
|
100
|
+
|
101
|
+
def on_operation_definition_children(new_node)
|
102
|
+
new_node.variables.each do |arg_node|
|
103
|
+
on_variable_definition(arg_node, new_node)
|
104
|
+
end
|
105
|
+
visit_directives(new_node)
|
106
|
+
visit_selections(new_node)
|
107
|
+
end
|
108
|
+
|
109
|
+
def on_argument_children(new_node)
|
110
|
+
new_node.children.each do |value_node|
|
111
|
+
case value_node
|
112
|
+
when Language::Nodes::VariableIdentifier
|
113
|
+
on_variable_identifier(value_node, new_node)
|
114
|
+
when Language::Nodes::InputObject
|
115
|
+
on_input_object(value_node, new_node)
|
116
|
+
when Language::Nodes::Enum
|
117
|
+
on_enum(value_node, new_node)
|
118
|
+
when Language::Nodes::NullValue
|
119
|
+
on_null_value(value_node, new_node)
|
120
|
+
else
|
121
|
+
raise ArgumentError, "Invariant: unexpected argument value node #{value_node.class} (#{value_node.inspect})"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
[
|
127
|
+
Language::Nodes::Argument,
|
128
|
+
Language::Nodes::Directive,
|
129
|
+
Language::Nodes::DirectiveDefinition,
|
130
|
+
Language::Nodes::DirectiveLocation,
|
131
|
+
Language::Nodes::Document,
|
132
|
+
Language::Nodes::Enum,
|
133
|
+
Language::Nodes::EnumTypeDefinition,
|
134
|
+
Language::Nodes::EnumTypeExtension,
|
135
|
+
Language::Nodes::EnumValueDefinition,
|
136
|
+
Language::Nodes::Field,
|
137
|
+
Language::Nodes::FieldDefinition,
|
138
|
+
Language::Nodes::FragmentDefinition,
|
139
|
+
Language::Nodes::FragmentSpread,
|
140
|
+
Language::Nodes::InlineFragment,
|
141
|
+
Language::Nodes::InputObject,
|
142
|
+
Language::Nodes::InputObjectTypeDefinition,
|
143
|
+
Language::Nodes::InputObjectTypeExtension,
|
144
|
+
Language::Nodes::InputValueDefinition,
|
145
|
+
Language::Nodes::InterfaceTypeDefinition,
|
146
|
+
Language::Nodes::InterfaceTypeExtension,
|
147
|
+
Language::Nodes::ListType,
|
148
|
+
Language::Nodes::NonNullType,
|
149
|
+
Language::Nodes::NullValue,
|
150
|
+
Language::Nodes::ObjectTypeDefinition,
|
151
|
+
Language::Nodes::ObjectTypeExtension,
|
152
|
+
Language::Nodes::OperationDefinition,
|
153
|
+
Language::Nodes::ScalarTypeDefinition,
|
154
|
+
Language::Nodes::ScalarTypeExtension,
|
155
|
+
Language::Nodes::SchemaDefinition,
|
156
|
+
Language::Nodes::SchemaExtension,
|
157
|
+
Language::Nodes::TypeName,
|
158
|
+
Language::Nodes::UnionTypeDefinition,
|
159
|
+
Language::Nodes::UnionTypeExtension,
|
160
|
+
Language::Nodes::VariableDefinition,
|
161
|
+
Language::Nodes::VariableIdentifier,
|
162
|
+
].each do |ast_node_class|
|
163
|
+
make_visit_methods(ast_node_class)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -30,12 +30,9 @@ module GraphQL
|
|
30
30
|
# # Check the result
|
31
31
|
# visitor.count
|
32
32
|
# # => 3
|
33
|
+
#
|
34
|
+
# @see GraphQL::Language::StaticVisitor for a faster visitor that doesn't support modifying the document
|
33
35
|
class Visitor
|
34
|
-
# If any hook returns this value, the {Visitor} stops visiting this
|
35
|
-
# node right away
|
36
|
-
# @deprecated Use `super` to continue the visit; or don't call it to halt.
|
37
|
-
SKIP = :_skip
|
38
|
-
|
39
36
|
class DeleteNode; end
|
40
37
|
|
41
38
|
# When this is returned from a visitor method,
|
@@ -44,28 +41,18 @@ module GraphQL
|
|
44
41
|
|
45
42
|
def initialize(document)
|
46
43
|
@document = document
|
47
|
-
@visitors = {}
|
48
44
|
@result = nil
|
49
45
|
end
|
50
46
|
|
51
47
|
# @return [GraphQL::Language::Nodes::Document] The document with any modifications applied
|
52
48
|
attr_reader :result
|
53
49
|
|
54
|
-
#
|
55
|
-
# @param node_class [Class] The node class that you want to listen to
|
56
|
-
# @return [NodeVisitor]
|
57
|
-
#
|
58
|
-
# @example Run a hook whenever you enter a new Field
|
59
|
-
# visitor[GraphQL::Language::Nodes::Field] << ->(node, parent) { p "Here's a field" }
|
60
|
-
# @deprecated see `on_` methods, like {#on_field}
|
61
|
-
def [](node_class)
|
62
|
-
@visitors[node_class] ||= NodeVisitor.new
|
63
|
-
end
|
64
|
-
|
65
|
-
# Visit `document` and all children, applying hooks as you go
|
50
|
+
# Visit `document` and all children
|
66
51
|
# @return [void]
|
67
52
|
def visit
|
68
|
-
|
53
|
+
# `@document` may be any kind of node:
|
54
|
+
visit_method = :"#{@document.visit_method}_with_modifications"
|
55
|
+
result = public_send(visit_method, @document, nil)
|
69
56
|
@result = if result.is_a?(Array)
|
70
57
|
result.first
|
71
58
|
else
|
@@ -74,104 +61,204 @@ module GraphQL
|
|
74
61
|
end
|
75
62
|
end
|
76
63
|
|
77
|
-
#
|
78
|
-
def
|
79
|
-
|
80
|
-
|
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"
|
81
69
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
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]
|
106
108
|
end
|
107
109
|
end
|
108
110
|
end
|
109
|
-
end_visit(new_node, parent) unless no_hooks
|
110
111
|
|
111
|
-
|
112
|
-
|
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
|
+
def on_document_children(document_node)
|
120
|
+
new_node = document_node
|
121
|
+
document_node.children.each do |child_node|
|
122
|
+
visit_method = :"#{child_node.visit_method}_with_modifications"
|
123
|
+
new_child_and_node = public_send(visit_method, child_node, new_node)
|
124
|
+
# Reassign `node` in case the child hook makes a modification
|
125
|
+
if new_child_and_node.is_a?(Array)
|
126
|
+
new_node = new_child_and_node[1]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
new_node
|
130
|
+
end
|
131
|
+
|
132
|
+
def on_field_children(new_node)
|
133
|
+
new_node.arguments.each do |arg_node| # rubocop:disable Development/ContextIsPassedCop
|
134
|
+
new_child_and_node = on_argument_with_modifications(arg_node, new_node)
|
135
|
+
# Reassign `node` in case the child hook makes a modification
|
136
|
+
if new_child_and_node.is_a?(Array)
|
137
|
+
new_node = new_child_and_node[1]
|
138
|
+
end
|
139
|
+
end
|
140
|
+
new_node = visit_directives(new_node)
|
141
|
+
new_node = visit_selections(new_node)
|
142
|
+
new_node
|
143
|
+
end
|
144
|
+
|
145
|
+
def visit_directives(new_node)
|
146
|
+
new_node.directives.each do |dir_node|
|
147
|
+
new_child_and_node = on_directive_with_modifications(dir_node, new_node)
|
148
|
+
# Reassign `node` in case the child hook makes a modification
|
149
|
+
if new_child_and_node.is_a?(Array)
|
150
|
+
new_node = new_child_and_node[1]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
new_node
|
154
|
+
end
|
155
|
+
|
156
|
+
def visit_selections(new_node)
|
157
|
+
new_node.selections.each do |selection|
|
158
|
+
new_child_and_node = case selection
|
159
|
+
when GraphQL::Language::Nodes::Field
|
160
|
+
on_field_with_modifications(selection, new_node)
|
161
|
+
when GraphQL::Language::Nodes::InlineFragment
|
162
|
+
on_inline_fragment_with_modifications(selection, new_node)
|
163
|
+
when GraphQL::Language::Nodes::FragmentSpread
|
164
|
+
on_fragment_spread_with_modifications(selection, new_node)
|
113
165
|
else
|
114
|
-
|
166
|
+
raise ArgumentError, "Invariant: unexpected field selection #{selection.class} (#{selection.inspect})"
|
167
|
+
end
|
168
|
+
# Reassign `node` in case the child hook makes a modification
|
169
|
+
if new_child_and_node.is_a?(Array)
|
170
|
+
new_node = new_child_and_node[1]
|
115
171
|
end
|
116
172
|
end
|
173
|
+
new_node
|
117
174
|
end
|
118
175
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
176
|
+
def on_fragment_definition_children(new_node)
|
177
|
+
new_node = visit_directives(new_node)
|
178
|
+
new_node = visit_selections(new_node)
|
179
|
+
new_node
|
180
|
+
end
|
181
|
+
|
182
|
+
alias :on_inline_fragment_children :on_fragment_definition_children
|
183
|
+
|
184
|
+
def on_operation_definition_children(new_node)
|
185
|
+
new_node.variables.each do |arg_node|
|
186
|
+
new_child_and_node = on_variable_definition_with_modifications(arg_node, new_node)
|
187
|
+
# Reassign `node` in case the child hook makes a modification
|
188
|
+
if new_child_and_node.is_a?(Array)
|
189
|
+
new_node = new_child_and_node[1]
|
126
190
|
end
|
127
|
-
|
191
|
+
end
|
192
|
+
new_node = visit_directives(new_node)
|
193
|
+
new_node = visit_selections(new_node)
|
194
|
+
new_node
|
128
195
|
end
|
129
196
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
197
|
+
def on_argument_children(new_node)
|
198
|
+
new_node.children.each do |value_node|
|
199
|
+
new_child_and_node = case value_node
|
200
|
+
when Language::Nodes::VariableIdentifier
|
201
|
+
on_variable_identifier_with_modifications(value_node, new_node)
|
202
|
+
when Language::Nodes::InputObject
|
203
|
+
on_input_object_with_modifications(value_node, new_node)
|
204
|
+
when Language::Nodes::Enum
|
205
|
+
on_enum_with_modifications(value_node, new_node)
|
206
|
+
when Language::Nodes::NullValue
|
207
|
+
on_null_value_with_modifications(value_node, new_node)
|
208
|
+
else
|
209
|
+
raise ArgumentError, "Invariant: unexpected argument value node #{value_node.class} (#{value_node.inspect})"
|
210
|
+
end
|
211
|
+
# Reassign `node` in case the child hook makes a modification
|
212
|
+
if new_child_and_node.is_a?(Array)
|
213
|
+
new_node = new_child_and_node[1]
|
214
|
+
end
|
215
|
+
end
|
216
|
+
new_node
|
217
|
+
end
|
218
|
+
|
219
|
+
[
|
220
|
+
Language::Nodes::Argument,
|
221
|
+
Language::Nodes::Directive,
|
222
|
+
Language::Nodes::DirectiveDefinition,
|
223
|
+
Language::Nodes::DirectiveLocation,
|
224
|
+
Language::Nodes::Document,
|
225
|
+
Language::Nodes::Enum,
|
226
|
+
Language::Nodes::EnumTypeDefinition,
|
227
|
+
Language::Nodes::EnumTypeExtension,
|
228
|
+
Language::Nodes::EnumValueDefinition,
|
229
|
+
Language::Nodes::Field,
|
230
|
+
Language::Nodes::FieldDefinition,
|
231
|
+
Language::Nodes::FragmentDefinition,
|
232
|
+
Language::Nodes::FragmentSpread,
|
233
|
+
Language::Nodes::InlineFragment,
|
234
|
+
Language::Nodes::InputObject,
|
235
|
+
Language::Nodes::InputObjectTypeDefinition,
|
236
|
+
Language::Nodes::InputObjectTypeExtension,
|
237
|
+
Language::Nodes::InputValueDefinition,
|
238
|
+
Language::Nodes::InterfaceTypeDefinition,
|
239
|
+
Language::Nodes::InterfaceTypeExtension,
|
240
|
+
Language::Nodes::ListType,
|
241
|
+
Language::Nodes::NonNullType,
|
242
|
+
Language::Nodes::NullValue,
|
243
|
+
Language::Nodes::ObjectTypeDefinition,
|
244
|
+
Language::Nodes::ObjectTypeExtension,
|
245
|
+
Language::Nodes::OperationDefinition,
|
246
|
+
Language::Nodes::ScalarTypeDefinition,
|
247
|
+
Language::Nodes::ScalarTypeExtension,
|
248
|
+
Language::Nodes::SchemaDefinition,
|
249
|
+
Language::Nodes::SchemaExtension,
|
250
|
+
Language::Nodes::TypeName,
|
251
|
+
Language::Nodes::UnionTypeDefinition,
|
252
|
+
Language::Nodes::UnionTypeExtension,
|
253
|
+
Language::Nodes::VariableDefinition,
|
254
|
+
Language::Nodes::VariableIdentifier,
|
255
|
+
].each do |ast_node_class|
|
256
|
+
make_visit_methods(ast_node_class)
|
257
|
+
end
|
165
258
|
|
166
259
|
private
|
167
260
|
|
168
|
-
|
169
|
-
# copy `parent` so that it contains the copy of that node as a child,
|
170
|
-
# then return the copies
|
171
|
-
# If a non-array value is returned, consuming functions should ignore
|
172
|
-
# said value
|
173
|
-
def on_node_with_modifications(node, parent)
|
174
|
-
new_node_and_new_parent = visit_node(node, parent)
|
261
|
+
def apply_modifications(node, parent, new_node_and_new_parent)
|
175
262
|
if new_node_and_new_parent.is_a?(Array)
|
176
263
|
new_node = new_node_and_new_parent[0]
|
177
264
|
new_parent = new_node_and_new_parent[1]
|
@@ -197,46 +284,6 @@ module GraphQL
|
|
197
284
|
new_node_and_new_parent
|
198
285
|
end
|
199
286
|
end
|
200
|
-
|
201
|
-
def begin_visit(node, parent)
|
202
|
-
node_visitor = self[node.class]
|
203
|
-
self.class.apply_hooks(node_visitor.enter, node, parent)
|
204
|
-
end
|
205
|
-
|
206
|
-
# Should global `leave` visitors come first or last?
|
207
|
-
def end_visit(node, parent)
|
208
|
-
node_visitor = self[node.class]
|
209
|
-
self.class.apply_hooks(node_visitor.leave, node, parent)
|
210
|
-
end
|
211
|
-
|
212
|
-
# If one of the visitors returns SKIP, stop visiting this node
|
213
|
-
def self.apply_hooks(hooks, node, parent)
|
214
|
-
hooks.each do |proc|
|
215
|
-
return false if proc.call(node, parent) == SKIP
|
216
|
-
end
|
217
|
-
true
|
218
|
-
end
|
219
|
-
|
220
|
-
# Collect `enter` and `leave` hooks for classes in {GraphQL::Language::Nodes}
|
221
|
-
#
|
222
|
-
# Access {NodeVisitor}s via {GraphQL::Language::Visitor#[]}
|
223
|
-
class NodeVisitor
|
224
|
-
# @return [Array<Proc>] Hooks to call when entering a node of this type
|
225
|
-
attr_reader :enter
|
226
|
-
# @return [Array<Proc>] Hooks to call when leaving a node of this type
|
227
|
-
attr_reader :leave
|
228
|
-
|
229
|
-
def initialize
|
230
|
-
@enter = []
|
231
|
-
@leave = []
|
232
|
-
end
|
233
|
-
|
234
|
-
# Shorthand to add a hook to the {#enter} array
|
235
|
-
# @param hook [Proc] A hook to add
|
236
|
-
def <<(hook)
|
237
|
-
enter << hook
|
238
|
-
end
|
239
|
-
end
|
240
287
|
end
|
241
288
|
end
|
242
289
|
end
|