graphql 2.6.1 → 2.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/graphql/analysis/query_complexity.rb +29 -13
- data/lib/graphql/backtrace/table.rb +10 -1
- data/lib/graphql/current.rb +7 -1
- data/lib/graphql/dataloader.rb +1 -1
- data/lib/graphql/execution/directive_checks.rb +2 -0
- data/lib/graphql/execution/field_resolve_step.rb +178 -65
- data/lib/graphql/execution/finalize.rb +21 -8
- data/lib/graphql/execution/input_values.rb +110 -38
- data/lib/graphql/execution/interpreter/arguments_cache.rb +3 -0
- data/lib/graphql/execution/interpreter/runtime.rb +36 -15
- data/lib/graphql/execution/load_argument_step.rb +41 -3
- data/lib/graphql/execution/next.rb +20 -12
- data/lib/graphql/execution/prepare_object_step.rb +24 -5
- data/lib/graphql/execution/resolve_type_step.rb +27 -0
- data/lib/graphql/execution/runner.rb +65 -30
- data/lib/graphql/execution/selections_step.rb +1 -1
- data/lib/graphql/execution.rb +8 -1
- data/lib/graphql/execution_error.rb +6 -12
- data/lib/graphql/introspection/entry_points.rb +2 -2
- data/lib/graphql/introspection/schema_type.rb +6 -2
- data/lib/graphql/language/lexer.rb +1 -1
- data/lib/graphql/language/parser.rb +1 -1
- data/lib/graphql/language.rb +8 -2
- data/lib/graphql/pagination/connections.rb +1 -3
- data/lib/graphql/query.rb +2 -2
- data/lib/graphql/schema/argument.rb +3 -3
- data/lib/graphql/schema/directive/feature.rb +4 -0
- data/lib/graphql/schema/directive/transform.rb +20 -0
- data/lib/graphql/schema/has_single_input_argument.rb +24 -13
- data/lib/graphql/schema/input_object.rb +4 -0
- data/lib/graphql/schema/interface.rb +1 -1
- data/lib/graphql/schema/introspection_system.rb +6 -21
- data/lib/graphql/schema/printer.rb +1 -1
- data/lib/graphql/schema/ractor_shareable.rb +1 -0
- data/lib/graphql/schema/relay_classic_mutation.rb +16 -2
- data/lib/graphql/schema/resolver.rb +0 -7
- data/lib/graphql/schema/subscription.rb +53 -8
- data/lib/graphql/schema/timeout.rb +2 -2
- data/lib/graphql/schema/validator/allow_blank_validator.rb +3 -3
- data/lib/graphql/schema/validator/allow_null_validator.rb +3 -3
- data/lib/graphql/schema/validator/exclusion_validator.rb +2 -2
- data/lib/graphql/schema/validator/format_validator.rb +3 -3
- data/lib/graphql/schema/validator/inclusion_validator.rb +2 -2
- data/lib/graphql/schema/validator/length_validator.rb +6 -6
- data/lib/graphql/schema/validator/numericality_validator.rb +19 -19
- data/lib/graphql/schema/validator/required_validator.rb +6 -4
- data/lib/graphql/schema/validator.rb +9 -0
- data/lib/graphql/schema/visibility/profile.rb +6 -4
- data/lib/graphql/schema/visibility/visit.rb +1 -1
- data/lib/graphql/schema/visibility.rb +30 -22
- data/lib/graphql/schema.rb +31 -10
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +6 -0
- data/lib/graphql/subscriptions/event.rb +0 -1
- data/lib/graphql/tracing/perfetto_trace.rb +5 -3
- data/lib/graphql/version.rb +1 -1
- metadata +3 -2
|
@@ -30,14 +30,47 @@ module GraphQL
|
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
# @api private
|
|
34
|
+
def call_resolve(args_hash)
|
|
35
|
+
if @field_resolve_step.nil?
|
|
36
|
+
super
|
|
37
|
+
else
|
|
38
|
+
context.namespace(:subscriptions)[:update_event] = event
|
|
39
|
+
result = nil
|
|
40
|
+
unsubscribed = true
|
|
41
|
+
unsubscribed_result = nil
|
|
42
|
+
begin
|
|
43
|
+
result = super
|
|
44
|
+
unsubscribed = false
|
|
45
|
+
rescue EarlyUnsubscribe => err
|
|
46
|
+
unsubscribed_result = err.unsubscribed_result
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
if unsubscribed
|
|
51
|
+
if unsubscribed_result
|
|
52
|
+
context.namespace(:subscriptions)[:final_update] = true
|
|
53
|
+
unsubscribed_result
|
|
54
|
+
else
|
|
55
|
+
context.skip
|
|
56
|
+
end
|
|
57
|
+
else
|
|
58
|
+
result
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
33
63
|
# @api private
|
|
34
64
|
def resolve_with_support(**args)
|
|
35
65
|
@original_arguments = args # before `loads:` have been run
|
|
36
66
|
result = nil
|
|
37
67
|
unsubscribed = true
|
|
38
|
-
unsubscribed_result =
|
|
68
|
+
unsubscribed_result = nil
|
|
69
|
+
begin
|
|
39
70
|
result = super
|
|
40
71
|
unsubscribed = false
|
|
72
|
+
rescue EarlyUnsubscribe => err
|
|
73
|
+
unsubscribed_result = err.unsubscribed_result
|
|
41
74
|
end
|
|
42
75
|
|
|
43
76
|
|
|
@@ -114,7 +147,13 @@ module GraphQL
|
|
|
114
147
|
# @return [void]
|
|
115
148
|
def unsubscribe(update_value = nil)
|
|
116
149
|
context.namespace(:subscriptions)[:unsubscribed] = true
|
|
117
|
-
|
|
150
|
+
err = EarlyUnsubscribe.new
|
|
151
|
+
err.unsubscribed_result = update_value
|
|
152
|
+
raise err
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
class EarlyUnsubscribe < GraphQL::RuntimeError
|
|
156
|
+
attr_accessor :unsubscribed_result
|
|
118
157
|
end
|
|
119
158
|
|
|
120
159
|
# Call this method to provide a new subscription_scope; OR
|
|
@@ -187,12 +226,18 @@ module GraphQL
|
|
|
187
226
|
|
|
188
227
|
# @return [Subscriptions::Event] This object is used as a representation of this subscription for the backend
|
|
189
228
|
def event
|
|
190
|
-
@event ||=
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
229
|
+
@event ||= begin
|
|
230
|
+
if @original_arguments.nil? && @field_resolve_step
|
|
231
|
+
@original_arguments, _errors = @field_resolve_step.arguments_without_loads
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
Subscriptions::Event.new(
|
|
235
|
+
name: field.name,
|
|
236
|
+
arguments: @original_arguments,
|
|
237
|
+
context: context,
|
|
238
|
+
field: field,
|
|
239
|
+
)
|
|
240
|
+
end
|
|
196
241
|
end
|
|
197
242
|
end
|
|
198
243
|
end
|
|
@@ -68,7 +68,7 @@ module GraphQL
|
|
|
68
68
|
super
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
def
|
|
71
|
+
def begin_execute_field(field, _arguments, _objects, query)
|
|
72
72
|
timeout_state = query.context.namespace(@timeout).fetch(:state)
|
|
73
73
|
# If the `:state` is `false`, then `max_seconds(query)` opted out of timeout for this query.
|
|
74
74
|
if timeout_state == false
|
|
@@ -84,7 +84,7 @@ module GraphQL
|
|
|
84
84
|
|
|
85
85
|
# `handle_timeout` may have set this to be `false`
|
|
86
86
|
if timeout_state != false
|
|
87
|
-
error
|
|
87
|
+
raise error
|
|
88
88
|
else
|
|
89
89
|
super
|
|
90
90
|
end
|
|
@@ -8,7 +8,7 @@ module GraphQL
|
|
|
8
8
|
# @example Require a non-empty string for an argument
|
|
9
9
|
# argument :name, String, required: true, validate: { allow_blank: false }
|
|
10
10
|
class AllowBlankValidator < Validator
|
|
11
|
-
def initialize(allow_blank_positional, allow_blank: nil, message: "%{validated} can't be blank", **default_options)
|
|
11
|
+
def initialize(allow_blank_positional = nil, allow_blank: nil, message: "%{validated} can't be blank", **default_options)
|
|
12
12
|
@message = message
|
|
13
13
|
super(**default_options)
|
|
14
14
|
@allow_blank = allow_blank.nil? ? allow_blank_positional : allow_blank
|
|
@@ -16,10 +16,10 @@ module GraphQL
|
|
|
16
16
|
|
|
17
17
|
def validate(_object, _context, value)
|
|
18
18
|
if value.respond_to?(:blank?) && value.blank?
|
|
19
|
-
if (value.nil? && @allow_null) || @allow_blank
|
|
19
|
+
if (value.nil? && validation_parameter(@allow_null)) || validation_parameter(@allow_blank)
|
|
20
20
|
# pass
|
|
21
21
|
else
|
|
22
|
-
@message
|
|
22
|
+
validation_parameter(@message)
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
end
|
|
@@ -9,15 +9,15 @@ module GraphQL
|
|
|
9
9
|
# argument :name, String, required: false, validates: { allow_null: false }
|
|
10
10
|
class AllowNullValidator < Validator
|
|
11
11
|
MESSAGE = "%{validated} can't be null"
|
|
12
|
-
def initialize(allow_null_positional, allow_null: nil, message: MESSAGE, **default_options)
|
|
12
|
+
def initialize(allow_null_positional = nil, allow_null: nil, message: MESSAGE, **default_options)
|
|
13
13
|
@message = message
|
|
14
14
|
super(**default_options)
|
|
15
15
|
@allow_null = allow_null.nil? ? allow_null_positional : allow_null
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def validate(_object, _context, value)
|
|
19
|
-
if value.nil? &&
|
|
20
|
-
@message
|
|
19
|
+
if value.nil? && !validation_parameter(@allow_null)
|
|
20
|
+
validation_parameter(@message)
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
end
|
|
@@ -23,8 +23,8 @@ module GraphQL
|
|
|
23
23
|
def validate(_object, _context, value)
|
|
24
24
|
if permitted_empty_value?(value)
|
|
25
25
|
# pass
|
|
26
|
-
elsif @in_list.include?(value)
|
|
27
|
-
@message
|
|
26
|
+
elsif validation_parameter(@in_list).include?(value)
|
|
27
|
+
validation_parameter(@message)
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -37,9 +37,9 @@ module GraphQL
|
|
|
37
37
|
if permitted_empty_value?(value)
|
|
38
38
|
# Do nothing
|
|
39
39
|
elsif value.nil? ||
|
|
40
|
-
(@with_pattern && !value.match?(@with_pattern)) ||
|
|
41
|
-
(@without_pattern && value.match?(@without_pattern))
|
|
42
|
-
@message
|
|
40
|
+
(@with_pattern && !value.match?(validation_parameter(@with_pattern))) ||
|
|
41
|
+
(@without_pattern && value.match?(validation_parameter(@without_pattern)))
|
|
42
|
+
validation_parameter(@message)
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
end
|
|
@@ -25,8 +25,8 @@ module GraphQL
|
|
|
25
25
|
def validate(_object, _context, value)
|
|
26
26
|
if permitted_empty_value?(value)
|
|
27
27
|
# pass
|
|
28
|
-
elsif
|
|
29
|
-
@message
|
|
28
|
+
elsif !validation_parameter(@in_list).include?(value)
|
|
29
|
+
validation_parameter(@message)
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
end
|
|
@@ -45,12 +45,12 @@ module GraphQL
|
|
|
45
45
|
def validate(_object, _context, value)
|
|
46
46
|
return if permitted_empty_value?(value) # pass in this case
|
|
47
47
|
length = value.nil? ? 0 : value.length
|
|
48
|
-
if @maximum && length >
|
|
49
|
-
partial_format(@too_long, { count:
|
|
50
|
-
elsif @minimum && length <
|
|
51
|
-
partial_format(@too_short, { count:
|
|
52
|
-
elsif @is && length !=
|
|
53
|
-
partial_format(@wrong_length, { count:
|
|
48
|
+
if (current_max = validation_parameter(@maximum)) && length > current_max
|
|
49
|
+
partial_format(validation_parameter(@too_long), { count: current_max })
|
|
50
|
+
elsif (current_min = validation_parameter(@minimum)) && length < current_min
|
|
51
|
+
partial_format(validation_parameter(@too_short), { count: current_min })
|
|
52
|
+
elsif (current_is = validation_parameter(@is)) && length != current_is
|
|
53
|
+
partial_format(validation_parameter(@wrong_length), { count: current_is })
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
56
|
end
|
|
@@ -55,25 +55,25 @@ module GraphQL
|
|
|
55
55
|
if permitted_empty_value?(value)
|
|
56
56
|
# pass in this case
|
|
57
57
|
elsif value.nil? # @allow_null is handled in the parent class
|
|
58
|
-
@null_message
|
|
59
|
-
elsif @greater_than && value <=
|
|
60
|
-
partial_format(@message, { comparison: "greater than", target:
|
|
61
|
-
elsif @greater_than_or_equal_to && value <
|
|
62
|
-
partial_format(@message, { comparison: "greater than or equal to", target:
|
|
63
|
-
elsif @less_than && value >=
|
|
64
|
-
partial_format(@message, { comparison: "less than", target:
|
|
65
|
-
elsif @less_than_or_equal_to && value >
|
|
66
|
-
partial_format(@message, { comparison: "less than or equal to", target:
|
|
67
|
-
elsif @equal_to && value !=
|
|
68
|
-
partial_format(@message, { comparison: "equal to", target:
|
|
69
|
-
elsif @other_than && value ==
|
|
70
|
-
partial_format(@message, { comparison: "something other than", target:
|
|
71
|
-
elsif @even && !value.even?
|
|
72
|
-
(partial_format(@message, { comparison: "even", target: "" })).strip
|
|
73
|
-
elsif @odd && !value.odd?
|
|
74
|
-
(partial_format(@message, { comparison: "odd", target: "" })).strip
|
|
75
|
-
elsif @within &&
|
|
76
|
-
partial_format(@message, { comparison: "within", target:
|
|
58
|
+
validation_parameter(@null_message)
|
|
59
|
+
elsif (current_greater_than = validation_parameter(@greater_than)) && value <= current_greater_than
|
|
60
|
+
partial_format(validation_parameter(@message), { comparison: "greater than", target: current_greater_than })
|
|
61
|
+
elsif (current_greater_than_or_equal_to = validation_parameter(@greater_than_or_equal_to)) && value < current_greater_than_or_equal_to
|
|
62
|
+
partial_format(validation_parameter(@message), { comparison: "greater than or equal to", target: current_greater_than_or_equal_to })
|
|
63
|
+
elsif (current_less_than = validation_parameter(@less_than)) && value >= current_less_than
|
|
64
|
+
partial_format(validation_parameter(@message), { comparison: "less than", target: current_less_than })
|
|
65
|
+
elsif (current_less_than_or_equal_to = validation_parameter(@less_than_or_equal_to)) && value > current_less_than_or_equal_to
|
|
66
|
+
partial_format(validation_parameter(@message), { comparison: "less than or equal to", target: current_less_than_or_equal_to })
|
|
67
|
+
elsif (current_equal_to = validation_parameter(@equal_to)) && value != current_equal_to
|
|
68
|
+
partial_format(validation_parameter(@message), { comparison: "equal to", target: current_equal_to })
|
|
69
|
+
elsif (current_other_than = validation_parameter(@other_than)) && value == current_other_than
|
|
70
|
+
partial_format(validation_parameter(@message), { comparison: "something other than", target: current_other_than })
|
|
71
|
+
elsif validation_parameter(@even) && !value.even?
|
|
72
|
+
(partial_format(validation_parameter(@message), { comparison: "even", target: "" })).strip
|
|
73
|
+
elsif validation_parameter(@odd) && !value.odd?
|
|
74
|
+
(partial_format(validation_parameter(@message), { comparison: "odd", target: "" })).strip
|
|
75
|
+
elsif (current_within = validation_parameter(@within)) && !current_within.include?(value)
|
|
76
|
+
partial_format(validation_parameter(@message), { comparison: "within", target: current_within })
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
end
|
|
@@ -67,7 +67,8 @@ module GraphQL
|
|
|
67
67
|
no_visible_conditions = true
|
|
68
68
|
|
|
69
69
|
if !value.nil?
|
|
70
|
-
@one_of.each do |one_of_condition|
|
|
70
|
+
validation_parameter(@one_of).each do |one_of_condition|
|
|
71
|
+
one_of_condition = validation_parameter(one_of_condition)
|
|
71
72
|
case one_of_condition
|
|
72
73
|
when Symbol
|
|
73
74
|
if no_visible_conditions && visible_keywords.include?(one_of_condition)
|
|
@@ -108,7 +109,7 @@ module GraphQL
|
|
|
108
109
|
end
|
|
109
110
|
|
|
110
111
|
if no_visible_conditions
|
|
111
|
-
if @allow_all_hidden
|
|
112
|
+
if validation_parameter(@allow_all_hidden)
|
|
112
113
|
return nil
|
|
113
114
|
else
|
|
114
115
|
raise GraphQL::Error, <<~ERR
|
|
@@ -122,7 +123,7 @@ module GraphQL
|
|
|
122
123
|
if fully_matched_conditions == 1 && partially_matched_conditions == 0
|
|
123
124
|
nil # OK
|
|
124
125
|
else
|
|
125
|
-
@message || build_message(context)
|
|
126
|
+
validation_parameter(@message) || build_message(context)
|
|
126
127
|
end
|
|
127
128
|
end
|
|
128
129
|
|
|
@@ -130,8 +131,9 @@ module GraphQL
|
|
|
130
131
|
argument_definitions = context.types.arguments(@validated)
|
|
131
132
|
|
|
132
133
|
required_names = @one_of.map do |arg_keyword|
|
|
134
|
+
arg_keyword = validation_parameter(arg_keyword)
|
|
133
135
|
if arg_keyword.is_a?(Array)
|
|
134
|
-
names = arg_keyword.map { |arg| arg_keyword_to_graphql_name(argument_definitions, arg) }
|
|
136
|
+
names = arg_keyword.map { |arg| arg_keyword_to_graphql_name(argument_definitions, validation_parameter(arg)) }
|
|
135
137
|
names.compact! # hidden arguments are `nil`
|
|
136
138
|
"(" + names.join(" and ") + ")"
|
|
137
139
|
else
|
|
@@ -34,6 +34,15 @@ module GraphQL
|
|
|
34
34
|
string
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
# @return [Object] The current value to use for validation, based on `config_value` from configuration time. If a Proc is given, this calls it and returns it.
|
|
38
|
+
def validation_parameter(config_value)
|
|
39
|
+
if config_value.is_a?(Proc)
|
|
40
|
+
config_value.call
|
|
41
|
+
else
|
|
42
|
+
config_value
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
37
46
|
# @return [Boolean] `true` if `value` is `nil` and this validator has `allow_null: true` or if value is `.blank?` and this validator has `allow_blank: true`
|
|
38
47
|
def permitted_empty_value?(value)
|
|
39
48
|
(value.nil? && @allow_null) ||
|
|
@@ -290,11 +290,13 @@ module GraphQL
|
|
|
290
290
|
end
|
|
291
291
|
# Lots more to do here
|
|
292
292
|
end
|
|
293
|
-
@schema.
|
|
294
|
-
|
|
295
|
-
|
|
293
|
+
if @schema.query
|
|
294
|
+
@schema.introspection_system.entry_points.each do |f|
|
|
295
|
+
arguments(f).each do |arg|
|
|
296
|
+
argument(f, arg.graphql_name)
|
|
297
|
+
end
|
|
298
|
+
field(@schema.query, f.graphql_name)
|
|
296
299
|
end
|
|
297
|
-
field(@schema.query, f.graphql_name)
|
|
298
300
|
end
|
|
299
301
|
@schema.introspection_system.dynamic_fields.each do |f|
|
|
300
302
|
arguments(f).each do |arg|
|
|
@@ -102,7 +102,7 @@ module GraphQL
|
|
|
102
102
|
|
|
103
103
|
missed_late_types_streak = 0
|
|
104
104
|
while (owner, late_type = @late_bound_types.shift)
|
|
105
|
-
if (late_type.is_a?(String) && (type = Member::BuildType.constantize(
|
|
105
|
+
if (late_type.is_a?(String) && (type = Member::BuildType.constantize(late_type))) ||
|
|
106
106
|
(late_type.is_a?(LateBoundType) && (type = @visited_types.find { |t| t.graphql_name == late_type.graphql_name }))
|
|
107
107
|
missed_late_types_streak = 0 # might succeed next round
|
|
108
108
|
update_type_owner(owner, type)
|
|
@@ -8,11 +8,17 @@ module GraphQL
|
|
|
8
8
|
# Use this plugin to make some parts of your schema hidden from some viewers.
|
|
9
9
|
#
|
|
10
10
|
class Visibility
|
|
11
|
+
class TypeConfigurationError < GraphQL::Error
|
|
12
|
+
def initialize(config_message, config_str)
|
|
13
|
+
message = "GraphQL::Schema::Visibility already preloaded, but #{config_message} added to the schema. Move this `#{config_str}` configuration above `use(GraphQL::Schema::Visibility)"
|
|
14
|
+
super(message)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
11
17
|
# @param schema [Class<GraphQL::Schema>]
|
|
12
18
|
# @param profiles [Hash<Symbol => Hash>] A hash of `name => context` pairs for preloading visibility profiles
|
|
13
19
|
# @param preload [Boolean] if `true`, load the default schema profile and all named profiles immediately (defaults to `true` for `Rails.env.production?` and `Rails.env.staging?`)
|
|
14
20
|
# @param migration_errors [Boolean] if `true`, raise an error when `Visibility` and `Warden` return different results
|
|
15
|
-
def self.use(schema, dynamic: false, profiles: EmptyObjects::EMPTY_HASH, preload: (defined?(Rails.env) ? (Rails.env.production? || Rails.env.staging?) :
|
|
21
|
+
def self.use(schema, dynamic: false, profiles: EmptyObjects::EMPTY_HASH, preload: (defined?(Rails.env) ? (Rails.env.production? || Rails.env.staging? || nil) : false), migration_errors: false)
|
|
16
22
|
profiles&.each { |name, ctx|
|
|
17
23
|
ctx[:visibility_profile] = name
|
|
18
24
|
ctx.freeze
|
|
@@ -20,7 +26,7 @@ module GraphQL
|
|
|
20
26
|
schema.visibility = self.new(schema, dynamic: dynamic, preload: preload, profiles: profiles, migration_errors: migration_errors)
|
|
21
27
|
end
|
|
22
28
|
|
|
23
|
-
def initialize(schema, dynamic:, preload:, profiles:, migration_errors:)
|
|
29
|
+
def initialize(schema, dynamic:, preload:, profiles:, migration_errors:, configuration_inherited: false)
|
|
24
30
|
@schema = schema
|
|
25
31
|
schema.use_visibility_profile = true
|
|
26
32
|
schema.visibility_profile_class = if migration_errors
|
|
@@ -40,6 +46,7 @@ module GraphQL
|
|
|
40
46
|
@types = nil
|
|
41
47
|
@all_references = nil
|
|
42
48
|
@loaded_all = false
|
|
49
|
+
@configuration_inherited = configuration_inherited
|
|
43
50
|
if preload
|
|
44
51
|
self.preload
|
|
45
52
|
end
|
|
@@ -94,6 +101,7 @@ module GraphQL
|
|
|
94
101
|
# Root types may have been nil:
|
|
95
102
|
types_to_visit.compact!
|
|
96
103
|
ensure_all_loaded(types_to_visit)
|
|
104
|
+
@cached_profiles.clear
|
|
97
105
|
@profiles.each do |profile_name, example_ctx|
|
|
98
106
|
prof = profile_for(example_ctx)
|
|
99
107
|
prof.preload
|
|
@@ -102,41 +110,27 @@ module GraphQL
|
|
|
102
110
|
|
|
103
111
|
# @api private
|
|
104
112
|
def query_configured(query_type)
|
|
105
|
-
|
|
106
|
-
ensure_all_loaded([query_type])
|
|
107
|
-
end
|
|
113
|
+
require_if_preloaded("a query type was", "query(...)")
|
|
108
114
|
end
|
|
109
115
|
|
|
110
116
|
# @api private
|
|
111
117
|
def mutation_configured(mutation_type)
|
|
112
|
-
|
|
113
|
-
ensure_all_loaded([mutation_type])
|
|
114
|
-
end
|
|
118
|
+
require_if_preloaded("a mutation type was", "mutation(...)")
|
|
115
119
|
end
|
|
116
120
|
|
|
117
121
|
# @api private
|
|
118
122
|
def subscription_configured(subscription_type)
|
|
119
|
-
|
|
120
|
-
ensure_all_loaded([subscription_type])
|
|
121
|
-
end
|
|
123
|
+
require_if_preloaded("a mutation type was", "subscription(...)")
|
|
122
124
|
end
|
|
123
125
|
|
|
124
126
|
# @api private
|
|
125
127
|
def orphan_types_configured(orphan_types)
|
|
126
|
-
|
|
127
|
-
ensure_all_loaded(orphan_types)
|
|
128
|
-
end
|
|
128
|
+
require_if_preloaded("orphan types were", "orphan_types(...)")
|
|
129
129
|
end
|
|
130
130
|
|
|
131
131
|
# @api private
|
|
132
132
|
def introspection_system_configured(introspection_system)
|
|
133
|
-
|
|
134
|
-
introspection_types = [
|
|
135
|
-
*@schema.introspection_system.types.values,
|
|
136
|
-
*@schema.introspection_system.entry_points.map { |ep| ep.type.unwrap },
|
|
137
|
-
]
|
|
138
|
-
ensure_all_loaded(introspection_types)
|
|
139
|
-
end
|
|
133
|
+
require_if_preloaded("custom introspection was", "introspection(...)")
|
|
140
134
|
end
|
|
141
135
|
|
|
142
136
|
# Make another Visibility for `schema` based on this one
|
|
@@ -148,7 +142,8 @@ module GraphQL
|
|
|
148
142
|
dynamic: @dynamic,
|
|
149
143
|
preload: @preload,
|
|
150
144
|
profiles: @profiles,
|
|
151
|
-
migration_errors: @migration_errors
|
|
145
|
+
migration_errors: @migration_errors,
|
|
146
|
+
configuration_inherited: true,
|
|
152
147
|
)
|
|
153
148
|
end
|
|
154
149
|
|
|
@@ -196,6 +191,19 @@ module GraphQL
|
|
|
196
191
|
|
|
197
192
|
private
|
|
198
193
|
|
|
194
|
+
def require_if_preloaded(config_message, config_code)
|
|
195
|
+
case @preload
|
|
196
|
+
when false
|
|
197
|
+
# Rails.env wasn't defined, so this won't try to preload unless manually set to true
|
|
198
|
+
when true, nil
|
|
199
|
+
if @configuration_inherited
|
|
200
|
+
preload
|
|
201
|
+
else
|
|
202
|
+
raise TypeConfigurationError.new(config_message, config_code)
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
199
207
|
def ensure_all_loaded(types_to_visit)
|
|
200
208
|
while (type = types_to_visit.shift)
|
|
201
209
|
if type.kind.fields? && @preloaded_types.add?(type)
|
data/lib/graphql/schema.rb
CHANGED
|
@@ -757,6 +757,7 @@ module GraphQL
|
|
|
757
757
|
# reset this cached value:
|
|
758
758
|
@introspection_system = nil
|
|
759
759
|
introspection_system
|
|
760
|
+
self.visibility&.introspection_system_configured(introspection_system)
|
|
760
761
|
@introspection
|
|
761
762
|
else
|
|
762
763
|
@introspection || find_inherited_value(:introspection)
|
|
@@ -768,7 +769,6 @@ module GraphQL
|
|
|
768
769
|
if !@introspection_system
|
|
769
770
|
@introspection_system = Schema::IntrospectionSystem.new(self)
|
|
770
771
|
@introspection_system.resolve_late_bindings
|
|
771
|
-
self.visibility&.introspection_system_configured(@introspection_system)
|
|
772
772
|
end
|
|
773
773
|
@introspection_system
|
|
774
774
|
end
|
|
@@ -1150,17 +1150,14 @@ module GraphQL
|
|
|
1150
1150
|
attr_accessor :using_backtrace
|
|
1151
1151
|
|
|
1152
1152
|
# @api private
|
|
1153
|
-
def handle_or_reraise(context, err)
|
|
1153
|
+
def handle_or_reraise(context, err, object: context[:current_object], arguments: context[:current_arguments], field: context[:current_field])
|
|
1154
1154
|
handler = Execution::Errors.find_handler_for(self, err.class)
|
|
1155
1155
|
if handler
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
field = context[:current_field]
|
|
1160
|
-
if obj.is_a?(GraphQL::Schema::Object)
|
|
1161
|
-
obj = obj.object
|
|
1156
|
+
arguments = arguments.respond_to?(:keyword_arguments) ? arguments.keyword_arguments : arguments
|
|
1157
|
+
if object.is_a?(GraphQL::Schema::Object)
|
|
1158
|
+
object = object.object
|
|
1162
1159
|
end
|
|
1163
|
-
handler[:handler].call(err,
|
|
1160
|
+
handler[:handler].call(err, object, arguments, context, field)
|
|
1164
1161
|
else
|
|
1165
1162
|
if (context[:backtrace] || using_backtrace) && !err.is_a?(GraphQL::ExecutionError)
|
|
1166
1163
|
err = GraphQL::Backtrace::TracedError.new(err, context)
|
|
@@ -1587,6 +1584,14 @@ module GraphQL
|
|
|
1587
1584
|
# @see {Query#initialize} for arguments.
|
|
1588
1585
|
# @return [GraphQL::Query::Result] query result, ready to be serialized as JSON
|
|
1589
1586
|
def execute(query_str = nil, **kwargs)
|
|
1587
|
+
if default_execution_next
|
|
1588
|
+
execute_next(query_str, **kwargs)
|
|
1589
|
+
else
|
|
1590
|
+
execute_legacy(query_str, **kwargs)
|
|
1591
|
+
end
|
|
1592
|
+
end
|
|
1593
|
+
|
|
1594
|
+
def execute_legacy(query_str = nil, **kwargs)
|
|
1590
1595
|
if query_str
|
|
1591
1596
|
kwargs[:query] = query_str
|
|
1592
1597
|
end
|
|
@@ -1628,7 +1633,23 @@ module GraphQL
|
|
|
1628
1633
|
# @option kwargs [nil, Integer] :max_complexity (nil)
|
|
1629
1634
|
# @return [Array<GraphQL::Query::Result>] One result for each query in the input
|
|
1630
1635
|
def multiplex(queries, **kwargs)
|
|
1631
|
-
|
|
1636
|
+
if @default_execution_next
|
|
1637
|
+
multiplex_next(queries, **kwargs)
|
|
1638
|
+
else
|
|
1639
|
+
GraphQL::Execution::Interpreter.run_all(self, queries, **kwargs)
|
|
1640
|
+
end
|
|
1641
|
+
end
|
|
1642
|
+
|
|
1643
|
+
def default_execution_next(new_value = NOT_CONFIGURED)
|
|
1644
|
+
if !NOT_CONFIGURED.equal?(new_value)
|
|
1645
|
+
@default_execution_next = new_value
|
|
1646
|
+
elsif instance_variable_defined?(:@default_execution_next)
|
|
1647
|
+
@default_execution_next
|
|
1648
|
+
elsif superclass.respond_to?(:default_execution_next)
|
|
1649
|
+
superclass.default_execution_next
|
|
1650
|
+
else
|
|
1651
|
+
false
|
|
1652
|
+
end
|
|
1632
1653
|
end
|
|
1633
1654
|
|
|
1634
1655
|
def instrumenters
|
|
@@ -54,6 +54,12 @@ module GraphQL
|
|
|
54
54
|
events << subscription_instance.event
|
|
55
55
|
end
|
|
56
56
|
value
|
|
57
|
+
elsif (exec_next_update_event = context.namespace(:subscriptions)[:update_event])
|
|
58
|
+
if context.query.subscription_topic == exec_next_update_event.topic
|
|
59
|
+
value
|
|
60
|
+
else
|
|
61
|
+
context.skip
|
|
62
|
+
end
|
|
57
63
|
elsif (events = context.namespace(:subscriptions)[:events])
|
|
58
64
|
# This is the first execution, so gather an Event
|
|
59
65
|
# for the backend to register:
|
|
@@ -67,6 +67,8 @@ module GraphQL
|
|
|
67
67
|
DA_FETCH_KEYS_IID => "fetch keys",
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
ANON_CLASS_NAME = "(anonymous)"
|
|
71
|
+
|
|
70
72
|
DEBUG_INSPECT_CATEGORY_IIDS = [15]
|
|
71
73
|
DA_DEBUG_INSPECT_CLASS_IID = 16
|
|
72
74
|
DEBUG_INSPECT_EVENT_NAME_IID = 17
|
|
@@ -118,7 +120,7 @@ module GraphQL
|
|
|
118
120
|
}
|
|
119
121
|
|
|
120
122
|
@source_name_iids = Hash.new do |h, source_class|
|
|
121
|
-
h[source_class] = @interned_event_name_iids[source_class.name]
|
|
123
|
+
h[source_class] = @interned_event_name_iids[source_class.name || ANON_CLASS_NAME]
|
|
122
124
|
end.compare_by_identity
|
|
123
125
|
|
|
124
126
|
@auth_name_iids = Hash.new do |h, graphql_type|
|
|
@@ -144,7 +146,7 @@ module GraphQL
|
|
|
144
146
|
end
|
|
145
147
|
|
|
146
148
|
@class_name_iids = Hash.new do |h, k|
|
|
147
|
-
h[k] = @interned_da_string_values[k.name]
|
|
149
|
+
h[k] = @interned_da_string_values[k.name || ANON_CLASS_NAME]
|
|
148
150
|
end.compare_by_identity
|
|
149
151
|
|
|
150
152
|
@starting_objects = GC.stat(:total_allocated_objects)
|
|
@@ -682,7 +684,7 @@ module GraphQL
|
|
|
682
684
|
when GraphQL::Schema::InputObject
|
|
683
685
|
payload_to_debug(k, v.to_h, iid: iid, intern_value: intern_value)
|
|
684
686
|
else
|
|
685
|
-
class_name_iid = @interned_da_string_values[(v.class.name ||
|
|
687
|
+
class_name_iid = @interned_da_string_values[(v.class.name || ANON_CLASS_NAME)]
|
|
686
688
|
da = [
|
|
687
689
|
debug_annotation(DA_DEBUG_INSPECT_CLASS_IID, :string_value_iid, class_name_iid),
|
|
688
690
|
]
|
data/lib/graphql/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: graphql
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.6.
|
|
4
|
+
version: 2.6.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Robert Mosolgo
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-05-26 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: base64
|
|
@@ -512,6 +512,7 @@ files:
|
|
|
512
512
|
- lib/graphql/execution/multiplex.rb
|
|
513
513
|
- lib/graphql/execution/next.rb
|
|
514
514
|
- lib/graphql/execution/prepare_object_step.rb
|
|
515
|
+
- lib/graphql/execution/resolve_type_step.rb
|
|
515
516
|
- lib/graphql/execution/runner.rb
|
|
516
517
|
- lib/graphql/execution/selections_step.rb
|
|
517
518
|
- lib/graphql/execution_error.rb
|