graphql 1.13.0 → 1.13.24
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 -8
- data/lib/generators/graphql/enum_generator.rb +4 -10
- data/lib/generators/graphql/field_extractor.rb +31 -0
- data/lib/generators/graphql/input_generator.rb +50 -0
- data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
- data/lib/generators/graphql/install_generator.rb +10 -3
- data/lib/generators/graphql/interface_generator.rb +7 -7
- data/lib/generators/graphql/mutation_create_generator.rb +22 -0
- data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
- data/lib/generators/graphql/mutation_generator.rb +5 -30
- data/lib/generators/graphql/mutation_update_generator.rb +22 -0
- data/lib/generators/graphql/object_generator.rb +8 -37
- data/lib/generators/graphql/orm_mutations_base.rb +40 -0
- data/lib/generators/graphql/scalar_generator.rb +4 -2
- data/lib/generators/graphql/templates/enum.erb +5 -1
- data/lib/generators/graphql/templates/input.erb +9 -0
- data/lib/generators/graphql/templates/interface.erb +4 -2
- data/lib/generators/graphql/templates/mutation.erb +1 -1
- data/lib/generators/graphql/templates/mutation_create.erb +20 -0
- data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
- data/lib/generators/graphql/templates/mutation_update.erb +21 -0
- data/lib/generators/graphql/templates/object.erb +4 -2
- data/lib/generators/graphql/templates/scalar.erb +3 -1
- data/lib/generators/graphql/templates/union.erb +4 -2
- data/lib/generators/graphql/type_generator.rb +46 -9
- data/lib/generators/graphql/union_generator.rb +5 -5
- data/lib/graphql/analysis/ast/field_usage.rb +6 -2
- data/lib/graphql/analysis/ast/visitor.rb +2 -1
- data/lib/graphql/argument.rb +1 -1
- data/lib/graphql/base_type.rb +5 -3
- data/lib/graphql/boolean_type.rb +1 -1
- data/lib/graphql/dataloader/source.rb +2 -2
- data/lib/graphql/date_encoding_error.rb +16 -0
- data/lib/graphql/define/instance_definable.rb +15 -0
- 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 +1 -1
- data/lib/graphql/enum_type.rb +2 -2
- data/lib/graphql/execution/interpreter/arguments_cache.rb +4 -2
- data/lib/graphql/execution/interpreter/runtime.rb +48 -28
- data/lib/graphql/execution/multiplex.rb +3 -0
- data/lib/graphql/field.rb +1 -1
- data/lib/graphql/float_type.rb +1 -1
- data/lib/graphql/id_type.rb +1 -1
- data/lib/graphql/input_object_type.rb +1 -1
- data/lib/graphql/int_type.rb +1 -1
- data/lib/graphql/interface_type.rb +1 -1
- data/lib/graphql/introspection/directive_location_enum.rb +2 -2
- data/lib/graphql/introspection/directive_type.rb +4 -2
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +7 -2
- data/lib/graphql/introspection/type_type.rb +14 -8
- data/lib/graphql/introspection.rb +4 -1
- data/lib/graphql/language/block_string.rb +2 -2
- data/lib/graphql/language/document_from_schema_definition.rb +8 -3
- data/lib/graphql/language/lexer.rb +50 -25
- data/lib/graphql/language/lexer.rl +2 -0
- data/lib/graphql/language/nodes.rb +15 -3
- data/lib/graphql/language/parser.rb +829 -816
- data/lib/graphql/language/parser.y +8 -2
- data/lib/graphql/language/printer.rb +4 -0
- data/lib/graphql/object_type.rb +2 -2
- data/lib/graphql/pagination/active_record_relation_connection.rb +43 -6
- data/lib/graphql/pagination/relation_connection.rb +59 -29
- data/lib/graphql/query/context.rb +10 -0
- data/lib/graphql/query/input_validation_result.rb +9 -0
- data/lib/graphql/query/validation_pipeline.rb +2 -3
- data/lib/graphql/query/variable_validation_error.rb +2 -2
- data/lib/graphql/query/variables.rb +30 -3
- data/lib/graphql/query.rb +0 -1
- data/lib/graphql/relay/connection_type.rb +15 -2
- data/lib/graphql/relay/global_id_resolve.rb +1 -2
- data/lib/graphql/relay/mutation.rb +1 -1
- data/lib/graphql/relay/page_info.rb +1 -1
- data/lib/graphql/relay/range_add.rb +4 -0
- data/lib/graphql/rubocop/graphql/default_required_true.rb +4 -4
- data/lib/graphql/scalar_type.rb +1 -1
- data/lib/graphql/schema/argument.rb +29 -16
- data/lib/graphql/schema/build_from_definition.rb +9 -7
- data/lib/graphql/schema/directive.rb +25 -2
- data/lib/graphql/schema/enum.rb +4 -3
- data/lib/graphql/schema/enum_value.rb +3 -1
- data/lib/graphql/schema/field.rb +196 -92
- data/lib/graphql/schema/field_extension.rb +89 -2
- data/lib/graphql/schema/input_object.rb +27 -9
- data/lib/graphql/schema/interface.rb +8 -2
- data/lib/graphql/schema/introspection_system.rb +1 -1
- data/lib/graphql/schema/list.rb +21 -4
- data/lib/graphql/schema/loader.rb +3 -0
- data/lib/graphql/schema/member/accepts_definition.rb +7 -2
- data/lib/graphql/schema/member/base_dsl_methods.rb +1 -1
- data/lib/graphql/schema/member/cached_graphql_definition.rb +29 -2
- data/lib/graphql/schema/member/has_arguments.rb +2 -2
- data/lib/graphql/schema/member/has_fields.rb +1 -1
- data/lib/graphql/schema/member/has_interfaces.rb +11 -1
- data/lib/graphql/schema/member/validates_input.rb +2 -2
- data/lib/graphql/schema/non_null.rb +9 -3
- data/lib/graphql/schema/object.rb +3 -1
- data/lib/graphql/schema/relay_classic_mutation.rb +8 -0
- data/lib/graphql/schema/resolver.rb +19 -13
- data/lib/graphql/schema/scalar.rb +15 -1
- data/lib/graphql/schema/traversal.rb +1 -1
- data/lib/graphql/schema/union.rb +2 -0
- data/lib/graphql/schema/validator/required_validator.rb +29 -15
- data/lib/graphql/schema/validator.rb +4 -7
- data/lib/graphql/schema/warden.rb +11 -2
- data/lib/graphql/schema.rb +34 -10
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/base_visitor.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +14 -7
- 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/unique_directives_per_location.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +6 -0
- data/lib/graphql/static_validation/validation_context.rb +4 -0
- data/lib/graphql/string_type.rb +1 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +2 -0
- data/lib/graphql/subscriptions/serialize.rb +22 -2
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +6 -20
- data/lib/graphql/tracing/data_dog_tracing.rb +24 -15
- data/lib/graphql/tracing/notifications_tracing.rb +59 -0
- data/lib/graphql/tracing/platform_tracing.rb +20 -10
- data/lib/graphql/types/iso_8601_date.rb +13 -5
- data/lib/graphql/types/iso_8601_date_time.rb +8 -1
- data/lib/graphql/types/relay/connection_behaviors.rb +28 -10
- 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/node_field.rb +2 -3
- data/lib/graphql/types/relay/nodes_field.rb +19 -3
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/union_type.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +14 -1
- metadata +56 -30
- /data/lib/generators/graphql/{templates → install/templates}/base_mutation.erb +0 -0
- /data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +0 -0
@@ -15,23 +15,110 @@ module GraphQL
|
|
15
15
|
# @return [Object]
|
16
16
|
attr_reader :options
|
17
17
|
|
18
|
+
# @return [Array<Symbol>, nil] `default_argument`s added, if any were added (otherwise, `nil`)
|
19
|
+
attr_reader :added_default_arguments
|
20
|
+
|
18
21
|
# Called when the extension is mounted with `extension(name, options)`.
|
19
|
-
# The instance
|
22
|
+
# The instance will be frozen to avoid improper use of state during execution.
|
20
23
|
# @param field [GraphQL::Schema::Field] The field where this extension was mounted
|
21
24
|
# @param options [Object] The second argument to `extension`, or `{}` if nothing was passed.
|
22
25
|
def initialize(field:, options:)
|
23
26
|
@field = field
|
24
27
|
@options = options || {}
|
28
|
+
@added_default_arguments = nil
|
25
29
|
apply
|
26
|
-
freeze
|
27
30
|
end
|
28
31
|
|
32
|
+
class << self
|
33
|
+
# @return [Array(Array, Hash), nil] A list of default argument configs, or `nil` if there aren't any
|
34
|
+
def default_argument_configurations
|
35
|
+
args = superclass.respond_to?(:default_argument_configurations) ? superclass.default_argument_configurations : nil
|
36
|
+
if @own_default_argument_configurations
|
37
|
+
if args
|
38
|
+
args.concat(@own_default_argument_configurations)
|
39
|
+
else
|
40
|
+
args = @own_default_argument_configurations.dup
|
41
|
+
end
|
42
|
+
end
|
43
|
+
args
|
44
|
+
end
|
45
|
+
|
46
|
+
# @see Argument#initialize
|
47
|
+
# @see HasArguments#argument
|
48
|
+
def default_argument(*argument_args, **argument_kwargs)
|
49
|
+
configs = @own_default_argument_configurations ||= []
|
50
|
+
configs << [argument_args, argument_kwargs]
|
51
|
+
end
|
52
|
+
|
53
|
+
# If configured, these `extras` will be added to the field if they aren't already present,
|
54
|
+
# but removed by from `arguments` before the field's `resolve` is called.
|
55
|
+
# (The extras _will_ be present for other extensions, though.)
|
56
|
+
#
|
57
|
+
# @param new_extras [Array<Symbol>] If provided, assign extras used by this extension
|
58
|
+
# @return [Array<Symbol>] any extras assigned to this extension
|
59
|
+
def extras(new_extras = nil)
|
60
|
+
if new_extras
|
61
|
+
@own_extras = new_extras
|
62
|
+
end
|
63
|
+
|
64
|
+
inherited_extras = self.superclass.respond_to?(:extras) ? superclass.extras : nil
|
65
|
+
if @own_extras
|
66
|
+
if inherited_extras
|
67
|
+
inherited_extras + @own_extras
|
68
|
+
else
|
69
|
+
@own_extras
|
70
|
+
end
|
71
|
+
elsif inherited_extras
|
72
|
+
inherited_extras
|
73
|
+
else
|
74
|
+
NO_EXTRAS
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
NO_EXTRAS = [].freeze
|
80
|
+
private_constant :NO_EXTRAS
|
81
|
+
|
29
82
|
# Called when this extension is attached to a field.
|
30
83
|
# The field definition may be extended during this method.
|
31
84
|
# @return [void]
|
32
85
|
def apply
|
33
86
|
end
|
34
87
|
|
88
|
+
# Called after the field's definition block has been executed.
|
89
|
+
# (Any arguments from the block are present on `field`)
|
90
|
+
# @return [void]
|
91
|
+
def after_define
|
92
|
+
end
|
93
|
+
|
94
|
+
# @api private
|
95
|
+
def after_define_apply
|
96
|
+
after_define
|
97
|
+
if (configs = self.class.default_argument_configurations)
|
98
|
+
existing_keywords = field.all_argument_definitions.map(&:keyword)
|
99
|
+
existing_keywords.uniq!
|
100
|
+
@added_default_arguments = []
|
101
|
+
configs.each do |config|
|
102
|
+
argument_args, argument_kwargs = config
|
103
|
+
arg_name = argument_args[0]
|
104
|
+
if !existing_keywords.include?(arg_name)
|
105
|
+
@added_default_arguments << arg_name
|
106
|
+
field.argument(*argument_args, **argument_kwargs)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
if (extras = self.class.extras).any?
|
111
|
+
@added_extras = extras - field.extras
|
112
|
+
field.extras(@added_extras)
|
113
|
+
else
|
114
|
+
@added_extras = nil
|
115
|
+
end
|
116
|
+
freeze
|
117
|
+
end
|
118
|
+
|
119
|
+
# @api private
|
120
|
+
attr_reader :added_extras
|
121
|
+
|
35
122
|
# Called before resolving {#field}. It should either:
|
36
123
|
#
|
37
124
|
# - `yield` values to continue execution; OR
|
@@ -79,6 +79,21 @@ module GraphQL
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
+
def self.authorized?(obj, value, ctx)
|
83
|
+
# Authorize each argument (but this doesn't apply if `prepare` is implemented):
|
84
|
+
if value.respond_to?(:key?)
|
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
|
+
|
82
97
|
def unwrap_value(value)
|
83
98
|
case value
|
84
99
|
when Array
|
@@ -123,15 +138,12 @@ module GraphQL
|
|
123
138
|
def argument(*args, **kwargs, &block)
|
124
139
|
argument_defn = super(*args, **kwargs, &block)
|
125
140
|
# Add a method access
|
126
|
-
|
127
|
-
class_eval <<-RUBY, __FILE__, __LINE__
|
128
|
-
def #{method_name}
|
129
|
-
self[#{method_name.inspect}]
|
130
|
-
end
|
131
|
-
RUBY
|
141
|
+
define_accessor_method(argument_defn.keyword)
|
132
142
|
argument_defn
|
133
143
|
end
|
134
144
|
|
145
|
+
prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
|
146
|
+
|
135
147
|
def to_graphql
|
136
148
|
type_defn = GraphQL::InputObjectType.new
|
137
149
|
type_defn.name = graphql_name
|
@@ -140,7 +152,7 @@ module GraphQL
|
|
140
152
|
type_defn.mutation = mutation
|
141
153
|
type_defn.ast_node = ast_node
|
142
154
|
all_argument_definitions.each do |arg|
|
143
|
-
type_defn.arguments[arg.graphql_definition.name] = arg.graphql_definition # rubocop:disable Development/ContextIsPassedCop -- legacy-related
|
155
|
+
type_defn.arguments[arg.graphql_definition(silence_deprecation_warning: true).name] = arg.graphql_definition(silence_deprecation_warning: true) # rubocop:disable Development/ContextIsPassedCop -- legacy-related
|
144
156
|
end
|
145
157
|
# Make a reference to a classic-style Arguments class
|
146
158
|
self.arguments_class = GraphQL::Query::Arguments.construct_arguments_class(type_defn)
|
@@ -156,9 +168,8 @@ module GraphQL
|
|
156
168
|
# @api private
|
157
169
|
INVALID_OBJECT_MESSAGE = "Expected %{object} to be a key-value object responding to `to_h` or `to_unsafe_h`."
|
158
170
|
|
159
|
-
def validate_non_null_input(input, ctx)
|
171
|
+
def validate_non_null_input(input, ctx, max_errors: nil)
|
160
172
|
result = GraphQL::Query::InputValidationResult.new
|
161
|
-
|
162
173
|
warden = ctx.warden
|
163
174
|
|
164
175
|
if input.is_a?(Array)
|
@@ -237,6 +248,13 @@ module GraphQL
|
|
237
248
|
|
238
249
|
result
|
239
250
|
end
|
251
|
+
|
252
|
+
private
|
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
|
240
258
|
end
|
241
259
|
|
242
260
|
private
|
@@ -81,7 +81,11 @@ module GraphQL
|
|
81
81
|
end
|
82
82
|
elsif child_class < GraphQL::Schema::Object
|
83
83
|
# This is being included into an object type, make sure it's using `implements(...)`
|
84
|
-
backtrace_line =
|
84
|
+
backtrace_line = caller_locations(0, 10).find do |location|
|
85
|
+
location.base_label == "implements" &&
|
86
|
+
location.path.end_with?("schema/member/has_interfaces.rb")
|
87
|
+
end
|
88
|
+
|
85
89
|
if !backtrace_line
|
86
90
|
raise "Attach interfaces using `implements(#{self})`, not `include(#{self})`"
|
87
91
|
end
|
@@ -100,6 +104,8 @@ module GraphQL
|
|
100
104
|
end
|
101
105
|
end
|
102
106
|
|
107
|
+
prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
|
108
|
+
|
103
109
|
def to_graphql
|
104
110
|
type_defn = GraphQL::InterfaceType.new
|
105
111
|
type_defn.name = graphql_name
|
@@ -108,7 +114,7 @@ module GraphQL
|
|
108
114
|
type_defn.type_membership_class = self.type_membership_class
|
109
115
|
type_defn.ast_node = ast_node
|
110
116
|
fields.each do |field_name, field_inst| # rubocop:disable Development/ContextIsPassedCop -- legacy-related
|
111
|
-
field_defn = field_inst.graphql_definition
|
117
|
+
field_defn = field_inst.graphql_definition(silence_deprecation_warning: true)
|
112
118
|
type_defn.fields[field_defn.name] = field_defn # rubocop:disable Development/ContextIsPassedCop -- legacy-related
|
113
119
|
end
|
114
120
|
type_defn.metadata[:type_class] = self
|
@@ -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]
|
@@ -49,15 +51,24 @@ module GraphQL
|
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
52
|
-
def validate_non_null_input(value, ctx)
|
54
|
+
def validate_non_null_input(value, ctx, max_errors: nil)
|
53
55
|
result = GraphQL::Query::InputValidationResult.new
|
54
56
|
ensure_array(value).each_with_index do |item, index|
|
55
57
|
item_result = of_type.validate_input(item, ctx)
|
56
|
-
|
58
|
+
unless item_result.valid?
|
59
|
+
if max_errors
|
60
|
+
if max_errors == 0
|
61
|
+
add_max_errros_reached_message(result)
|
62
|
+
break
|
63
|
+
end
|
64
|
+
|
65
|
+
max_errors -= 1
|
66
|
+
end
|
67
|
+
|
57
68
|
result.merge_result!(index, item_result)
|
58
69
|
end
|
59
70
|
end
|
60
|
-
result
|
71
|
+
result.valid? ? nil : result
|
61
72
|
end
|
62
73
|
|
63
74
|
private
|
@@ -70,6 +81,12 @@ module GraphQL
|
|
70
81
|
[value]
|
71
82
|
end
|
72
83
|
end
|
84
|
+
|
85
|
+
def add_max_errros_reached_message(result)
|
86
|
+
message = "Too many errors processing list variable, max validation error limit reached. Execution aborted"
|
87
|
+
item_result = GraphQL::Query::InputValidationResult.from_problem(message)
|
88
|
+
result.merge_result!(nil, item_result)
|
89
|
+
end
|
73
90
|
end
|
74
91
|
end
|
75
92
|
end
|
@@ -34,6 +34,7 @@ module GraphQL
|
|
34
34
|
Class.new(GraphQL::Schema) do
|
35
35
|
orphan_types(types.values)
|
36
36
|
directives(directives)
|
37
|
+
description(schema["description"])
|
37
38
|
|
38
39
|
def self.resolve_type(*)
|
39
40
|
raise(GraphQL::RequiredImplementationMissingError, "This schema was loaded from string, so it can't resolve types for objects")
|
@@ -141,6 +142,7 @@ module GraphQL
|
|
141
142
|
Class.new(GraphQL::Schema::Scalar) do
|
142
143
|
graphql_name(type["name"])
|
143
144
|
description(type["description"])
|
145
|
+
specified_by_url(type["specifiedByUrl"])
|
144
146
|
end
|
145
147
|
end
|
146
148
|
when "UNION"
|
@@ -160,6 +162,7 @@ module GraphQL
|
|
160
162
|
graphql_name(directive["name"])
|
161
163
|
description(directive["description"])
|
162
164
|
locations(*directive["locations"].map(&:to_sym))
|
165
|
+
repeatable(directive["isRepeatable"])
|
163
166
|
loader.build_arguments(self, directive["args"], type_resolver)
|
164
167
|
end
|
165
168
|
end
|
@@ -123,8 +123,13 @@ module GraphQL
|
|
123
123
|
end
|
124
124
|
|
125
125
|
module ToGraphQLExtension
|
126
|
-
def to_graphql
|
127
|
-
|
126
|
+
def to_graphql(*args, **kwargs)
|
127
|
+
|
128
|
+
defn = if args.empty? && kwargs.empty?
|
129
|
+
super()
|
130
|
+
else
|
131
|
+
super
|
132
|
+
end
|
128
133
|
accepts_definition_methods.each do |method_name|
|
129
134
|
value = public_send(method_name)
|
130
135
|
if !value.nil?
|
@@ -108,7 +108,7 @@ module GraphQL
|
|
108
108
|
@default_graphql_name ||= begin
|
109
109
|
raise GraphQL::RequiredImplementationMissingError, 'Anonymous class should declare a `graphql_name`' if name.nil?
|
110
110
|
|
111
|
-
name.split("::").last.sub(/Type\Z/, "")
|
111
|
+
-name.split("::").last.sub(/Type\Z/, "")
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
@@ -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
|
@@ -167,7 +167,7 @@ module GraphQL
|
|
167
167
|
# @return [Interpreter::Arguments, Execution::Lazy<Interpeter::Arguments>]
|
168
168
|
def coerce_arguments(parent_object, values, context, &block)
|
169
169
|
# Cache this hash to avoid re-merging it
|
170
|
-
arg_defns =
|
170
|
+
arg_defns = context.warden.arguments(self)
|
171
171
|
total_args_count = arg_defns.size
|
172
172
|
|
173
173
|
finished_args = nil
|
@@ -181,7 +181,7 @@ module GraphQL
|
|
181
181
|
argument_values = {}
|
182
182
|
resolved_args_count = 0
|
183
183
|
raised_error = false
|
184
|
-
arg_defns.each do |
|
184
|
+
arg_defns.each do |arg_defn|
|
185
185
|
context.dataloader.append_job do
|
186
186
|
begin
|
187
187
|
arg_defn.coerce_into_values(parent_object, values, context, argument_values)
|
@@ -134,7 +134,7 @@ module GraphQL
|
|
134
134
|
if type.respond_to?(:kind) && type.kind.interface?
|
135
135
|
implements_this_interface = false
|
136
136
|
implementation_is_visible = false
|
137
|
-
interface_type_memberships.each do |tm|
|
137
|
+
warden.interface_type_memberships(self, context).each do |tm|
|
138
138
|
if tm.abstract_type == type
|
139
139
|
implements_this_interface ||= true
|
140
140
|
if warden.visible_type_membership?(tm, context)
|
@@ -57,7 +57,17 @@ module GraphQL
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def interface_type_memberships
|
60
|
-
|
60
|
+
own_tms = own_interface_type_memberships
|
61
|
+
if (self.is_a?(Class) && superclass.respond_to?(:interface_type_memberships))
|
62
|
+
inherited_tms = superclass.interface_type_memberships
|
63
|
+
if inherited_tms.size > 0
|
64
|
+
own_tms + inherited_tms
|
65
|
+
else
|
66
|
+
own_tms
|
67
|
+
end
|
68
|
+
else
|
69
|
+
own_tms
|
70
|
+
end
|
61
71
|
end
|
62
72
|
|
63
73
|
# param context [Query::Context] If omitted, skip filtering.
|
@@ -8,11 +8,11 @@ module GraphQL
|
|
8
8
|
validate_input(val, ctx).valid?
|
9
9
|
end
|
10
10
|
|
11
|
-
def validate_input(val, ctx)
|
11
|
+
def validate_input(val, ctx, max_errors: nil)
|
12
12
|
if val.nil?
|
13
13
|
GraphQL::Query::InputValidationResult.new
|
14
14
|
else
|
15
|
-
validate_non_null_input(val, ctx)
|
15
|
+
validate_non_null_input(val, ctx, max_errors: max_errors) || Query::InputValidationResult::VALID
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -8,8 +8,10 @@ module GraphQL
|
|
8
8
|
class NonNull < 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_non_null_type
|
14
|
+
@of_type.graphql_definition(silence_deprecation_warning: true).to_non_null_type
|
13
15
|
end
|
14
16
|
|
15
17
|
# @return [GraphQL::TypeKinds::NON_NULL]
|
@@ -35,13 +37,13 @@ module GraphQL
|
|
35
37
|
"#<#{self.class.name} @of_type=#{@of_type.inspect}>"
|
36
38
|
end
|
37
39
|
|
38
|
-
def validate_input(value, ctx)
|
40
|
+
def validate_input(value, ctx, max_errors: nil)
|
39
41
|
if value.nil?
|
40
42
|
result = GraphQL::Query::InputValidationResult.new
|
41
43
|
result.add_problem("Expected value to not be null")
|
42
44
|
result
|
43
45
|
else
|
44
|
-
of_type.validate_input(value, ctx)
|
46
|
+
of_type.validate_input(value, ctx, max_errors: max_errors)
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
@@ -51,6 +53,10 @@ module GraphQL
|
|
51
53
|
end
|
52
54
|
|
53
55
|
def coerce_input(value, ctx)
|
56
|
+
# `.validate_input` above is used for variables, but this method is used for arguments
|
57
|
+
if value.nil?
|
58
|
+
raise GraphQL::ExecutionError, "`null` is not a valid input for `#{to_type_signature}`, please provide a value for this argument."
|
59
|
+
end
|
54
60
|
of_type.coerce_input(value, ctx)
|
55
61
|
end
|
56
62
|
|
@@ -122,6 +122,8 @@ module GraphQL
|
|
122
122
|
all_fields
|
123
123
|
end
|
124
124
|
|
125
|
+
prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
|
126
|
+
|
125
127
|
# @return [GraphQL::ObjectType]
|
126
128
|
def to_graphql
|
127
129
|
obj_type = GraphQL::ObjectType.new
|
@@ -132,7 +134,7 @@ module GraphQL
|
|
132
134
|
obj_type.mutation = mutation
|
133
135
|
obj_type.ast_node = ast_node
|
134
136
|
fields.each do |field_name, field_inst| # rubocop:disable Development/ContextIsPassedCop -- legacy-related
|
135
|
-
field_defn = field_inst.to_graphql
|
137
|
+
field_defn = field_inst.to_graphql(silence_deprecation_warning: true)
|
136
138
|
obj_type.fields[field_defn.name] = field_defn # rubocop:disable Development/ContextIsPassedCop -- legacy-related
|
137
139
|
end
|
138
140
|
|
@@ -155,6 +155,14 @@ module GraphQL
|
|
155
155
|
end
|
156
156
|
end
|
157
157
|
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def authorize_arguments(args, values)
|
162
|
+
# remove the `input` wrapper to match values
|
163
|
+
input_args = args["input"].type.unwrap.arguments(context)
|
164
|
+
super(input_args, values)
|
165
|
+
end
|
158
166
|
end
|
159
167
|
end
|
160
168
|
end
|
@@ -145,19 +145,9 @@ module GraphQL
|
|
145
145
|
# @raise [GraphQL::UnauthorizedError] To signal an authorization failure
|
146
146
|
# @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
|
147
147
|
def authorized?(**inputs)
|
148
|
-
self.class
|
149
|
-
|
150
|
-
|
151
|
-
arg_auth, err = argument.authorized?(self, arg_value, context)
|
152
|
-
if !arg_auth
|
153
|
-
return arg_auth, err
|
154
|
-
else
|
155
|
-
true
|
156
|
-
end
|
157
|
-
else
|
158
|
-
true
|
159
|
-
end
|
160
|
-
end
|
148
|
+
arg_owner = @field # || self.class
|
149
|
+
args = arg_owner.arguments(context)
|
150
|
+
authorize_arguments(args, inputs)
|
161
151
|
end
|
162
152
|
|
163
153
|
# Called when an object loaded by `loads:` fails the `.authorized?` check for its resolved GraphQL object type.
|
@@ -172,6 +162,22 @@ module GraphQL
|
|
172
162
|
|
173
163
|
private
|
174
164
|
|
165
|
+
def authorize_arguments(args, inputs)
|
166
|
+
args.each_value do |argument|
|
167
|
+
arg_keyword = argument.keyword
|
168
|
+
if inputs.key?(arg_keyword) && !(arg_value = inputs[arg_keyword]).nil? && (arg_value != argument.default_value)
|
169
|
+
arg_auth, err = argument.authorized?(self, arg_value, context)
|
170
|
+
if !arg_auth
|
171
|
+
return arg_auth, err
|
172
|
+
else
|
173
|
+
true
|
174
|
+
end
|
175
|
+
else
|
176
|
+
true
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
175
181
|
def load_arguments(args)
|
176
182
|
prepared_args = {}
|
177
183
|
prepare_lazies = []
|
@@ -14,6 +14,8 @@ module GraphQL
|
|
14
14
|
val
|
15
15
|
end
|
16
16
|
|
17
|
+
prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
|
18
|
+
|
17
19
|
def to_graphql
|
18
20
|
type_defn = GraphQL::ScalarType.new
|
19
21
|
type_defn.name = graphql_name
|
@@ -30,6 +32,18 @@ module GraphQL
|
|
30
32
|
GraphQL::TypeKinds::SCALAR
|
31
33
|
end
|
32
34
|
|
35
|
+
def specified_by_url(new_url = nil)
|
36
|
+
if new_url
|
37
|
+
@specified_by_url = new_url
|
38
|
+
elsif defined?(@specified_by_url)
|
39
|
+
@specified_by_url
|
40
|
+
elsif superclass.respond_to?(:specified_by_url)
|
41
|
+
superclass.specified_by_url
|
42
|
+
else
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
33
47
|
def default_scalar(is_default = nil)
|
34
48
|
if !is_default.nil?
|
35
49
|
@default_scalar = is_default
|
@@ -41,7 +55,7 @@ module GraphQL
|
|
41
55
|
@default_scalar ||= false
|
42
56
|
end
|
43
57
|
|
44
|
-
def validate_non_null_input(value, ctx)
|
58
|
+
def validate_non_null_input(value, ctx, max_errors: nil)
|
45
59
|
result = Query::InputValidationResult.new
|
46
60
|
coerced_result = begin
|
47
61
|
ctx.query.with_error_handling do
|
@@ -173,7 +173,7 @@ Some late-bound types couldn't be resolved:
|
|
173
173
|
end
|
174
174
|
when Class
|
175
175
|
if member.respond_to?(:graphql_definition)
|
176
|
-
graphql_member = member.graphql_definition
|
176
|
+
graphql_member = member.graphql_definition(silence_deprecation_warning: true)
|
177
177
|
visit(schema, graphql_member, context_description)
|
178
178
|
else
|
179
179
|
raise GraphQL::Schema::InvalidTypeError.new("Unexpected traversal member: #{member} (#{member.class.name})")
|
data/lib/graphql/schema/union.rb
CHANGED