graphql 2.5.23 → 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/analysis.rb +20 -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 +744 -0
- data/lib/graphql/execution/finalize.rb +230 -0
- data/lib/graphql/execution/input_values.rb +333 -0
- data/lib/graphql/execution/interpreter/arguments_cache.rb +3 -0
- data/lib/graphql/execution/interpreter/handles_raw_value.rb +6 -0
- data/lib/graphql/execution/interpreter/runtime.rb +36 -15
- data/lib/graphql/execution/load_argument_step.rb +102 -0
- data/lib/graphql/execution/next.rb +42 -16
- data/lib/graphql/execution/prepare_object_step.rb +147 -0
- data/lib/graphql/execution/resolve_type_step.rb +27 -0
- data/lib/graphql/execution/runner.rb +445 -0
- data/lib/graphql/execution/selections_step.rb +91 -0
- data/lib/graphql/execution.rb +10 -3
- data/lib/graphql/execution_error.rb +7 -13
- data/lib/graphql/introspection/entry_points.rb +2 -2
- data/lib/graphql/introspection/schema_type.rb +6 -2
- data/lib/graphql/language/lexer.rb +12 -8
- 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/context.rb +6 -0
- data/lib/graphql/query/partial.rb +18 -3
- data/lib/graphql/query.rb +12 -3
- data/lib/graphql/runtime_error.rb +6 -0
- data/lib/graphql/schema/argument.rb +3 -3
- data/lib/graphql/schema/build_from_definition.rb +10 -0
- data/lib/graphql/schema/directive/feature.rb +4 -0
- data/lib/graphql/schema/directive/transform.rb +20 -0
- data/lib/graphql/schema/directive.rb +23 -9
- data/lib/graphql/schema/field/connection_extension.rb +2 -15
- data/lib/graphql/schema/field/scope_extension.rb +0 -4
- data/lib/graphql/schema/field.rb +20 -20
- data/lib/graphql/schema/field_extension.rb +11 -41
- 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 +26 -0
- data/lib/graphql/schema/introspection_system.rb +6 -21
- data/lib/graphql/schema/list.rb +4 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +0 -10
- 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 +30 -14
- 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 +43 -20
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +31 -25
- data/lib/graphql/subscriptions/event.rb +0 -1
- data/lib/graphql/subscriptions.rb +15 -0
- data/lib/graphql/tracing/perfetto_trace.rb +5 -3
- data/lib/graphql/tracing/trace.rb +6 -0
- data/lib/graphql/unauthorized_error.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +1 -3
- metadata +11 -7
- data/lib/graphql/execution/next/field_resolve_step.rb +0 -743
- data/lib/graphql/execution/next/load_argument_step.rb +0 -64
- data/lib/graphql/execution/next/prepare_object_step.rb +0 -129
- data/lib/graphql/execution/next/runner.rb +0 -411
- data/lib/graphql/execution/next/selections_step.rb +0 -37
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 16abc9c2a5eda0da251dbe7e14433241bc7d038d2527926832ceb29336fb857a
|
|
4
|
+
data.tar.gz: c89bd2a4b340ca30bfa7b823f51e4671972355d54bd56fdaed598c13a415c3b3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6452d2a517c502b4a8934582d060885a5f6462de244a1f331433f1076dc57a879cdd081e147f70925064a99607e0794fcf6eadad7a3f4a9111a5ab979c552554
|
|
7
|
+
data.tar.gz: b6a0219606d905fc885ab2192596d1acb1d92bce407defc751bfafb1a7199e9c32275c1d3202f3246251e72b80554698b1f54920f76178f1ddc81b41d628bacd
|
|
@@ -9,6 +9,8 @@ module GraphQL
|
|
|
9
9
|
super
|
|
10
10
|
@skip_introspection_fields = !query.schema.max_complexity_count_introspection_fields
|
|
11
11
|
@complexities_on_type_by_query = {}
|
|
12
|
+
@intersect_cache = Hash.new { |h, k| h[k] = {}.compare_by_identity }.compare_by_identity
|
|
13
|
+
@possible_types_cache = {}.compare_by_identity
|
|
12
14
|
end
|
|
13
15
|
|
|
14
16
|
# Override this method to use the complexity result
|
|
@@ -159,8 +161,22 @@ module GraphQL
|
|
|
159
161
|
|
|
160
162
|
def types_intersect?(query, a, b)
|
|
161
163
|
return true if a == b
|
|
162
|
-
|
|
163
|
-
|
|
164
|
+
|
|
165
|
+
if a.object_id < b.object_id
|
|
166
|
+
first_cache = @intersect_cache[a]
|
|
167
|
+
second_key = b
|
|
168
|
+
else
|
|
169
|
+
first_cache = @intersect_cache[b]
|
|
170
|
+
second_key = a
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
if first_cache.key?(second_key)
|
|
174
|
+
first_cache[second_key]
|
|
175
|
+
else
|
|
176
|
+
a_types = @possible_types_cache[a] ||= query.types.possible_types(a).to_set
|
|
177
|
+
b_types = @possible_types_cache[b] ||= query.types.possible_types(b).to_set
|
|
178
|
+
first_cache[second_key] = a_types.intersect?(b_types)
|
|
179
|
+
end
|
|
164
180
|
end
|
|
165
181
|
|
|
166
182
|
# A hook which is called whenever a field's max complexity is calculated.
|
|
@@ -175,18 +191,16 @@ module GraphQL
|
|
|
175
191
|
# @param inner_selections [Array<Hash<String, ScopedTypeComplexity>>] Field selections for a scope
|
|
176
192
|
# @return [Integer] Total complexity value for all these selections in the parent scope
|
|
177
193
|
def merged_max_complexity(query, inner_selections)
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
194
|
+
child_scopes_by_key = {}
|
|
195
|
+
inner_selections.each do |inner_selection|
|
|
196
|
+
inner_selection.each do |k, v|
|
|
197
|
+
scopes = child_scopes_by_key[k] ||= []
|
|
198
|
+
scopes << v
|
|
199
|
+
end
|
|
182
200
|
end
|
|
183
|
-
|
|
184
201
|
# Add up the total cost for each unique field name's coalesced selections
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
# all keys come with at least one scope.
|
|
188
|
-
child_scopes = inner_selections.filter_map { _1[field_key] }
|
|
189
|
-
|
|
202
|
+
total = 0
|
|
203
|
+
child_scopes_by_key.each do |field_key, child_scopes|
|
|
190
204
|
# Compute maximum possible cost of child selections;
|
|
191
205
|
# composites merge their maximums, while leaf scopes are always zero.
|
|
192
206
|
# FieldsWillMerge validation assures all scopes are uniformly composite or leaf.
|
|
@@ -214,8 +228,10 @@ module GraphQL
|
|
|
214
228
|
child_complexity: maximum_children_cost,
|
|
215
229
|
)
|
|
216
230
|
|
|
217
|
-
total
|
|
231
|
+
total += maximum_cost
|
|
218
232
|
end
|
|
233
|
+
|
|
234
|
+
total
|
|
219
235
|
end
|
|
220
236
|
|
|
221
237
|
def legacy_merged_max_complexity(query, inner_selections)
|
data/lib/graphql/analysis.rb
CHANGED
|
@@ -40,13 +40,13 @@ module GraphQL
|
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
multiplex_results = multiplex_analyzers.map(&:result)
|
|
44
|
-
multiplex_errors = analysis_errors(multiplex_results)
|
|
45
43
|
|
|
44
|
+
multiplex_analyzers.map!(&:result)
|
|
45
|
+
multiplex_errors = analysis_errors(EmptyObjects::EMPTY_ARRAY, multiplex_analyzers)
|
|
46
46
|
multiplex.queries.each_with_index do |query, idx|
|
|
47
|
-
query.analysis_errors = multiplex_errors
|
|
47
|
+
query.analysis_errors = analysis_errors(multiplex_errors, query_results[idx])
|
|
48
48
|
end
|
|
49
|
-
|
|
49
|
+
multiplex_analyzers
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -55,13 +55,11 @@ module GraphQL
|
|
|
55
55
|
# @return [Array<Any>] Results from those analyzers
|
|
56
56
|
def analyze_query(query, analyzers, multiplex_analyzers: [])
|
|
57
57
|
query.current_trace.analyze_query(query: query) do
|
|
58
|
-
query_analyzers = analyzers
|
|
59
|
-
|
|
60
|
-
.tap { _1.select!(&:analyze?) }
|
|
61
|
-
|
|
58
|
+
query_analyzers = analyzers.map { |analyzer| analyzer.new(query) }
|
|
59
|
+
query_analyzers.select!(&:analyze?)
|
|
62
60
|
analyzers_to_run = query_analyzers + multiplex_analyzers
|
|
63
|
-
if !analyzers_to_run.empty?
|
|
64
61
|
|
|
62
|
+
if !analyzers_to_run.empty?
|
|
65
63
|
analyzers_to_run.select!(&:visit?)
|
|
66
64
|
if !analyzers_to_run.empty?
|
|
67
65
|
visitor = GraphQL::Analysis::Visitor.new(
|
|
@@ -79,18 +77,27 @@ module GraphQL
|
|
|
79
77
|
|
|
80
78
|
query_analyzers.map(&:result)
|
|
81
79
|
else
|
|
82
|
-
|
|
80
|
+
EmptyObjects::EMPTY_ARRAY
|
|
83
81
|
end
|
|
84
82
|
end
|
|
85
83
|
rescue TimeoutError => err
|
|
86
84
|
[err]
|
|
87
85
|
rescue GraphQL::UnauthorizedError, GraphQL::ExecutionError
|
|
88
86
|
# This error was raised during analysis and will be returned the client before execution
|
|
89
|
-
|
|
87
|
+
EmptyObjects::EMPTY_ARRAY
|
|
90
88
|
end
|
|
91
89
|
|
|
92
|
-
def analysis_errors(results)
|
|
93
|
-
|
|
90
|
+
def analysis_errors(parent_errors, results)
|
|
91
|
+
if !results.empty?
|
|
92
|
+
results = results.flatten
|
|
93
|
+
results.select! { |r| r.is_a?(GraphQL::AnalysisError) }
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
if parent_errors.empty?
|
|
97
|
+
results
|
|
98
|
+
else
|
|
99
|
+
parent_errors + results
|
|
100
|
+
end
|
|
94
101
|
end
|
|
95
102
|
end
|
|
96
103
|
end
|
|
@@ -90,7 +90,16 @@ module GraphQL
|
|
|
90
90
|
|
|
91
91
|
if ast_node
|
|
92
92
|
field_defn = query.get_field(result.graphql_result_type, ast_node.name)
|
|
93
|
-
args =
|
|
93
|
+
args = begin
|
|
94
|
+
if (cached_args = query.arguments_cache.cached_arguments_for(ast_node, field_defn))
|
|
95
|
+
cached_args.to_h
|
|
96
|
+
else
|
|
97
|
+
EmptyObjects::EMPTY_HASH
|
|
98
|
+
end
|
|
99
|
+
rescue StandardError => err
|
|
100
|
+
"Failed to load arguments, #{err.class}: #{err.message}"
|
|
101
|
+
end
|
|
102
|
+
|
|
94
103
|
field_path = field_defn.path
|
|
95
104
|
if ast_node.alias
|
|
96
105
|
field_path += " as #{ast_node.alias}"
|
data/lib/graphql/current.rb
CHANGED
|
@@ -41,7 +41,13 @@ module GraphQL
|
|
|
41
41
|
# @see GraphQL::Field#path for a string identifying this field
|
|
42
42
|
# @return [GraphQL::Field, nil] The currently-running field, if there is one.
|
|
43
43
|
def self.field
|
|
44
|
-
Fiber[:__graphql_runtime_info]
|
|
44
|
+
if (interpreter_info = Fiber[:__graphql_runtime_info])
|
|
45
|
+
interpreter_info.values&.first&.current_field
|
|
46
|
+
elsif (field = Fiber[:__graphql_current_field])
|
|
47
|
+
field
|
|
48
|
+
else
|
|
49
|
+
nil
|
|
50
|
+
end
|
|
45
51
|
end
|
|
46
52
|
|
|
47
53
|
# @return [Class, nil] The currently-running {Dataloader::Source} class, if there is one.
|
data/lib/graphql/dataloader.rb
CHANGED
|
@@ -108,7 +108,7 @@ module GraphQL
|
|
|
108
108
|
# @param batch_parameters [Array<Object>]
|
|
109
109
|
# @return [GraphQL::Dataloader::Source] An instance of {source_class}, initialized with `self, *batch_parameters`,
|
|
110
110
|
# and cached for the lifetime of this {Multiplex}.
|
|
111
|
-
if
|
|
111
|
+
if (RUBY_ENGINE == "ruby" && RUBY_ENGINE < "3") || RUBY_ENGINE == "truffleruby" # truffle-ruby wasn't doing well with the implementation below
|
|
112
112
|
def with(source_class, *batch_args)
|
|
113
113
|
batch_key = source_class.batch_key_for(*batch_args)
|
|
114
114
|
@source_cache[source_class][batch_key] ||= begin
|
|
@@ -18,11 +18,13 @@ module GraphQL
|
|
|
18
18
|
case name
|
|
19
19
|
when SKIP
|
|
20
20
|
args = query.arguments_for(directive_ast_node, directive_defn)
|
|
21
|
+
next if args.is_a?(GraphQL::ExecutionError)
|
|
21
22
|
if args[:if] == true
|
|
22
23
|
return false
|
|
23
24
|
end
|
|
24
25
|
when INCLUDE
|
|
25
26
|
args = query.arguments_for(directive_ast_node, directive_defn)
|
|
27
|
+
next if args.is_a?(GraphQL::ExecutionError)
|
|
26
28
|
if args[:if] == false
|
|
27
29
|
return false
|
|
28
30
|
end
|