graphql 2.3.22 → 2.4.0
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/graphql/analysis/analyzer.rb +1 -2
- data/lib/graphql/analysis/visitor.rb +0 -2
- data/lib/graphql/language/nodes.rb +0 -3
- data/lib/graphql/language/static_visitor.rb +33 -37
- data/lib/graphql/language/visitor.rb +55 -59
- data/lib/graphql/schema/argument.rb +5 -3
- data/lib/graphql/schema/build_from_definition.rb +7 -8
- data/lib/graphql/schema/directive.rb +1 -1
- data/lib/graphql/schema/enum_value.rb +1 -1
- data/lib/graphql/schema/field.rb +2 -2
- data/lib/graphql/schema/input_object.rb +7 -6
- data/lib/graphql/schema/interface.rb +1 -1
- data/lib/graphql/schema/member/has_directives.rb +1 -1
- data/lib/graphql/schema/member/has_fields.rb +1 -1
- data/lib/graphql/schema/member/has_interfaces.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/printer.rb +1 -0
- data/lib/graphql/schema/visibility/migration.rb +1 -0
- data/lib/graphql/schema/warden.rb +63 -1
- data/lib/graphql/schema.rb +15 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +2 -1
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +2 -1
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +2 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +1 -1
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +11 -1
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +10 -1
- data/lib/graphql/static_validation/validation_context.rb +15 -0
- data/lib/graphql/tracing/appoptics_trace.rb +0 -4
- data/lib/graphql/tracing/appsignal_trace.rb +0 -4
- data/lib/graphql/tracing/data_dog_trace.rb +0 -4
- data/lib/graphql/tracing/notifications_trace.rb +0 -4
- data/lib/graphql/tracing/platform_trace.rb +0 -5
- data/lib/graphql/tracing/prometheus_trace.rb +0 -4
- data/lib/graphql/tracing/scout_trace.rb +0 -3
- data/lib/graphql/tracing/sentry_trace.rb +0 -4
- data/lib/graphql/tracing/statsd_trace.rb +0 -4
- data/lib/graphql/types/relay/connection_behaviors.rb +1 -1
- data/lib/graphql/types/relay/edge_behaviors.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 26e43b0bc48317698ed17f8a11498c19a7a4a0df9d33fdc9785edc47ae1147b6
|
4
|
+
data.tar.gz: 74402e930ebe03a451bc2bdb82285642aeeba7222ab491dd9329400fc852eb41
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1d97c4397ca8410f6b62c3ea2de9a0a4b18ca610adcb92de9676c5377b00a071cbff4fbd0396760eea9ab359e4b0b8cdfff1630c9fa83de51cfd31b0b96307f
|
7
|
+
data.tar.gz: d9250a9ad1d57f40e7b0151484f77a66e11a361f8b0f50938f42219eb8322a9b4dc59c59102f4b49f62a28e90f03b8f9e0cf5b2799b5fd5080dbcf443cebac15
|
@@ -42,7 +42,6 @@ module GraphQL
|
|
42
42
|
raise GraphQL::RequiredImplementationMissingError
|
43
43
|
end
|
44
44
|
|
45
|
-
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
46
45
|
class << self
|
47
46
|
private
|
48
47
|
|
@@ -73,7 +72,7 @@ module GraphQL
|
|
73
72
|
build_visitor_hooks :variable_definition
|
74
73
|
build_visitor_hooks :variable_identifier
|
75
74
|
build_visitor_hooks :abstract_node
|
76
|
-
|
75
|
+
|
77
76
|
protected
|
78
77
|
|
79
78
|
# @return [GraphQL::Query, GraphQL::Execution::Multiplex] Whatever this analyzer is analyzing
|
@@ -64,7 +64,6 @@ module GraphQL
|
|
64
64
|
@response_path.dup
|
65
65
|
end
|
66
66
|
|
67
|
-
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
68
67
|
# Visitor Hooks
|
69
68
|
[
|
70
69
|
:operation_definition, :fragment_definition,
|
@@ -93,7 +92,6 @@ module GraphQL
|
|
93
92
|
|
94
93
|
RUBY
|
95
94
|
end
|
96
|
-
# rubocop:enable Development/NoEvalCop
|
97
95
|
|
98
96
|
def on_operation_definition(node, parent)
|
99
97
|
object_type = @schema.root_type_for_operation(node.operation_type)
|
@@ -141,8 +141,6 @@ module GraphQL
|
|
141
141
|
end
|
142
142
|
|
143
143
|
class << self
|
144
|
-
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
145
|
-
|
146
144
|
# Add a default `#visit_method` and `#children_method_name` using the class name
|
147
145
|
def inherited(child_class)
|
148
146
|
super
|
@@ -345,7 +343,6 @@ module GraphQL
|
|
345
343
|
RUBY
|
346
344
|
end
|
347
345
|
end
|
348
|
-
# rubocop:enable Development/NoEvalCop
|
349
346
|
end
|
350
347
|
end
|
351
348
|
|
@@ -22,6 +22,39 @@ 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
|
+
|
25
58
|
def on_document_children(document_node)
|
26
59
|
document_node.children.each do |child_node|
|
27
60
|
visit_method = child_node.visit_method
|
@@ -90,41 +123,6 @@ module GraphQL
|
|
90
123
|
end
|
91
124
|
end
|
92
125
|
|
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
|
-
|
128
126
|
[
|
129
127
|
Language::Nodes::Argument,
|
130
128
|
Language::Nodes::Directive,
|
@@ -164,8 +162,6 @@ module GraphQL
|
|
164
162
|
].each do |ast_node_class|
|
165
163
|
make_visit_methods(ast_node_class)
|
166
164
|
end
|
167
|
-
|
168
|
-
# rubocop:disable Development/NoEvalCop
|
169
165
|
end
|
170
166
|
end
|
171
167
|
end
|
@@ -61,6 +61,61 @@ 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
|
+
|
64
119
|
def on_document_children(document_node)
|
65
120
|
new_node = document_node
|
66
121
|
document_node.children.each do |child_node|
|
@@ -161,63 +216,6 @@ module GraphQL
|
|
161
216
|
new_node
|
162
217
|
end
|
163
218
|
|
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
|
-
|
221
219
|
[
|
222
220
|
Language::Nodes::Argument,
|
223
221
|
Language::Nodes::Directive,
|
@@ -258,8 +256,6 @@ module GraphQL
|
|
258
256
|
make_visit_methods(ast_node_class)
|
259
257
|
end
|
260
258
|
|
261
|
-
# rubocop:enable Development/NoEvalCop
|
262
|
-
|
263
259
|
private
|
264
260
|
|
265
261
|
def apply_modifications(node, parent, new_node_and_new_parent)
|
@@ -53,7 +53,6 @@ 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)
|
57
56
|
@type_expr = type_expr || type
|
58
57
|
@description = desc || description
|
59
58
|
@comment = comment
|
@@ -90,8 +89,11 @@ module GraphQL
|
|
90
89
|
end
|
91
90
|
|
92
91
|
if definition_block
|
93
|
-
|
94
|
-
|
92
|
+
if definition_block.arity == 1
|
93
|
+
instance_exec(self, &definition_block)
|
94
|
+
else
|
95
|
+
instance_eval(&definition_block)
|
96
|
+
end
|
95
97
|
end
|
96
98
|
end
|
97
99
|
|
@@ -467,18 +467,17 @@ module GraphQL
|
|
467
467
|
|
468
468
|
# Don't do this for interfaces
|
469
469
|
if default_resolve
|
470
|
-
|
470
|
+
owner.class_eval <<-RUBY, __FILE__, __LINE__
|
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
|
471
477
|
end
|
472
478
|
end
|
473
479
|
end
|
474
480
|
|
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
|
-
|
482
481
|
def build_resolve_type(lookup_hash, directives, missing_type_handler)
|
483
482
|
resolve_type_proc = nil
|
484
483
|
resolve_type_proc = ->(ast_node) {
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -255,7 +255,7 @@ module GraphQL
|
|
255
255
|
|
256
256
|
@underscored_name = -Member::BuildType.underscore(name_s)
|
257
257
|
@name = -(camelize ? Member::BuildType.camelize(name_s) : name_s)
|
258
|
-
|
258
|
+
|
259
259
|
@description = description
|
260
260
|
@comment = comment
|
261
261
|
@type = @owner_type = @own_validators = @own_directives = @own_arguments = @arguments_statically_coercible = nil # these will be prepared later if necessary
|
@@ -369,7 +369,7 @@ module GraphQL
|
|
369
369
|
if @definition_block.arity == 1
|
370
370
|
@definition_block.call(self)
|
371
371
|
else
|
372
|
-
|
372
|
+
instance_eval(&@definition_block)
|
373
373
|
end
|
374
374
|
self.extensions.each(&:after_define_apply)
|
375
375
|
@call_after_define = true
|
@@ -132,8 +132,14 @@ module GraphQL
|
|
132
132
|
end
|
133
133
|
end
|
134
134
|
# Add a method access
|
135
|
+
method_name = argument_defn.keyword
|
135
136
|
suppress_redefinition_warning do
|
136
|
-
|
137
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
138
|
+
def #{method_name}
|
139
|
+
self[#{method_name.inspect}]
|
140
|
+
end
|
141
|
+
alias_method :#{method_name}, :#{method_name}
|
142
|
+
RUBY
|
137
143
|
end
|
138
144
|
argument_defn
|
139
145
|
end
|
@@ -250,11 +256,6 @@ module GraphQL
|
|
250
256
|
ensure
|
251
257
|
$VERBOSE = verbose
|
252
258
|
end
|
253
|
-
|
254
|
-
def define_accessor_method(method_name)
|
255
|
-
define_method(method_name) { self[method_name] }
|
256
|
-
alias_method(method_name, method_name)
|
257
|
-
end
|
258
259
|
end
|
259
260
|
|
260
261
|
private
|
@@ -29,7 +29,7 @@ module GraphQL
|
|
29
29
|
const_set(:DefinitionMethods, defn_methods_module)
|
30
30
|
extend(self::DefinitionMethods)
|
31
31
|
end
|
32
|
-
self::DefinitionMethods.
|
32
|
+
self::DefinitionMethods.module_eval(&block)
|
33
33
|
end
|
34
34
|
|
35
35
|
# @see {Schema::Warden} hides interfaces without visible implementations
|
@@ -96,6 +96,7 @@ module GraphQL
|
|
96
96
|
end
|
97
97
|
warden_ctx = GraphQL::Query::Context.new(query: context.query, values: warden_ctx_vals)
|
98
98
|
warden_ctx.warden = GraphQL::Schema::Warden.new(schema: warden_schema, context: warden_ctx)
|
99
|
+
warden_ctx.warden.skip_warning = true
|
99
100
|
warden_ctx.types = @warden_types = warden_ctx.warden.visibility_profile
|
100
101
|
end
|
101
102
|
end
|
@@ -19,6 +19,10 @@ module GraphQL
|
|
19
19
|
PassThruWarden
|
20
20
|
end
|
21
21
|
|
22
|
+
def self.use(schema)
|
23
|
+
# no-op
|
24
|
+
end
|
25
|
+
|
22
26
|
# @param visibility_method [Symbol] a Warden method to call for this entry
|
23
27
|
# @param entry [Object, Array<Object>] One or more definitions for a given name in a GraphQL Schema
|
24
28
|
# @param context [GraphQL::Query::Context]
|
@@ -73,6 +77,9 @@ module GraphQL
|
|
73
77
|
@visibility_profile = Warden::VisibilityProfile.new(self)
|
74
78
|
end
|
75
79
|
|
80
|
+
# No-op, but for compatibility:
|
81
|
+
attr_writer :skip_warning
|
82
|
+
|
76
83
|
# @api private
|
77
84
|
module NullVisibilityProfile
|
78
85
|
def self.new(context:, schema:)
|
@@ -187,7 +194,7 @@ module GraphQL
|
|
187
194
|
@mutation = @schema.mutation
|
188
195
|
@subscription = @schema.subscription
|
189
196
|
@context = context
|
190
|
-
@visibility_cache = read_through { |m| schema
|
197
|
+
@visibility_cache = read_through { |m| check_visible(schema, m) }
|
191
198
|
# Initialize all ivars to improve object shape consistency:
|
192
199
|
@types = @visible_types = @reachable_types = @visible_parent_fields =
|
193
200
|
@visible_possible_types = @visible_fields = @visible_arguments = @visible_enum_arrays =
|
@@ -195,8 +202,11 @@ module GraphQL
|
|
195
202
|
@visible_and_reachable_type = @unions = @unfiltered_interfaces =
|
196
203
|
@reachable_type_set = @visibility_profile =
|
197
204
|
nil
|
205
|
+
@skip_warning = schema.plugins.any? { |(plugin, _opts)| plugin == GraphQL::Schema::Warden }
|
198
206
|
end
|
199
207
|
|
208
|
+
attr_writer :skip_warning
|
209
|
+
|
200
210
|
# @return [Hash<String, GraphQL::BaseType>] Visible types in the schema
|
201
211
|
def types
|
202
212
|
@types ||= begin
|
@@ -465,6 +475,58 @@ module GraphQL
|
|
465
475
|
Hash.new { |h, k| h[k] = yield(k) }.compare_by_identity
|
466
476
|
end
|
467
477
|
|
478
|
+
def check_visible(schema, member)
|
479
|
+
if schema.visible?(member, @context)
|
480
|
+
true
|
481
|
+
elsif @skip_warning
|
482
|
+
false
|
483
|
+
else
|
484
|
+
member_s = member.respond_to?(:path) ? member.path : member.inspect
|
485
|
+
member_type = case member
|
486
|
+
when Module
|
487
|
+
if member.respond_to?(:kind)
|
488
|
+
member.kind.name.downcase
|
489
|
+
else
|
490
|
+
""
|
491
|
+
end
|
492
|
+
when GraphQL::Schema::Field
|
493
|
+
"field"
|
494
|
+
when GraphQL::Schema::EnumValue
|
495
|
+
"enum value"
|
496
|
+
when GraphQL::Schema::Argument
|
497
|
+
"argument"
|
498
|
+
else
|
499
|
+
""
|
500
|
+
end
|
501
|
+
|
502
|
+
schema_s = schema.name ? "#{schema.name}'s" : ""
|
503
|
+
schema_name = schema.name ? "#{schema.name}" : "your schema"
|
504
|
+
warn(ADD_WARDEN_WARNING % { schema_s: schema_s, schema_name: schema_name, member: member_s, member_type: member_type })
|
505
|
+
@skip_warning = true # only warn once per query
|
506
|
+
# If there's no schema name, add the backtrace for additional context:
|
507
|
+
if schema_s == ""
|
508
|
+
puts caller.map { |l| " #{l}"}
|
509
|
+
end
|
510
|
+
false
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
ADD_WARDEN_WARNING = <<~WARNING
|
515
|
+
DEPRECATION: %{schema_s} "%{member}" %{member_type} returned `false` for `.visible?` but `GraphQL::Schema::Visibility` isn't configured yet.
|
516
|
+
|
517
|
+
Address this warning by adding:
|
518
|
+
|
519
|
+
use GraphQL::Schema::Visibility
|
520
|
+
|
521
|
+
to the definition for %{schema_name}. (Future GraphQL-Ruby versions won't check `.visible?` methods by default.)
|
522
|
+
|
523
|
+
Alternatively, for legacy behavior, add:
|
524
|
+
|
525
|
+
use GraphQL::Schema::Warden # legacy visibility behavior
|
526
|
+
|
527
|
+
For more information see: https://graphql-ruby.org/authorization/visibility.html
|
528
|
+
WARNING
|
529
|
+
|
468
530
|
def reachable_type_set
|
469
531
|
return @reachable_type_set if @reachable_type_set
|
470
532
|
|
data/lib/graphql/schema.rb
CHANGED
@@ -1162,7 +1162,7 @@ module GraphQL
|
|
1162
1162
|
# @return [Object, nil] The application which `object_id` references, or `nil` if there is no object or the current operation shouldn't have access to the object
|
1163
1163
|
# @see id_from_object which produces these IDs
|
1164
1164
|
def object_from_id(object_id, context)
|
1165
|
-
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.object_from_id(object_id, context) must be implemented to load by ID (tried to load from id `#{
|
1165
|
+
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.object_from_id(object_id, context) must be implemented to load by ID (tried to load from id `#{object_id}`)"
|
1166
1166
|
end
|
1167
1167
|
|
1168
1168
|
# Return a stable ID string for `object` so that it can be refetched later, using {.object_from_id}.
|
@@ -1575,6 +1575,20 @@ module GraphQL
|
|
1575
1575
|
end
|
1576
1576
|
end
|
1577
1577
|
|
1578
|
+
# Returns `DidYouMean` if it's defined.
|
1579
|
+
# Override this to return `nil` if you don't want to use `DidYouMean`
|
1580
|
+
def did_you_mean(new_dym = NOT_CONFIGURED)
|
1581
|
+
if NOT_CONFIGURED.equal?(new_dym)
|
1582
|
+
if defined?(@did_you_mean)
|
1583
|
+
@did_you_mean
|
1584
|
+
else
|
1585
|
+
find_inherited_value(:did_you_mean, defined?(DidYouMean) ? DidYouMean : nil)
|
1586
|
+
end
|
1587
|
+
else
|
1588
|
+
@did_you_mean = new_dym
|
1589
|
+
end
|
1590
|
+
end
|
1591
|
+
|
1578
1592
|
private
|
1579
1593
|
|
1580
1594
|
def add_trace_options_for(mode, new_options)
|
@@ -10,8 +10,9 @@ module GraphQL
|
|
10
10
|
elsif parent_defn
|
11
11
|
kind_of_node = node_type(parent)
|
12
12
|
error_arg_name = parent_name(parent, parent_defn)
|
13
|
+
arg_names = context.types.arguments(parent_defn).map(&:graphql_name)
|
13
14
|
add_error(GraphQL::StaticValidation::ArgumentsAreDefinedError.new(
|
14
|
-
"#{kind_of_node} '#{error_arg_name}' doesn't accept argument '#{node.name}'",
|
15
|
+
"#{kind_of_node} '#{error_arg_name}' doesn't accept argument '#{node.name}'#{context.did_you_mean_suggestion(node.name, arg_names)}",
|
15
16
|
nodes: node,
|
16
17
|
name: error_arg_name,
|
17
18
|
type: kind_of_node,
|
@@ -10,8 +10,9 @@ module GraphQL
|
|
10
10
|
if !@types.directive_exists?(node.name)
|
11
11
|
@directives_are_defined_errors_by_name ||= {}
|
12
12
|
error = @directives_are_defined_errors_by_name[node.name] ||= begin
|
13
|
+
@directive_names ||= @types.directives.map(&:graphql_name)
|
13
14
|
err = GraphQL::StaticValidation::DirectivesAreDefinedError.new(
|
14
|
-
"Directive @#{node.name} is not defined",
|
15
|
+
"Directive @#{node.name} is not defined#{context.did_you_mean_suggestion(node.name, @directive_names)}",
|
15
16
|
nodes: [],
|
16
17
|
directive: node.name
|
17
18
|
)
|
@@ -14,8 +14,9 @@ module GraphQL
|
|
14
14
|
node_name: parent_type.graphql_name
|
15
15
|
))
|
16
16
|
else
|
17
|
+
message = "Field '#{node.name}' doesn't exist on type '#{parent_type.graphql_name}'#{context.did_you_mean_suggestion(node.name, context.types.fields(parent_type).map(&:graphql_name))}"
|
17
18
|
add_error(GraphQL::StaticValidation::FieldsAreDefinedOnTypeError.new(
|
18
|
-
|
19
|
+
message,
|
19
20
|
nodes: node,
|
20
21
|
field: node.name,
|
21
22
|
type: parent_type.graphql_name
|
@@ -345,7 +345,7 @@ module GraphQL
|
|
345
345
|
fields << Field.new(node, definition, owner_type, parents)
|
346
346
|
when GraphQL::Language::Nodes::InlineFragment
|
347
347
|
fragment_type = node.type ? @types.type(node.type.name) : owner_type
|
348
|
-
find_fields_and_fragments(node.selections, parents: [*parents, fragment_type], owner_type:
|
348
|
+
find_fields_and_fragments(node.selections, parents: [*parents, fragment_type], owner_type: owner_type, fields: fields, fragment_spreads: fragment_spreads) if fragment_type
|
349
349
|
when GraphQL::Language::Nodes::FragmentSpread
|
350
350
|
fragment_spreads << FragmentSpread.new(node.name, parents)
|
351
351
|
end
|
@@ -23,8 +23,18 @@ module GraphQL
|
|
23
23
|
type_name = fragment_node.type.name
|
24
24
|
type = @types.type(type_name)
|
25
25
|
if type.nil?
|
26
|
+
@all_possible_fragment_type_names ||= begin
|
27
|
+
names = []
|
28
|
+
context.types.all_types.each do |type|
|
29
|
+
if type.kind.fields?
|
30
|
+
names << type.graphql_name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
names
|
34
|
+
end
|
35
|
+
|
26
36
|
add_error(GraphQL::StaticValidation::FragmentTypesExistError.new(
|
27
|
-
"No such type #{type_name}, so it can't be a fragment condition",
|
37
|
+
"No such type #{type_name}, so it can't be a fragment condition#{context.did_you_mean_suggestion(type_name, @all_possible_fragment_type_names)}",
|
28
38
|
nodes: fragment_node,
|
29
39
|
type: type_name
|
30
40
|
))
|
@@ -7,8 +7,17 @@ module GraphQL
|
|
7
7
|
type = context.query.types.type(type_name)
|
8
8
|
|
9
9
|
if type.nil?
|
10
|
+
@all_possible_input_type_names ||= begin
|
11
|
+
names = []
|
12
|
+
context.types.all_types.each { |(t)|
|
13
|
+
if t.kind.input?
|
14
|
+
names << t.graphql_name
|
15
|
+
end
|
16
|
+
}
|
17
|
+
names
|
18
|
+
end
|
10
19
|
add_error(GraphQL::StaticValidation::VariablesAreInputTypesError.new(
|
11
|
-
"#{type_name} isn't a defined input type (on $#{node.name})",
|
20
|
+
"#{type_name} isn't a defined input type (on $#{node.name})#{context.did_you_mean_suggestion(type_name, @all_possible_input_type_names)}",
|
12
21
|
nodes: node,
|
13
22
|
name: node.name,
|
14
23
|
type: type_name
|
@@ -48,6 +48,21 @@ module GraphQL
|
|
48
48
|
def schema_directives
|
49
49
|
@schema_directives ||= schema.directives
|
50
50
|
end
|
51
|
+
|
52
|
+
def did_you_mean_suggestion(name, options)
|
53
|
+
if did_you_mean = schema.did_you_mean
|
54
|
+
suggestions = did_you_mean::SpellChecker.new(dictionary: options).correct(name)
|
55
|
+
case suggestions.size
|
56
|
+
when 0
|
57
|
+
""
|
58
|
+
when 1
|
59
|
+
" (Did you mean `#{suggestions.first}`?)"
|
60
|
+
else
|
61
|
+
last_sugg = suggestions.pop
|
62
|
+
" (Did you mean #{suggestions.map {|s| "`#{s}`"}.join(", ")} or `#{last_sugg}`?)"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
51
66
|
end
|
52
67
|
end
|
53
68
|
end
|
@@ -28,8 +28,6 @@ module GraphQL
|
|
28
28
|
Gem::Version.new('1.0.0')
|
29
29
|
end
|
30
30
|
|
31
|
-
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
32
|
-
|
33
31
|
[
|
34
32
|
'lex',
|
35
33
|
'parse',
|
@@ -57,8 +55,6 @@ module GraphQL
|
|
57
55
|
RUBY
|
58
56
|
end
|
59
57
|
|
60
|
-
# rubocop:enable Development/NoEvalCop
|
61
|
-
|
62
58
|
def execute_field(query:, field:, ast_node:, arguments:, object:)
|
63
59
|
return_type = field.type.unwrap
|
64
60
|
trace_field = if return_type.kind.scalar? || return_type.kind.enum?
|
@@ -13,8 +13,6 @@ module GraphQL
|
|
13
13
|
super
|
14
14
|
end
|
15
15
|
|
16
|
-
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
17
|
-
|
18
16
|
{
|
19
17
|
"lex" => "lex.graphql",
|
20
18
|
"parse" => "parse.graphql",
|
@@ -45,8 +43,6 @@ module GraphQL
|
|
45
43
|
RUBY
|
46
44
|
end
|
47
45
|
|
48
|
-
# rubocop:enable Development/NoEvalCop
|
49
|
-
|
50
46
|
def platform_execute_field(platform_key)
|
51
47
|
Appsignal.instrument(platform_key) do
|
52
48
|
yield
|
@@ -20,8 +20,6 @@ module GraphQL
|
|
20
20
|
super
|
21
21
|
end
|
22
22
|
|
23
|
-
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
24
|
-
|
25
23
|
{
|
26
24
|
'lex' => 'lex.graphql',
|
27
25
|
'parse' => 'parse.graphql',
|
@@ -71,8 +69,6 @@ module GraphQL
|
|
71
69
|
RUBY
|
72
70
|
end
|
73
71
|
|
74
|
-
# rubocop:enable Development/NoEvalCop
|
75
|
-
|
76
72
|
def execute_field_span(span_key, query, field, ast_node, arguments, object)
|
77
73
|
return_type = field.type.unwrap
|
78
74
|
trace_field = if return_type.kind.scalar? || return_type.kind.enum?
|
@@ -16,8 +16,6 @@ module GraphQL
|
|
16
16
|
super
|
17
17
|
end
|
18
18
|
|
19
|
-
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
20
|
-
|
21
19
|
{
|
22
20
|
"lex" => "lex.graphql",
|
23
21
|
"parse" => "parse.graphql",
|
@@ -41,8 +39,6 @@ module GraphQL
|
|
41
39
|
RUBY
|
42
40
|
end
|
43
41
|
|
44
|
-
# rubocop:enable Development/NoEvalCop
|
45
|
-
|
46
42
|
include PlatformTrace
|
47
43
|
end
|
48
44
|
end
|
@@ -39,9 +39,6 @@ module GraphQL
|
|
39
39
|
include(BaseKeyCache)
|
40
40
|
}
|
41
41
|
child_class.const_set(:KeyCache, key_methods_class)
|
42
|
-
|
43
|
-
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
44
|
-
|
45
42
|
[:execute_field, :execute_field_lazy].each do |field_trace_method|
|
46
43
|
if !child_class.method_defined?(field_trace_method)
|
47
44
|
child_class.module_eval <<-RUBY, __FILE__, __LINE__
|
@@ -94,8 +91,6 @@ module GraphQL
|
|
94
91
|
end
|
95
92
|
RUBY
|
96
93
|
end
|
97
|
-
|
98
|
-
# rubocop:enable Development/NoEvalCop
|
99
94
|
end
|
100
95
|
end
|
101
96
|
|
@@ -13,8 +13,6 @@ module GraphQL
|
|
13
13
|
super(**rest)
|
14
14
|
end
|
15
15
|
|
16
|
-
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
17
|
-
|
18
16
|
{
|
19
17
|
'lex' => "graphql.lex",
|
20
18
|
'parse' => "graphql.parse",
|
@@ -32,8 +30,6 @@ module GraphQL
|
|
32
30
|
RUBY
|
33
31
|
end
|
34
32
|
|
35
|
-
# rubocop:enable Development/NoEvalCop
|
36
|
-
|
37
33
|
def platform_execute_field(platform_key, &block)
|
38
34
|
instrument_prometheus_execution(platform_key, "execute_field", &block)
|
39
35
|
end
|
@@ -16,8 +16,6 @@ module GraphQL
|
|
16
16
|
super
|
17
17
|
end
|
18
18
|
|
19
|
-
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
20
|
-
|
21
19
|
{
|
22
20
|
"lex" => "lex.graphql",
|
23
21
|
"parse" => "parse.graphql",
|
@@ -47,7 +45,6 @@ module GraphQL
|
|
47
45
|
end
|
48
46
|
RUBY
|
49
47
|
end
|
50
|
-
# rubocop:enable Development/NoEvalCop
|
51
48
|
|
52
49
|
def platform_execute_field(platform_key, &block)
|
53
50
|
self.class.instrument("GraphQL", platform_key, INSTRUMENT_OPTS, &block)
|
@@ -23,8 +23,6 @@ module GraphQL
|
|
23
23
|
instrument_sentry_execution("graphql.execute", "execute_query", data) { super }
|
24
24
|
end
|
25
25
|
|
26
|
-
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
27
|
-
|
28
26
|
{
|
29
27
|
"lex" => "graphql.lex",
|
30
28
|
"parse" => "graphql.parse",
|
@@ -41,8 +39,6 @@ module GraphQL
|
|
41
39
|
RUBY
|
42
40
|
end
|
43
41
|
|
44
|
-
# rubocop:enable Development/NoEvalCop
|
45
|
-
|
46
42
|
def platform_execute_field(platform_key, &block)
|
47
43
|
instrument_sentry_execution(platform_key, "execute_field", &block)
|
48
44
|
end
|
@@ -11,8 +11,6 @@ module GraphQL
|
|
11
11
|
super(**rest)
|
12
12
|
end
|
13
13
|
|
14
|
-
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
15
|
-
|
16
14
|
{
|
17
15
|
'lex' => "graphql.lex",
|
18
16
|
'parse' => "graphql.parse",
|
@@ -32,8 +30,6 @@ module GraphQL
|
|
32
30
|
RUBY
|
33
31
|
end
|
34
32
|
|
35
|
-
# rubocop:enable Development/NoEvalCop
|
36
|
-
|
37
33
|
def platform_execute_field(platform_key, &block)
|
38
34
|
@statsd.time(platform_key, &block)
|
39
35
|
end
|
@@ -8,7 +8,7 @@ module GraphQL
|
|
8
8
|
child_class.description("An edge in a connection.")
|
9
9
|
child_class.field(:cursor, String, null: false, description: "A cursor for use in pagination.")
|
10
10
|
child_class.extend(ClassMethods)
|
11
|
-
child_class.
|
11
|
+
child_class.class_eval { self.node_type = nil }
|
12
12
|
child_class.node_nullable(true)
|
13
13
|
child_class.default_broadcastable(nil)
|
14
14
|
end
|
data/lib/graphql/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-10-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: base64
|
@@ -650,7 +650,7 @@ metadata:
|
|
650
650
|
bug_tracker_uri: https://github.com/rmosolgo/graphql-ruby/issues
|
651
651
|
mailing_list_uri: https://buttondown.email/graphql-ruby
|
652
652
|
rubygems_mfa_required: 'true'
|
653
|
-
post_install_message:
|
653
|
+
post_install_message:
|
654
654
|
rdoc_options: []
|
655
655
|
require_paths:
|
656
656
|
- lib
|
@@ -665,8 +665,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
665
665
|
- !ruby/object:Gem::Version
|
666
666
|
version: '0'
|
667
667
|
requirements: []
|
668
|
-
rubygems_version: 3.
|
669
|
-
signing_key:
|
668
|
+
rubygems_version: 3.5.12
|
669
|
+
signing_key:
|
670
670
|
specification_version: 4
|
671
671
|
summary: A GraphQL language and runtime for Ruby
|
672
672
|
test_files: []
|