graphql 1.12.10 → 1.13.4
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/generators/graphql/core.rb +3 -1
- data/lib/generators/graphql/install_generator.rb +9 -2
- data/lib/generators/graphql/mutation_generator.rb +1 -1
- data/lib/generators/graphql/object_generator.rb +2 -1
- data/lib/generators/graphql/relay.rb +19 -11
- data/lib/generators/graphql/templates/schema.erb +14 -2
- data/lib/generators/graphql/type_generator.rb +0 -1
- data/lib/graphql/analysis/ast/field_usage.rb +28 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +10 -14
- data/lib/graphql/analysis/ast/visitor.rb +4 -4
- data/lib/graphql/backtrace/table.rb +15 -3
- data/lib/graphql/backtrace/tracer.rb +7 -4
- data/lib/graphql/base_type.rb +4 -2
- data/lib/graphql/boolean_type.rb +1 -1
- data/lib/graphql/dataloader/null_dataloader.rb +1 -0
- data/lib/graphql/dataloader/source.rb +50 -2
- data/lib/graphql/dataloader.rb +110 -41
- data/lib/graphql/define/instance_definable.rb +1 -1
- data/lib/graphql/deprecated_dsl.rb +11 -3
- data/lib/graphql/deprecation.rb +1 -5
- data/lib/graphql/directive/deprecated_directive.rb +1 -1
- data/lib/graphql/directive/include_directive.rb +1 -1
- data/lib/graphql/directive/skip_directive.rb +1 -1
- data/lib/graphql/directive.rb +0 -4
- data/lib/graphql/enum_type.rb +5 -1
- data/lib/graphql/execution/errors.rb +1 -0
- data/lib/graphql/execution/execute.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -4
- data/lib/graphql/execution/interpreter/resolve.rb +6 -2
- data/lib/graphql/execution/interpreter/runtime.rb +513 -213
- data/lib/graphql/execution/interpreter.rb +4 -8
- data/lib/graphql/execution/lazy.rb +5 -1
- data/lib/graphql/execution/lookahead.rb +2 -2
- data/lib/graphql/execution/multiplex.rb +4 -1
- data/lib/graphql/float_type.rb +1 -1
- data/lib/graphql/id_type.rb +1 -1
- data/lib/graphql/int_type.rb +1 -1
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/introspection/directive_type.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +2 -2
- data/lib/graphql/introspection/enum_value_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +2 -2
- data/lib/graphql/introspection/input_value_type.rb +10 -4
- data/lib/graphql/introspection/schema_type.rb +3 -3
- data/lib/graphql/introspection/type_type.rb +10 -10
- data/lib/graphql/language/block_string.rb +2 -6
- data/lib/graphql/language/document_from_schema_definition.rb +10 -4
- data/lib/graphql/language/lexer.rb +0 -3
- data/lib/graphql/language/lexer.rl +0 -4
- data/lib/graphql/language/nodes.rb +13 -3
- data/lib/graphql/language/parser.rb +442 -434
- data/lib/graphql/language/parser.y +5 -4
- data/lib/graphql/language/printer.rb +6 -1
- data/lib/graphql/language/sanitized_printer.rb +5 -5
- data/lib/graphql/language/token.rb +0 -4
- data/lib/graphql/name_validator.rb +0 -4
- data/lib/graphql/pagination/active_record_relation_connection.rb +43 -6
- data/lib/graphql/pagination/connections.rb +40 -16
- data/lib/graphql/pagination/relation_connection.rb +57 -27
- data/lib/graphql/query/arguments.rb +1 -1
- data/lib/graphql/query/arguments_cache.rb +1 -1
- data/lib/graphql/query/context.rb +15 -2
- data/lib/graphql/query/literal_input.rb +1 -1
- data/lib/graphql/query/null_context.rb +12 -7
- data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
- data/lib/graphql/query/validation_pipeline.rb +1 -1
- data/lib/graphql/query/variables.rb +5 -1
- data/lib/graphql/query.rb +5 -1
- data/lib/graphql/relay/edges_instrumentation.rb +0 -1
- data/lib/graphql/relay/global_id_resolve.rb +1 -1
- data/lib/graphql/relay/page_info.rb +1 -1
- data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
- data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
- data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
- data/lib/graphql/rubocop.rb +4 -0
- data/lib/graphql/schema/addition.rb +247 -0
- data/lib/graphql/schema/argument.rb +103 -45
- data/lib/graphql/schema/build_from_definition.rb +13 -7
- data/lib/graphql/schema/directive/feature.rb +1 -1
- data/lib/graphql/schema/directive/flagged.rb +2 -2
- data/lib/graphql/schema/directive/include.rb +1 -1
- data/lib/graphql/schema/directive/skip.rb +1 -1
- data/lib/graphql/schema/directive/transform.rb +14 -2
- data/lib/graphql/schema/directive.rb +7 -3
- data/lib/graphql/schema/enum.rb +70 -11
- data/lib/graphql/schema/enum_value.rb +6 -0
- data/lib/graphql/schema/field/connection_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +243 -81
- data/lib/graphql/schema/field_extension.rb +89 -2
- data/lib/graphql/schema/find_inherited_value.rb +1 -0
- data/lib/graphql/schema/finder.rb +5 -5
- data/lib/graphql/schema/input_object.rb +39 -29
- data/lib/graphql/schema/interface.rb +11 -20
- data/lib/graphql/schema/introspection_system.rb +1 -1
- data/lib/graphql/schema/list.rb +3 -1
- data/lib/graphql/schema/member/accepts_definition.rb +15 -3
- data/lib/graphql/schema/member/build_type.rb +1 -4
- data/lib/graphql/schema/member/cached_graphql_definition.rb +29 -2
- data/lib/graphql/schema/member/has_arguments.rb +145 -57
- data/lib/graphql/schema/member/has_deprecation_reason.rb +1 -1
- data/lib/graphql/schema/member/has_fields.rb +76 -18
- data/lib/graphql/schema/member/has_interfaces.rb +90 -0
- data/lib/graphql/schema/member.rb +1 -0
- data/lib/graphql/schema/non_null.rb +7 -1
- data/lib/graphql/schema/object.rb +10 -75
- data/lib/graphql/schema/printer.rb +12 -17
- data/lib/graphql/schema/relay_classic_mutation.rb +37 -3
- data/lib/graphql/schema/resolver/has_payload_type.rb +27 -2
- data/lib/graphql/schema/resolver.rb +75 -65
- data/lib/graphql/schema/scalar.rb +2 -0
- data/lib/graphql/schema/subscription.rb +36 -8
- data/lib/graphql/schema/traversal.rb +1 -1
- data/lib/graphql/schema/type_expression.rb +1 -1
- data/lib/graphql/schema/type_membership.rb +18 -4
- data/lib/graphql/schema/union.rb +8 -1
- data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
- data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
- data/lib/graphql/schema/validator/exclusion_validator.rb +3 -1
- data/lib/graphql/schema/validator/format_validator.rb +4 -5
- data/lib/graphql/schema/validator/inclusion_validator.rb +3 -1
- data/lib/graphql/schema/validator/length_validator.rb +5 -3
- data/lib/graphql/schema/validator/numericality_validator.rb +13 -2
- data/lib/graphql/schema/validator/required_validator.rb +29 -15
- data/lib/graphql/schema/validator.rb +33 -25
- data/lib/graphql/schema/warden.rb +116 -52
- data/lib/graphql/schema.rb +162 -227
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/base_visitor.rb +8 -5
- data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
- data/lib/graphql/static_validation/error.rb +3 -1
- data/lib/graphql/static_validation/literal_validator.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +52 -26
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
- data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
- data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +3 -1
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +4 -4
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +13 -7
- data/lib/graphql/static_validation/validation_context.rb +8 -2
- data/lib/graphql/static_validation/validator.rb +15 -12
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/string_type.rb +1 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +36 -6
- data/lib/graphql/subscriptions/event.rb +68 -31
- data/lib/graphql/subscriptions/serialize.rb +23 -3
- data/lib/graphql/subscriptions.rb +17 -19
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +6 -20
- data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
- data/lib/graphql/tracing/notifications_tracing.rb +59 -0
- data/lib/graphql/types/big_int.rb +5 -1
- data/lib/graphql/types/int.rb +1 -1
- data/lib/graphql/types/relay/connection_behaviors.rb +26 -9
- data/lib/graphql/types/relay/default_relay.rb +5 -1
- data/lib/graphql/types/relay/edge_behaviors.rb +13 -2
- data/lib/graphql/types/relay/has_node_field.rb +2 -2
- data/lib/graphql/types/relay/has_nodes_field.rb +2 -2
- data/lib/graphql/types/relay/node_field.rb +15 -4
- data/lib/graphql/types/relay/nodes_field.rb +14 -4
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/unauthorized_error.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +10 -28
- data/readme.md +1 -4
- metadata +17 -21
- data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
|
@@ -11,6 +11,14 @@ module GraphQL
|
|
|
11
11
|
|
|
12
12
|
include GraphQL::Dig
|
|
13
13
|
|
|
14
|
+
# @return [GraphQL::Query::Context] The context for this query
|
|
15
|
+
attr_reader :context
|
|
16
|
+
# @return [GraphQL::Query::Arguments, GraphQL::Execution::Interpereter::Arguments] The underlying arguments instance
|
|
17
|
+
attr_reader :arguments
|
|
18
|
+
|
|
19
|
+
# Ruby-like hash behaviors, read-only
|
|
20
|
+
def_delegators :@ruby_style_hash, :keys, :values, :each, :map, :any?, :empty?
|
|
21
|
+
|
|
14
22
|
def initialize(arguments = nil, ruby_kwargs: nil, context:, defaults_used:)
|
|
15
23
|
@context = context
|
|
16
24
|
if ruby_kwargs
|
|
@@ -23,7 +31,7 @@ module GraphQL
|
|
|
23
31
|
end
|
|
24
32
|
# Apply prepares, not great to have it duplicated here.
|
|
25
33
|
maybe_lazies = []
|
|
26
|
-
self.class.arguments.each_value do |arg_defn|
|
|
34
|
+
self.class.arguments(context).each_value do |arg_defn|
|
|
27
35
|
ruby_kwargs_key = arg_defn.keyword
|
|
28
36
|
|
|
29
37
|
if @ruby_style_hash.key?(ruby_kwargs_key)
|
|
@@ -32,11 +40,7 @@ module GraphQL
|
|
|
32
40
|
# With the interpreter, it's done during `coerce_arguments`
|
|
33
41
|
if loads && !arg_defn.from_resolver? && !context.interpreter?
|
|
34
42
|
value = @ruby_style_hash[ruby_kwargs_key]
|
|
35
|
-
loaded_value =
|
|
36
|
-
value.map { |val| load_application_object(arg_defn, loads, val, context) }
|
|
37
|
-
else
|
|
38
|
-
load_application_object(arg_defn, loads, value, context)
|
|
39
|
-
end
|
|
43
|
+
loaded_value = arg_defn.load_and_authorize_value(self, value, context)
|
|
40
44
|
maybe_lazies << context.schema.after_lazy(loaded_value) do |loaded_value|
|
|
41
45
|
overwrite_argument(ruby_kwargs_key, loaded_value)
|
|
42
46
|
end
|
|
@@ -54,19 +58,8 @@ module GraphQL
|
|
|
54
58
|
@maybe_lazies = maybe_lazies
|
|
55
59
|
end
|
|
56
60
|
|
|
57
|
-
# @return [GraphQL::Query::Context] The context for this query
|
|
58
|
-
attr_reader :context
|
|
59
|
-
|
|
60
|
-
# @return [GraphQL::Query::Arguments, GraphQL::Execution::Interpereter::Arguments] The underlying arguments instance
|
|
61
|
-
attr_reader :arguments
|
|
62
|
-
|
|
63
|
-
# Ruby-like hash behaviors, read-only
|
|
64
|
-
def_delegators :@ruby_style_hash, :keys, :values, :each, :map, :any?, :empty?
|
|
65
|
-
|
|
66
61
|
def to_h
|
|
67
|
-
@ruby_style_hash
|
|
68
|
-
h.merge(key => unwrap_value(value))
|
|
69
|
-
end
|
|
62
|
+
unwrap_value(@ruby_style_hash)
|
|
70
63
|
end
|
|
71
64
|
|
|
72
65
|
def to_hash
|
|
@@ -74,11 +67,11 @@ module GraphQL
|
|
|
74
67
|
end
|
|
75
68
|
|
|
76
69
|
def prepare
|
|
77
|
-
if context
|
|
78
|
-
context.schema.after_any_lazies(@maybe_lazies) do
|
|
79
|
-
object = context[:current_object]
|
|
70
|
+
if @context
|
|
71
|
+
@context.schema.after_any_lazies(@maybe_lazies) do
|
|
72
|
+
object = @context[:current_object]
|
|
80
73
|
# Pass this object's class with `as` so that messages are rendered correctly from inherited validators
|
|
81
|
-
Schema::Validator.validate!(self.class.validators, object, context, @ruby_style_hash, as: self.class)
|
|
74
|
+
Schema::Validator.validate!(self.class.validators, object, @context, @ruby_style_hash, as: self.class)
|
|
82
75
|
self
|
|
83
76
|
end
|
|
84
77
|
else
|
|
@@ -86,13 +79,28 @@ module GraphQL
|
|
|
86
79
|
end
|
|
87
80
|
end
|
|
88
81
|
|
|
82
|
+
def self.authorized?(obj, value, ctx)
|
|
83
|
+
# Authorize each argument (but this doesn't apply if `prepare` is implemented):
|
|
84
|
+
if value.is_a?(InputObject)
|
|
85
|
+
arguments(ctx).each do |_name, input_obj_arg|
|
|
86
|
+
input_obj_arg = input_obj_arg.type_class
|
|
87
|
+
if value.key?(input_obj_arg.keyword) &&
|
|
88
|
+
!input_obj_arg.authorized?(obj, value[input_obj_arg.keyword], ctx)
|
|
89
|
+
return false
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
# It didn't early-return false:
|
|
94
|
+
true
|
|
95
|
+
end
|
|
96
|
+
|
|
89
97
|
def unwrap_value(value)
|
|
90
98
|
case value
|
|
91
99
|
when Array
|
|
92
100
|
value.map { |item| unwrap_value(item) }
|
|
93
101
|
when Hash
|
|
94
|
-
value.
|
|
95
|
-
h.merge(key => unwrap_value(value))
|
|
102
|
+
value.reduce({}) do |h, (key, value)|
|
|
103
|
+
h.merge!(key => unwrap_value(value))
|
|
96
104
|
end
|
|
97
105
|
when InputObject
|
|
98
106
|
value.to_h
|
|
@@ -136,8 +144,11 @@ module GraphQL
|
|
|
136
144
|
self[#{method_name.inspect}]
|
|
137
145
|
end
|
|
138
146
|
RUBY
|
|
147
|
+
argument_defn
|
|
139
148
|
end
|
|
140
149
|
|
|
150
|
+
prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
|
|
151
|
+
|
|
141
152
|
def to_graphql
|
|
142
153
|
type_defn = GraphQL::InputObjectType.new
|
|
143
154
|
type_defn.name = graphql_name
|
|
@@ -145,8 +156,8 @@ module GraphQL
|
|
|
145
156
|
type_defn.metadata[:type_class] = self
|
|
146
157
|
type_defn.mutation = mutation
|
|
147
158
|
type_defn.ast_node = ast_node
|
|
148
|
-
|
|
149
|
-
type_defn.arguments[arg.graphql_definition.name] = arg.graphql_definition
|
|
159
|
+
all_argument_definitions.each do |arg|
|
|
160
|
+
type_defn.arguments[arg.graphql_definition(silence_deprecation_warning: true).name] = arg.graphql_definition(silence_deprecation_warning: true) # rubocop:disable Development/ContextIsPassedCop -- legacy-related
|
|
150
161
|
end
|
|
151
162
|
# Make a reference to a classic-style Arguments class
|
|
152
163
|
self.arguments_class = GraphQL::Query::Arguments.construct_arguments_class(type_defn)
|
|
@@ -162,7 +173,6 @@ module GraphQL
|
|
|
162
173
|
# @api private
|
|
163
174
|
INVALID_OBJECT_MESSAGE = "Expected %{object} to be a key-value object responding to `to_h` or `to_unsafe_h`."
|
|
164
175
|
|
|
165
|
-
|
|
166
176
|
def validate_non_null_input(input, ctx)
|
|
167
177
|
result = GraphQL::Query::InputValidationResult.new
|
|
168
178
|
|
|
@@ -180,7 +190,7 @@ module GraphQL
|
|
|
180
190
|
end
|
|
181
191
|
|
|
182
192
|
# Inject missing required arguments
|
|
183
|
-
missing_required_inputs = self.arguments.reduce({}) do |m, (argument_name, argument)|
|
|
193
|
+
missing_required_inputs = self.arguments(ctx).reduce({}) do |m, (argument_name, argument)|
|
|
184
194
|
if !input.key?(argument_name) && argument.type.non_null? && warden.get_argument(self, argument_name)
|
|
185
195
|
m[argument_name] = nil
|
|
186
196
|
end
|
|
@@ -231,7 +241,7 @@ module GraphQL
|
|
|
231
241
|
|
|
232
242
|
result = {}
|
|
233
243
|
|
|
234
|
-
arguments.each do |input_key, input_field_defn|
|
|
244
|
+
arguments(ctx).each do |input_key, input_field_defn|
|
|
235
245
|
input_value = value[input_key]
|
|
236
246
|
if value.key?(input_key)
|
|
237
247
|
result[input_key] = if input_value.nil?
|
|
@@ -16,6 +16,7 @@ module GraphQL
|
|
|
16
16
|
include GraphQL::Schema::Member::HasAstNode
|
|
17
17
|
include GraphQL::Schema::Member::HasUnresolvedTypeError
|
|
18
18
|
include GraphQL::Schema::Member::HasDirectives
|
|
19
|
+
include GraphQL::Schema::Member::HasInterfaces
|
|
19
20
|
|
|
20
21
|
# Methods defined in this block will be:
|
|
21
22
|
# - Added as class methods to this interface
|
|
@@ -57,9 +58,10 @@ module GraphQL
|
|
|
57
58
|
child_class.extend(Schema::Interface::DefinitionMethods)
|
|
58
59
|
|
|
59
60
|
child_class.type_membership_class(self.type_membership_class)
|
|
60
|
-
child_class.
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
child_class.ancestors.reverse_each do |ancestor|
|
|
62
|
+
if ancestor.const_defined?(:DefinitionMethods)
|
|
63
|
+
child_class.extend(ancestor::DefinitionMethods)
|
|
64
|
+
end
|
|
63
65
|
end
|
|
64
66
|
|
|
65
67
|
# Use an instance variable to tell whether it's been included previously or not;
|
|
@@ -73,16 +75,13 @@ module GraphQL
|
|
|
73
75
|
end
|
|
74
76
|
child_class.introspection(introspection)
|
|
75
77
|
child_class.description(description)
|
|
76
|
-
if overridden_graphql_name
|
|
77
|
-
child_class.graphql_name(overridden_graphql_name)
|
|
78
|
-
end
|
|
79
78
|
# If interfaces are mixed into each other, only define this class once
|
|
80
79
|
if !child_class.const_defined?(:UnresolvedTypeError, false)
|
|
81
80
|
add_unresolved_type_error(child_class)
|
|
82
81
|
end
|
|
83
82
|
elsif child_class < GraphQL::Schema::Object
|
|
84
83
|
# This is being included into an object type, make sure it's using `implements(...)`
|
|
85
|
-
backtrace_line = caller(0, 10).find { |line| line.include?("schema/
|
|
84
|
+
backtrace_line = caller(0, 10).find { |line| line.include?("schema/member/has_interfaces.rb") && line.include?("in `implements'")}
|
|
86
85
|
if !backtrace_line
|
|
87
86
|
raise "Attach interfaces using `implements(#{self})`, not `include(#{self})`"
|
|
88
87
|
end
|
|
@@ -101,6 +100,8 @@ module GraphQL
|
|
|
101
100
|
end
|
|
102
101
|
end
|
|
103
102
|
|
|
103
|
+
prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
|
|
104
|
+
|
|
104
105
|
def to_graphql
|
|
105
106
|
type_defn = GraphQL::InterfaceType.new
|
|
106
107
|
type_defn.name = graphql_name
|
|
@@ -108,9 +109,9 @@ module GraphQL
|
|
|
108
109
|
type_defn.orphan_types = orphan_types
|
|
109
110
|
type_defn.type_membership_class = self.type_membership_class
|
|
110
111
|
type_defn.ast_node = ast_node
|
|
111
|
-
fields.each do |field_name, field_inst|
|
|
112
|
-
field_defn = field_inst.graphql_definition
|
|
113
|
-
type_defn.fields[field_defn.name] = field_defn
|
|
112
|
+
fields.each do |field_name, field_inst| # rubocop:disable Development/ContextIsPassedCop -- legacy-related
|
|
113
|
+
field_defn = field_inst.graphql_definition(silence_deprecation_warning: true)
|
|
114
|
+
type_defn.fields[field_defn.name] = field_defn # rubocop:disable Development/ContextIsPassedCop -- legacy-related
|
|
114
115
|
end
|
|
115
116
|
type_defn.metadata[:type_class] = self
|
|
116
117
|
if respond_to?(:resolve_type)
|
|
@@ -122,16 +123,6 @@ module GraphQL
|
|
|
122
123
|
def kind
|
|
123
124
|
GraphQL::TypeKinds::INTERFACE
|
|
124
125
|
end
|
|
125
|
-
|
|
126
|
-
protected
|
|
127
|
-
|
|
128
|
-
def own_interfaces
|
|
129
|
-
@own_interfaces ||= []
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def interfaces
|
|
133
|
-
own_interfaces + (own_interfaces.map { |i| i.own_interfaces }).flatten
|
|
134
|
-
end
|
|
135
126
|
end
|
|
136
127
|
|
|
137
128
|
# Extend this _after_ `DefinitionMethods` is defined, so it will be used
|
|
@@ -107,7 +107,7 @@ module GraphQL
|
|
|
107
107
|
dup_type_class(const)
|
|
108
108
|
else
|
|
109
109
|
# Use `.to_graphql` to get a freshly-made version, not shared between schemas
|
|
110
|
-
const.
|
|
110
|
+
const.deprecated_to_graphql
|
|
111
111
|
end
|
|
112
112
|
rescue NameError
|
|
113
113
|
# Dup the built-in so that the cached fields aren't shared
|
data/lib/graphql/schema/list.rb
CHANGED
|
@@ -8,8 +8,10 @@ module GraphQL
|
|
|
8
8
|
class List < GraphQL::Schema::Wrapper
|
|
9
9
|
include Schema::Member::ValidatesInput
|
|
10
10
|
|
|
11
|
+
prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
|
|
12
|
+
|
|
11
13
|
def to_graphql
|
|
12
|
-
@of_type.graphql_definition.to_list_type
|
|
14
|
+
@of_type.graphql_definition(silence_deprecation_warning: true).to_list_type
|
|
13
15
|
end
|
|
14
16
|
|
|
15
17
|
# @return [GraphQL::TypeKinds::LIST]
|
|
@@ -85,8 +85,15 @@ module GraphQL
|
|
|
85
85
|
define_method(name) do |*args|
|
|
86
86
|
if args.any?
|
|
87
87
|
instance_variable_set(ivar_name, args)
|
|
88
|
+
else
|
|
89
|
+
if (v = instance_variable_get(ivar_name))
|
|
90
|
+
v
|
|
91
|
+
elsif (ancestor = ancestors.find { |i| i.respond_to?(name) && i != self })
|
|
92
|
+
ancestor.public_send(name)
|
|
93
|
+
else
|
|
94
|
+
nil
|
|
95
|
+
end
|
|
88
96
|
end
|
|
89
|
-
instance_variable_get(ivar_name) || ((int = interfaces.first { |i| i.respond_to?()}) && int.public_send(name))
|
|
90
97
|
end
|
|
91
98
|
end
|
|
92
99
|
end
|
|
@@ -116,8 +123,13 @@ module GraphQL
|
|
|
116
123
|
end
|
|
117
124
|
|
|
118
125
|
module ToGraphQLExtension
|
|
119
|
-
def to_graphql
|
|
120
|
-
|
|
126
|
+
def to_graphql(*args, **kwargs)
|
|
127
|
+
|
|
128
|
+
defn = if args.empty? && kwargs.empty?
|
|
129
|
+
super()
|
|
130
|
+
else
|
|
131
|
+
super
|
|
132
|
+
end
|
|
121
133
|
accepts_definition_methods.each do |method_name|
|
|
122
134
|
value = public_send(method_name)
|
|
123
135
|
if !value.nil?
|
|
@@ -4,10 +4,6 @@ module GraphQL
|
|
|
4
4
|
class Member
|
|
5
5
|
# @api private
|
|
6
6
|
module BuildType
|
|
7
|
-
if !String.method_defined?(:match?)
|
|
8
|
-
using GraphQL::StringMatchBackport
|
|
9
|
-
end
|
|
10
|
-
|
|
11
7
|
LIST_TYPE_ERROR = "Use an array of [T] or [T, null: true] for list types; other arrays are not supported"
|
|
12
8
|
|
|
13
9
|
module_function
|
|
@@ -124,6 +120,7 @@ module GraphQL
|
|
|
124
120
|
end
|
|
125
121
|
|
|
126
122
|
def camelize(string)
|
|
123
|
+
return string if string == '_'
|
|
127
124
|
return string unless string.include?("_")
|
|
128
125
|
camelized = string.split('_').map(&:capitalize).join
|
|
129
126
|
camelized[0] = camelized[0].downcase
|
|
@@ -11,8 +11,24 @@ module GraphQL
|
|
|
11
11
|
# A cached result of {.to_graphql}.
|
|
12
12
|
# It's cached here so that user-overridden {.to_graphql} implementations
|
|
13
13
|
# are also cached
|
|
14
|
-
def graphql_definition
|
|
15
|
-
@graphql_definition ||=
|
|
14
|
+
def graphql_definition(silence_deprecation_warning: false)
|
|
15
|
+
@graphql_definition ||= begin
|
|
16
|
+
unless silence_deprecation_warning
|
|
17
|
+
message = "Legacy `.graphql_definition` objects are deprecated and will be removed in GraphQL-Ruby 2.0. Remove `.graphql_definition` to use a class-based definition instead."
|
|
18
|
+
caller_message = "\n\nCalled on #{self.inspect} from:\n #{caller(1, 25).map { |l| " #{l}" }.join("\n")}"
|
|
19
|
+
GraphQL::Deprecation.warn(message + caller_message)
|
|
20
|
+
end
|
|
21
|
+
deprecated_to_graphql
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def deprecated_to_graphql
|
|
26
|
+
case method(:to_graphql).arity
|
|
27
|
+
when 0
|
|
28
|
+
to_graphql
|
|
29
|
+
else
|
|
30
|
+
to_graphql(silence_deprecation_warning: true)
|
|
31
|
+
end
|
|
16
32
|
end
|
|
17
33
|
|
|
18
34
|
# This is for a common interface with .define-based types
|
|
@@ -25,6 +41,17 @@ module GraphQL
|
|
|
25
41
|
super
|
|
26
42
|
@graphql_definition = nil
|
|
27
43
|
end
|
|
44
|
+
|
|
45
|
+
module DeprecatedToGraphQL
|
|
46
|
+
def to_graphql(silence_deprecation_warning: false)
|
|
47
|
+
unless silence_deprecation_warning
|
|
48
|
+
message = "Legacy `.to_graphql` objects are deprecated and will be removed in GraphQL-Ruby 2.0. Remove `.to_graphql` to use a class-based definition instead."
|
|
49
|
+
caller_message = "\n\nCalled on #{self.inspect} from:\n #{caller(1, 25).map { |l| " #{l}" }.join("\n")}"
|
|
50
|
+
GraphQL::Deprecation.warn(message + caller_message)
|
|
51
|
+
end
|
|
52
|
+
super()
|
|
53
|
+
end
|
|
54
|
+
end
|
|
28
55
|
end
|
|
29
56
|
end
|
|
30
57
|
end
|
|
@@ -37,6 +37,40 @@ module GraphQL
|
|
|
37
37
|
end
|
|
38
38
|
arg_defn = self.argument_class.new(*args, **kwargs, &block)
|
|
39
39
|
add_argument(arg_defn)
|
|
40
|
+
|
|
41
|
+
if self.is_a?(Class) && !method_defined?(:"load_#{arg_defn.keyword}")
|
|
42
|
+
method_owner = if self < GraphQL::Schema::InputObject || self < GraphQL::Schema::Directive
|
|
43
|
+
"self."
|
|
44
|
+
elsif self < GraphQL::Schema::Resolver
|
|
45
|
+
""
|
|
46
|
+
else
|
|
47
|
+
raise "Unexpected argument owner: #{self}"
|
|
48
|
+
end
|
|
49
|
+
if loads && arg_defn.type.list?
|
|
50
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
51
|
+
def #{method_owner}load_#{arg_defn.keyword}(values, context = nil)
|
|
52
|
+
argument = get_argument("#{arg_defn.graphql_name}")
|
|
53
|
+
(context || self.context).schema.after_lazy(values) do |values2|
|
|
54
|
+
GraphQL::Execution::Lazy.all(values2.map { |value| load_application_object(argument, value, context || self.context) })
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
RUBY
|
|
58
|
+
elsif loads
|
|
59
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
60
|
+
def #{method_owner}load_#{arg_defn.keyword}(value, context = nil)
|
|
61
|
+
argument = get_argument("#{arg_defn.graphql_name}")
|
|
62
|
+
load_application_object(argument, value, context || self.context)
|
|
63
|
+
end
|
|
64
|
+
RUBY
|
|
65
|
+
else
|
|
66
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
67
|
+
def #{method_owner}load_#{arg_defn.keyword}(value, _context = nil)
|
|
68
|
+
value
|
|
69
|
+
end
|
|
70
|
+
RUBY
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
arg_defn
|
|
40
74
|
end
|
|
41
75
|
|
|
42
76
|
# Register this argument with the class.
|
|
@@ -44,30 +78,72 @@ module GraphQL
|
|
|
44
78
|
# @return [GraphQL::Schema::Argument]
|
|
45
79
|
def add_argument(arg_defn)
|
|
46
80
|
@own_arguments ||= {}
|
|
47
|
-
own_arguments[arg_defn.name]
|
|
81
|
+
prev_defn = own_arguments[arg_defn.name]
|
|
82
|
+
case prev_defn
|
|
83
|
+
when nil
|
|
84
|
+
own_arguments[arg_defn.name] = arg_defn
|
|
85
|
+
when Array
|
|
86
|
+
prev_defn << arg_defn
|
|
87
|
+
when GraphQL::Schema::Argument
|
|
88
|
+
own_arguments[arg_defn.name] = [prev_defn, arg_defn]
|
|
89
|
+
else
|
|
90
|
+
raise "Invariant: unexpected `@own_arguments[#{arg_defn.name.inspect}]`: #{prev_defn.inspect}"
|
|
91
|
+
end
|
|
48
92
|
arg_defn
|
|
49
93
|
end
|
|
50
94
|
|
|
51
95
|
# @return [Hash<String => GraphQL::Schema::Argument] Arguments defined on this thing, keyed by name. Includes inherited definitions
|
|
52
|
-
def arguments
|
|
53
|
-
inherited_arguments = ((self.is_a?(Class) && superclass.respond_to?(:arguments)) ? superclass.arguments : nil)
|
|
96
|
+
def arguments(context = GraphQL::Query::NullContext)
|
|
97
|
+
inherited_arguments = ((self.is_a?(Class) && superclass.respond_to?(:arguments)) ? superclass.arguments(context) : nil)
|
|
54
98
|
# Local definitions override inherited ones
|
|
99
|
+
if own_arguments.any?
|
|
100
|
+
own_arguments_that_apply = {}
|
|
101
|
+
own_arguments.each do |name, args_entry|
|
|
102
|
+
if (visible_defn = Warden.visible_entry?(:visible_argument?, args_entry, context))
|
|
103
|
+
own_arguments_that_apply[visible_defn.graphql_name] = visible_defn
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
55
108
|
if inherited_arguments
|
|
56
|
-
|
|
109
|
+
if own_arguments_that_apply
|
|
110
|
+
inherited_arguments.merge(own_arguments_that_apply)
|
|
111
|
+
else
|
|
112
|
+
inherited_arguments
|
|
113
|
+
end
|
|
57
114
|
else
|
|
58
|
-
|
|
115
|
+
# might be nil if there are actually no arguments
|
|
116
|
+
own_arguments_that_apply || own_arguments
|
|
59
117
|
end
|
|
60
118
|
end
|
|
61
119
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
120
|
+
def all_argument_definitions
|
|
121
|
+
if self.is_a?(Class)
|
|
122
|
+
all_defns = {}
|
|
123
|
+
ancestors.reverse_each do |ancestor|
|
|
124
|
+
if ancestor.respond_to?(:own_arguments)
|
|
125
|
+
all_defns.merge!(ancestor.own_arguments)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
else
|
|
129
|
+
all_defns = own_arguments
|
|
130
|
+
end
|
|
131
|
+
all_defns = all_defns.values
|
|
132
|
+
all_defns.flatten!
|
|
133
|
+
all_defns
|
|
134
|
+
end
|
|
65
135
|
|
|
66
|
-
|
|
67
|
-
|
|
136
|
+
# @return [GraphQL::Schema::Argument, nil] Argument defined on this thing, fetched by name.
|
|
137
|
+
def get_argument(argument_name, context = GraphQL::Query::NullContext)
|
|
138
|
+
warden = Warden.from_context(context)
|
|
139
|
+
if !self.is_a?(Class)
|
|
140
|
+
a = own_arguments[argument_name]
|
|
141
|
+
a && Warden.visible_entry?(:visible_argument?, a, context, warden)
|
|
68
142
|
else
|
|
69
143
|
for ancestor in ancestors
|
|
70
|
-
if ancestor.respond_to?(:own_arguments) &&
|
|
144
|
+
if ancestor.respond_to?(:own_arguments) &&
|
|
145
|
+
(a = ancestor.own_arguments[argument_name]) &&
|
|
146
|
+
(a = Warden.visible_entry?(:visible_argument?, a, context, warden))
|
|
71
147
|
return a
|
|
72
148
|
end
|
|
73
149
|
end
|
|
@@ -91,57 +167,55 @@ module GraphQL
|
|
|
91
167
|
# @return [Interpreter::Arguments, Execution::Lazy<Interpeter::Arguments>]
|
|
92
168
|
def coerce_arguments(parent_object, values, context, &block)
|
|
93
169
|
# Cache this hash to avoid re-merging it
|
|
94
|
-
arg_defns = self.arguments
|
|
170
|
+
arg_defns = self.arguments(context)
|
|
95
171
|
total_args_count = arg_defns.size
|
|
96
172
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if
|
|
100
|
-
|
|
101
|
-
|
|
173
|
+
finished_args = nil
|
|
174
|
+
prepare_finished_args = -> {
|
|
175
|
+
if total_args_count == 0
|
|
176
|
+
finished_args = GraphQL::Execution::Interpreter::Arguments::EMPTY
|
|
177
|
+
if block_given?
|
|
178
|
+
block.call(finished_args)
|
|
179
|
+
end
|
|
102
180
|
else
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
begin
|
|
113
|
-
arg_defn.coerce_into_values(parent_object, values, context, argument_values)
|
|
114
|
-
rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => err
|
|
115
|
-
raised_error = true
|
|
116
|
-
if block_given?
|
|
117
|
-
block.call(err)
|
|
118
|
-
else
|
|
181
|
+
argument_values = {}
|
|
182
|
+
resolved_args_count = 0
|
|
183
|
+
raised_error = false
|
|
184
|
+
arg_defns.each do |arg_name, arg_defn|
|
|
185
|
+
context.dataloader.append_job do
|
|
186
|
+
begin
|
|
187
|
+
arg_defn.coerce_into_values(parent_object, values, context, argument_values)
|
|
188
|
+
rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => err
|
|
189
|
+
raised_error = true
|
|
119
190
|
finished_args = err
|
|
191
|
+
if block_given?
|
|
192
|
+
block.call(finished_args)
|
|
193
|
+
end
|
|
120
194
|
end
|
|
121
|
-
end
|
|
122
195
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
196
|
+
resolved_args_count += 1
|
|
197
|
+
if resolved_args_count == total_args_count && !raised_error
|
|
198
|
+
finished_args = context.schema.after_any_lazies(argument_values.values) {
|
|
199
|
+
GraphQL::Execution::Interpreter::Arguments.new(
|
|
200
|
+
argument_values: argument_values,
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
if block_given?
|
|
204
|
+
block.call(finished_args)
|
|
205
|
+
end
|
|
133
206
|
end
|
|
134
207
|
end
|
|
135
208
|
end
|
|
136
209
|
end
|
|
210
|
+
}
|
|
137
211
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
212
|
+
if block_given?
|
|
213
|
+
prepare_finished_args.call
|
|
214
|
+
nil
|
|
215
|
+
else
|
|
216
|
+
# This API returns eagerly, gotta run it now
|
|
217
|
+
context.dataloader.run_isolated(&prepare_finished_args)
|
|
218
|
+
finished_args
|
|
145
219
|
end
|
|
146
220
|
end
|
|
147
221
|
|
|
@@ -159,7 +233,7 @@ module GraphQL
|
|
|
159
233
|
def arguments_statically_coercible?
|
|
160
234
|
return @arguments_statically_coercible if defined?(@arguments_statically_coercible)
|
|
161
235
|
|
|
162
|
-
@arguments_statically_coercible =
|
|
236
|
+
@arguments_statically_coercible = all_argument_definitions.all?(&:statically_coercible?)
|
|
163
237
|
end
|
|
164
238
|
|
|
165
239
|
module ArgumentClassAccessor
|
|
@@ -186,12 +260,20 @@ module GraphQL
|
|
|
186
260
|
context.schema.object_from_id(id, context)
|
|
187
261
|
end
|
|
188
262
|
|
|
189
|
-
def load_application_object(argument,
|
|
263
|
+
def load_application_object(argument, id, context)
|
|
190
264
|
# See if any object can be found for this ID
|
|
191
265
|
if id.nil?
|
|
192
266
|
return nil
|
|
193
267
|
end
|
|
194
|
-
|
|
268
|
+
object_from_id(argument.loads, id, context)
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def load_and_authorize_application_object(argument, id, context)
|
|
272
|
+
loaded_application_object = load_application_object(argument, id, context)
|
|
273
|
+
authorize_application_object(argument, id, context, loaded_application_object)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def authorize_application_object(argument, id, context, loaded_application_object)
|
|
195
277
|
context.schema.after_lazy(loaded_application_object) do |application_object|
|
|
196
278
|
if application_object.nil?
|
|
197
279
|
err = GraphQL::LoadApplicationObjectFailedError.new(argument: argument, id: id, object: application_object)
|
|
@@ -199,9 +281,9 @@ module GraphQL
|
|
|
199
281
|
end
|
|
200
282
|
# Double-check that the located object is actually of this type
|
|
201
283
|
# (Don't want to allow arbitrary access to objects this way)
|
|
202
|
-
resolved_application_object_type = context.schema.resolve_type(
|
|
284
|
+
resolved_application_object_type = context.schema.resolve_type(argument.loads, application_object, context)
|
|
203
285
|
context.schema.after_lazy(resolved_application_object_type) do |application_object_type|
|
|
204
|
-
possible_object_types = context.warden.possible_types(
|
|
286
|
+
possible_object_types = context.warden.possible_types(argument.loads)
|
|
205
287
|
if !possible_object_types.include?(application_object_type)
|
|
206
288
|
err = GraphQL::LoadApplicationObjectFailedError.new(argument: argument, id: id, object: application_object)
|
|
207
289
|
load_application_object_failed(err)
|
|
@@ -214,11 +296,17 @@ module GraphQL
|
|
|
214
296
|
if authed
|
|
215
297
|
application_object
|
|
216
298
|
else
|
|
217
|
-
|
|
299
|
+
err = GraphQL::UnauthorizedError.new(
|
|
218
300
|
object: application_object,
|
|
219
301
|
type: class_based_type,
|
|
220
302
|
context: context,
|
|
221
303
|
)
|
|
304
|
+
if self.respond_to?(:unauthorized_object)
|
|
305
|
+
err.set_backtrace(caller)
|
|
306
|
+
unauthorized_object(err)
|
|
307
|
+
else
|
|
308
|
+
raise err
|
|
309
|
+
end
|
|
222
310
|
end
|
|
223
311
|
end
|
|
224
312
|
else
|
|
@@ -7,7 +7,7 @@ module GraphQL
|
|
|
7
7
|
# @return [String, nil] Explains why this member was deprecated (if present, this will be marked deprecated in introspection)
|
|
8
8
|
def deprecation_reason
|
|
9
9
|
dir = self.directives.find { |d| d.is_a?(GraphQL::Schema::Directive::Deprecated) }
|
|
10
|
-
dir && dir.arguments[:reason]
|
|
10
|
+
dir && dir.arguments[:reason] # rubocop:disable Development/ContextIsPassedCop -- definition-related
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
# Set the deprecation reason for this member, or remove it by assigning `nil`
|