graphql 1.12.20 → 1.13.1
Sign up to get free protection for your applications and to get access to all the features.
- 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/templates/schema.erb +2 -2
- data/lib/generators/graphql/type_generator.rb +0 -1
- data/lib/graphql/analysis/ast/field_usage.rb +2 -2
- 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 +1 -1
- data/lib/graphql/base_type.rb +4 -2
- data/lib/graphql/boolean_type.rb +1 -1
- data/lib/graphql/dataloader.rb +55 -22
- 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/interpreter/arguments.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +2 -2
- data/lib/graphql/execution/interpreter/runtime.rb +30 -18
- 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/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 +4 -4
- data/lib/graphql/introspection/schema_type.rb +2 -2
- 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 +4 -2
- data/lib/graphql/language/lexer.rb +0 -3
- data/lib/graphql/language/lexer.rl +0 -4
- data/lib/graphql/language/nodes.rb +12 -2
- 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/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/variables.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 +37 -28
- data/lib/graphql/schema/argument.rb +8 -6
- data/lib/graphql/schema/build_from_definition.rb +5 -5
- 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 +1 -1
- data/lib/graphql/schema/directive.rb +7 -3
- data/lib/graphql/schema/enum.rb +60 -10
- 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 +130 -39
- data/lib/graphql/schema/field_extension.rb +52 -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 +8 -5
- 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 +0 -4
- data/lib/graphql/schema/member/cached_graphql_definition.rb +29 -2
- data/lib/graphql/schema/member/has_arguments.rb +55 -13
- 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 +3 -1
- data/lib/graphql/schema/object.rb +10 -75
- data/lib/graphql/schema/printer.rb +1 -1
- data/lib/graphql/schema/relay_classic_mutation.rb +29 -3
- data/lib/graphql/schema/resolver/has_payload_type.rb +27 -2
- data/lib/graphql/schema/resolver.rb +19 -5
- data/lib/graphql/schema/scalar.rb +2 -0
- data/lib/graphql/schema/subscription.rb +11 -1
- 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/format_validator.rb +3 -5
- data/lib/graphql/schema/validator/numericality_validator.rb +1 -0
- data/lib/graphql/schema/validator.rb +4 -7
- data/lib/graphql/schema/warden.rb +116 -52
- data/lib/graphql/schema.rb +106 -22
- data/lib/graphql/static_validation/base_visitor.rb +5 -5
- data/lib/graphql/static_validation/definition_dependencies.rb +0 -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 +15 -8
- 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 +7 -7
- data/lib/graphql/string_type.rb +1 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +8 -4
- data/lib/graphql/subscriptions/event.rb +20 -12
- data/lib/graphql/subscriptions.rb +17 -19
- 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 +1 -1
- data/lib/graphql/types/relay/has_nodes_field.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +10 -32
- metadata +10 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f950da72b7fb585a9135dc893b2c2cf41c8a6482a82a0f7401ba913d48c643f
|
4
|
+
data.tar.gz: 8d5cd615133ca107e38ab18ccc59902c6eaa1f8d7ffeef5c7af474f1e4c5cde9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 961ac5fe60ef45ea3eed645bcbef7793363dabe18d676c739188430b95e86887470d93966eccdfe89f0bebe99e0c4e5cfa68b5e697865d8228713a080d28f98d
|
7
|
+
data.tar.gz: a545feab4e634fc1039c232c43fe45412382b44215fe4038211e19a9fcef44dd02bb0db22eda2c3f78553867b7c3aed1b7630947a83d72741431e6fe2caeffdf
|
@@ -19,7 +19,9 @@ module Graphql
|
|
19
19
|
sentinel = /< GraphQL::Schema\s*\n/m
|
20
20
|
|
21
21
|
in_root do
|
22
|
-
|
22
|
+
if File.exist?(schema_file_path)
|
23
|
+
inject_into_file schema_file_path, " #{type}(Types::#{name})\n", after: sentinel, verbose: false, force: false
|
24
|
+
end
|
23
25
|
end
|
24
26
|
end
|
25
27
|
|
@@ -122,8 +122,15 @@ module Graphql
|
|
122
122
|
if options.api?
|
123
123
|
say("Skipped graphiql, as this rails project is API only")
|
124
124
|
say(" You may wish to use GraphiQL.app for development: https://github.com/skevy/graphiql-app")
|
125
|
-
elsif !options[:skip_graphiql]
|
126
|
-
gem(
|
125
|
+
elsif !options[:skip_graphiql]
|
126
|
+
# `gem(...)` uses `gsub_file(...)` under the hood, which is a no-op for `rails destroy...` (when `behavior == :revoke`).
|
127
|
+
# So handle that case by calling `gsub_file` with `force: true`.
|
128
|
+
if behavior == :invoke && !File.read(Rails.root.join("Gemfile")).include?("graphiql-rails")
|
129
|
+
gem("graphiql-rails", group: :development)
|
130
|
+
elsif behavior == :revoke
|
131
|
+
gemfile_pattern = /\n\s*gem ('|")graphiql-rails('|"), :?group(:| =>) :development/
|
132
|
+
gsub_file Rails.root.join("Gemfile"), gemfile_pattern, "", { force: true }
|
133
|
+
end
|
127
134
|
|
128
135
|
# This is a little cheat just to get cleaner shell output:
|
129
136
|
log :route, 'graphiql-rails'
|
@@ -17,7 +17,7 @@ module Graphql
|
|
17
17
|
|
18
18
|
argument :name, type: :string
|
19
19
|
|
20
|
-
def initialize(args, *options)
|
20
|
+
def initialize(args, *options) # :nodoc:
|
21
21
|
# Unfreeze name in case it's given as a frozen string
|
22
22
|
args[0] = args[0].dup if args[0].is_a?(String) && args[0].frozen?
|
23
23
|
super
|
@@ -12,7 +12,8 @@ module Graphql
|
|
12
12
|
#
|
13
13
|
# Add the Node interface with `--node`.
|
14
14
|
class ObjectGenerator < TypeGeneratorBase
|
15
|
-
desc "Create a GraphQL::ObjectType with the given name and fields"
|
15
|
+
desc "Create a GraphQL::ObjectType with the given name and fields." \
|
16
|
+
"If the given type name matches an existing ActiveRecord model, the generated type will automatically include fields for the models database columns."
|
16
17
|
source_root File.expand_path('../templates', __FILE__)
|
17
18
|
|
18
19
|
argument :custom_fields,
|
@@ -9,7 +9,7 @@ class <%= schema_name %> < GraphQL::Schema
|
|
9
9
|
use GraphQL::Dataloader
|
10
10
|
<% end %>
|
11
11
|
# GraphQL-Ruby calls this when something goes wrong while running a query:
|
12
|
-
def self.type_error(err)
|
12
|
+
def self.type_error(err, context)
|
13
13
|
# if err.is_a?(GraphQL::InvalidNullError)
|
14
14
|
# # report to your bug tracker here
|
15
15
|
# return nil
|
@@ -19,7 +19,7 @@ class <%= schema_name %> < GraphQL::Schema
|
|
19
19
|
|
20
20
|
# Union and Interface Resolution
|
21
21
|
def self.resolve_type(abstract_type, obj, ctx)
|
22
|
-
# TODO: Implement this
|
22
|
+
# TODO: Implement this method
|
23
23
|
# to return the correct GraphQL object type for `obj`
|
24
24
|
raise(GraphQL::RequiredImplementationMissingError)
|
25
25
|
end
|
@@ -36,12 +36,12 @@ module GraphQL
|
|
36
36
|
end
|
37
37
|
|
38
38
|
if argument.definition.type.kind.input_object?
|
39
|
-
extract_deprecated_arguments(argument.value.arguments.argument_values)
|
39
|
+
extract_deprecated_arguments(argument.value.arguments.argument_values) # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
|
40
40
|
elsif argument.definition.type.list? && !argument.value.nil?
|
41
41
|
argument
|
42
42
|
.value
|
43
43
|
.select { |value| value.respond_to?(:arguments) }
|
44
|
-
.each { |value| extract_deprecated_arguments(value.arguments.argument_values) }
|
44
|
+
.each { |value| extract_deprecated_arguments(value.arguments.argument_values) } # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
@@ -23,18 +23,22 @@ module GraphQL
|
|
23
23
|
|
24
24
|
attr_reader :field_definition, :response_path, :query
|
25
25
|
|
26
|
-
# @param
|
26
|
+
# @param parent_type [Class] The owner of `field_definition`
|
27
27
|
# @param field_definition [GraphQL::Field, GraphQL::Schema::Field] Used for getting the `.complexity` configuration
|
28
28
|
# @param query [GraphQL::Query] Used for `query.possible_types`
|
29
29
|
# @param response_path [Array<String>] The path to the response key for the field
|
30
|
-
def initialize(
|
31
|
-
@
|
30
|
+
def initialize(parent_type, field_definition, query, response_path)
|
31
|
+
@parent_type = parent_type
|
32
32
|
@field_definition = field_definition
|
33
33
|
@query = query
|
34
34
|
@response_path = response_path
|
35
35
|
@scoped_children = nil
|
36
|
+
@nodes = []
|
36
37
|
end
|
37
38
|
|
39
|
+
# @return [Array<GraphQL::Language::Nodes::Field>]
|
40
|
+
attr_reader :nodes
|
41
|
+
|
38
42
|
# Returns true if this field has no selections, ie, it's a scalar.
|
39
43
|
# We need a quick way to check whether we should continue traversing.
|
40
44
|
def terminal?
|
@@ -50,16 +54,7 @@ module GraphQL
|
|
50
54
|
end
|
51
55
|
|
52
56
|
def own_complexity(child_complexity)
|
53
|
-
|
54
|
-
case defined_complexity
|
55
|
-
when Proc
|
56
|
-
arguments = @query.arguments_for(@node, @field_definition)
|
57
|
-
defined_complexity.call(@query.context, arguments.keyword_arguments, child_complexity)
|
58
|
-
when Numeric
|
59
|
-
defined_complexity + child_complexity
|
60
|
-
else
|
61
|
-
raise("Invalid complexity: #{defined_complexity.inspect} on #{@field_definition.name}")
|
62
|
-
end
|
57
|
+
@field_definition.calculate_complexity(query: @query, nodes: @nodes, child_complexity: child_complexity)
|
63
58
|
end
|
64
59
|
end
|
65
60
|
|
@@ -79,7 +74,8 @@ module GraphQL
|
|
79
74
|
# then the query would have been rejected as invalid.
|
80
75
|
complexities_on_type = @complexities_on_type_by_query[visitor.query] ||= [ScopedTypeComplexity.new(nil, nil, query, visitor.response_path)]
|
81
76
|
|
82
|
-
complexity = complexities_on_type.last.scoped_children[parent_type][field_key] ||= ScopedTypeComplexity.new(
|
77
|
+
complexity = complexities_on_type.last.scoped_children[parent_type][field_key] ||= ScopedTypeComplexity.new(parent_type, visitor.field_definition, visitor.query, visitor.response_path)
|
78
|
+
complexity.nodes.push(node)
|
83
79
|
# Push it on the stack.
|
84
80
|
complexities_on_type.push(complexity)
|
85
81
|
end
|
@@ -100,7 +100,7 @@ module GraphQL
|
|
100
100
|
def on_field(node, parent)
|
101
101
|
@response_path.push(node.alias || node.name)
|
102
102
|
parent_type = @object_types.last
|
103
|
-
field_definition = @schema.get_field(parent_type, node.name)
|
103
|
+
field_definition = @schema.get_field(parent_type, node.name, @query.context)
|
104
104
|
@field_definitions.push(field_definition)
|
105
105
|
if !field_definition.nil?
|
106
106
|
next_object_type = field_definition.type.unwrap
|
@@ -138,14 +138,14 @@ module GraphQL
|
|
138
138
|
argument_defn = if (arg = @argument_definitions.last)
|
139
139
|
arg_type = arg.type.unwrap
|
140
140
|
if arg_type.kind.input_object?
|
141
|
-
arg_type.
|
141
|
+
arg_type.get_argument(node.name, @query.context)
|
142
142
|
else
|
143
143
|
nil
|
144
144
|
end
|
145
145
|
elsif (directive_defn = @directive_definitions.last)
|
146
|
-
directive_defn.
|
146
|
+
directive_defn.get_argument(node.name, @query.context)
|
147
147
|
elsif (field_defn = @field_definitions.last)
|
148
|
-
field_defn.
|
148
|
+
field_defn.get_argument(node.name, @query.context)
|
149
149
|
else
|
150
150
|
nil
|
151
151
|
end
|
@@ -89,7 +89,7 @@ module GraphQL
|
|
89
89
|
"#{context_entry.ast_node ? context_entry.ast_node.position.join(":") : ""}",
|
90
90
|
"#{context_entry.field.path}#{field_alias ? " as #{field_alias}" : ""}",
|
91
91
|
"#{context_entry.object.object.inspect}",
|
92
|
-
context_entry.arguments.to_h.inspect,
|
92
|
+
context_entry.arguments.to_h.inspect, # rubocop:disable Development/ContextIsPassedCop -- unrelated method
|
93
93
|
Backtrace::InspectResult.inspect_result(value),
|
94
94
|
]
|
95
95
|
if (parent = context_entry.parent_frame)
|
data/lib/graphql/base_type.rb
CHANGED
@@ -41,7 +41,9 @@ module GraphQL
|
|
41
41
|
alias :graphql_name :name
|
42
42
|
# Future-compatible alias
|
43
43
|
# @see {GraphQL::SchemaMember}
|
44
|
-
|
44
|
+
def graphql_definition(silence_deprecation_warning: false)
|
45
|
+
itself
|
46
|
+
end
|
45
47
|
|
46
48
|
def type_class
|
47
49
|
metadata[:type_class]
|
@@ -194,7 +196,7 @@ module GraphQL
|
|
194
196
|
resolve_related_type(Object.const_get(type_arg))
|
195
197
|
else
|
196
198
|
if type_arg.respond_to?(:graphql_definition)
|
197
|
-
type_arg.graphql_definition
|
199
|
+
type_arg.graphql_definition(silence_deprecation_warning: true)
|
198
200
|
else
|
199
201
|
type_arg
|
200
202
|
end
|
data/lib/graphql/boolean_type.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
GraphQL::BOOLEAN_TYPE = GraphQL::Types::Boolean.graphql_definition
|
2
|
+
GraphQL::BOOLEAN_TYPE = GraphQL::Types::Boolean.graphql_definition(silence_deprecation_warning: true)
|
data/lib/graphql/dataloader.rb
CHANGED
@@ -23,8 +23,18 @@ module GraphQL
|
|
23
23
|
# end
|
24
24
|
#
|
25
25
|
class Dataloader
|
26
|
-
|
27
|
-
|
26
|
+
class << self
|
27
|
+
attr_accessor :default_nonblocking
|
28
|
+
end
|
29
|
+
|
30
|
+
AsyncDataloader = Class.new(self) { self.default_nonblocking = true }
|
31
|
+
|
32
|
+
def self.use(schema, nonblocking: nil)
|
33
|
+
schema.dataloader_class = if nonblocking
|
34
|
+
AsyncDataloader
|
35
|
+
else
|
36
|
+
self
|
37
|
+
end
|
28
38
|
end
|
29
39
|
|
30
40
|
# Call the block with a Dataloader instance,
|
@@ -39,9 +49,16 @@ module GraphQL
|
|
39
49
|
result
|
40
50
|
end
|
41
51
|
|
42
|
-
def initialize
|
52
|
+
def initialize(nonblocking: self.class.default_nonblocking)
|
43
53
|
@source_cache = Hash.new { |h, k| h[k] = {} }
|
44
54
|
@pending_jobs = []
|
55
|
+
if !nonblocking.nil?
|
56
|
+
@nonblocking = nonblocking
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def nonblocking?
|
61
|
+
@nonblocking
|
45
62
|
end
|
46
63
|
|
47
64
|
# Get a Source instance from this dataloader, for calling `.load(...)` or `.request(...)` on.
|
@@ -50,7 +67,7 @@ module GraphQL
|
|
50
67
|
# @param batch_parameters [Array<Object>]
|
51
68
|
# @return [GraphQL::Dataloader::Source] An instance of {source_class}, initialized with `self, *batch_parameters`,
|
52
69
|
# and cached for the lifetime of this {Multiplex}.
|
53
|
-
if RUBY_VERSION < "3"
|
70
|
+
if RUBY_VERSION < "3" || RUBY_ENGINE != "ruby" # truffle-ruby wasn't doing well with the implementation below
|
54
71
|
def with(source_class, *batch_args)
|
55
72
|
batch_key = source_class.batch_key_for(*batch_args)
|
56
73
|
@source_cache[source_class][batch_key] ||= begin
|
@@ -117,6 +134,9 @@ module GraphQL
|
|
117
134
|
|
118
135
|
# @api private Move along, move along
|
119
136
|
def run
|
137
|
+
if @nonblocking && !Fiber.scheduler
|
138
|
+
raise "`nonblocking: true` requires `Fiber.scheduler`, assign one with `Fiber.set_scheduler(...)` before executing GraphQL."
|
139
|
+
end
|
120
140
|
# At a high level, the algorithm is:
|
121
141
|
#
|
122
142
|
# A) Inside Fibers, run jobs from the queue one-by-one
|
@@ -137,6 +157,8 @@ module GraphQL
|
|
137
157
|
#
|
138
158
|
pending_fibers = []
|
139
159
|
next_fibers = []
|
160
|
+
pending_source_fibers = []
|
161
|
+
next_source_fibers = []
|
140
162
|
first_pass = true
|
141
163
|
|
142
164
|
while first_pass || (f = pending_fibers.shift)
|
@@ -174,31 +196,27 @@ module GraphQL
|
|
174
196
|
# This is where an evented approach would be even better -- can we tell which
|
175
197
|
# fibers are ready to continue, and continue execution there?
|
176
198
|
#
|
177
|
-
|
178
|
-
|
179
|
-
else
|
180
|
-
nil
|
199
|
+
if (first_source_fiber = create_source_fiber)
|
200
|
+
pending_source_fibers << first_source_fiber
|
181
201
|
end
|
182
202
|
|
183
|
-
|
184
|
-
while (outer_source_fiber =
|
203
|
+
while pending_source_fibers.any?
|
204
|
+
while (outer_source_fiber = pending_source_fibers.pop)
|
185
205
|
resume(outer_source_fiber)
|
186
|
-
|
187
|
-
# If this source caused more sources to become pending, run those before running this one again:
|
188
|
-
next_source_fiber = create_source_fiber
|
189
|
-
if next_source_fiber
|
190
|
-
source_fiber_queue << next_source_fiber
|
191
|
-
end
|
192
|
-
|
193
206
|
if outer_source_fiber.alive?
|
194
|
-
|
207
|
+
next_source_fibers << outer_source_fiber
|
208
|
+
end
|
209
|
+
if (next_source_fiber = create_source_fiber)
|
210
|
+
pending_source_fibers << next_source_fiber
|
195
211
|
end
|
196
212
|
end
|
213
|
+
join_queues(pending_source_fibers, next_source_fibers)
|
214
|
+
next_source_fibers.clear
|
197
215
|
end
|
198
216
|
# Move newly-enqueued Fibers on to the list to be resumed.
|
199
217
|
# Clear out the list of next-round Fibers, so that
|
200
218
|
# any Fibers that pause can be put on it.
|
201
|
-
pending_fibers
|
219
|
+
join_queues(pending_fibers, next_fibers)
|
202
220
|
next_fibers.clear
|
203
221
|
end
|
204
222
|
end
|
@@ -213,6 +231,14 @@ module GraphQL
|
|
213
231
|
nil
|
214
232
|
end
|
215
233
|
|
234
|
+
def join_queues(previous_queue, next_queue)
|
235
|
+
if @nonblocking
|
236
|
+
Fiber.scheduler.run
|
237
|
+
next_queue.select!(&:alive?)
|
238
|
+
end
|
239
|
+
previous_queue.concat(next_queue)
|
240
|
+
end
|
241
|
+
|
216
242
|
private
|
217
243
|
|
218
244
|
# If there are pending sources, return a fiber for running them.
|
@@ -266,9 +292,16 @@ module GraphQL
|
|
266
292
|
fiber_locals[fiber_var_key] = Thread.current[fiber_var_key]
|
267
293
|
end
|
268
294
|
|
269
|
-
|
270
|
-
|
271
|
-
|
295
|
+
if @nonblocking
|
296
|
+
Fiber.new(blocking: false) do
|
297
|
+
fiber_locals.each { |k, v| Thread.current[k] = v }
|
298
|
+
yield
|
299
|
+
end
|
300
|
+
else
|
301
|
+
Fiber.new do
|
302
|
+
fiber_locals.each { |k, v| Thread.current[k] = v }
|
303
|
+
yield
|
304
|
+
end
|
272
305
|
end
|
273
306
|
end
|
274
307
|
end
|
@@ -1,2 +1,2 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
GraphQL::Directive::DeprecatedDirective = GraphQL::Schema::Directive::Deprecated.graphql_definition
|
2
|
+
GraphQL::Directive::DeprecatedDirective = GraphQL::Schema::Directive::Deprecated.graphql_definition(silence_deprecation_warning: true)
|
@@ -1,2 +1,2 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
GraphQL::Directive::IncludeDirective = GraphQL::Schema::Directive::Include.graphql_definition
|
2
|
+
GraphQL::Directive::IncludeDirective = GraphQL::Schema::Directive::Include.graphql_definition(silence_deprecation_warning: true)
|
@@ -1,2 +1,2 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
GraphQL::Directive::SkipDirective = GraphQL::Schema::Directive::Skip.graphql_definition
|
2
|
+
GraphQL::Directive::SkipDirective = GraphQL::Schema::Directive::Skip.graphql_definition(silence_deprecation_warning: true)
|
data/lib/graphql/directive.rb
CHANGED
data/lib/graphql/enum_type.rb
CHANGED
@@ -34,10 +34,14 @@ module GraphQL
|
|
34
34
|
end
|
35
35
|
|
36
36
|
# @return [Hash<String => EnumValue>] `{name => value}` pairs contained in this type
|
37
|
-
def values
|
37
|
+
def values(_context = nil)
|
38
38
|
@values_by_name
|
39
39
|
end
|
40
40
|
|
41
|
+
def enum_values(_context = nil)
|
42
|
+
values.values
|
43
|
+
end
|
44
|
+
|
41
45
|
def kind
|
42
46
|
GraphQL::TypeKinds::ENUM
|
43
47
|
end
|
@@ -111,6 +111,7 @@ module GraphQL
|
|
111
111
|
runtime_info = ctx.namespace(:interpreter) || {}
|
112
112
|
obj = runtime_info[:current_object]
|
113
113
|
args = runtime_info[:current_arguments]
|
114
|
+
args = args && args.keyword_arguments
|
114
115
|
field = runtime_info[:current_field]
|
115
116
|
if obj.is_a?(GraphQL::Schema::Object)
|
116
117
|
obj = obj.object
|
@@ -59,7 +59,7 @@ module GraphQL
|
|
59
59
|
@empty
|
60
60
|
end
|
61
61
|
|
62
|
-
def_delegators :keyword_arguments, :key?, :[], :fetch, :keys, :each, :values
|
62
|
+
def_delegators :keyword_arguments, :key?, :[], :fetch, :keys, :each, :values, :size, :to_h
|
63
63
|
def_delegators :argument_values, :each_value
|
64
64
|
|
65
65
|
def inspect
|
@@ -71,11 +71,11 @@ module GraphQL
|
|
71
71
|
when Array
|
72
72
|
ast_arg_or_hash_or_value.map { |v| prepare_args_hash(query, v) }
|
73
73
|
when GraphQL::Language::Nodes::Field, GraphQL::Language::Nodes::InputObject, GraphQL::Language::Nodes::Directive
|
74
|
-
if ast_arg_or_hash_or_value.arguments.empty?
|
74
|
+
if ast_arg_or_hash_or_value.arguments.empty? # rubocop:disable Development/ContextIsPassedCop -- AST-related
|
75
75
|
return NO_ARGUMENTS
|
76
76
|
end
|
77
77
|
args_hash = {}
|
78
|
-
ast_arg_or_hash_or_value.arguments.each do |arg|
|
78
|
+
ast_arg_or_hash_or_value.arguments.each do |arg| # rubocop:disable Development/ContextIsPassedCop -- AST-related
|
79
79
|
v = prepare_args_hash(query, arg.value)
|
80
80
|
if v != NO_VALUE_GIVEN
|
81
81
|
args_hash[arg.name] = v
|
@@ -314,7 +314,7 @@ module GraphQL
|
|
314
314
|
case node
|
315
315
|
when GraphQL::Language::Nodes::InlineFragment
|
316
316
|
if node.type
|
317
|
-
type_defn = schema.get_type(node.type.name)
|
317
|
+
type_defn = schema.get_type(node.type.name, context)
|
318
318
|
|
319
319
|
# Faster than .map{}.include?()
|
320
320
|
query.warden.possible_types(type_defn).each do |t|
|
@@ -329,7 +329,7 @@ module GraphQL
|
|
329
329
|
end
|
330
330
|
when GraphQL::Language::Nodes::FragmentSpread
|
331
331
|
fragment_def = query.fragments[node.name]
|
332
|
-
type_defn =
|
332
|
+
type_defn = query.get_type(fragment_def.type.name)
|
333
333
|
possible_types = query.warden.possible_types(type_defn)
|
334
334
|
possible_types.each do |t|
|
335
335
|
if t == owner_type
|
@@ -384,7 +384,9 @@ module GraphQL
|
|
384
384
|
ast_node = field_ast_nodes_or_ast_node
|
385
385
|
end
|
386
386
|
field_name = ast_node.name
|
387
|
-
|
387
|
+
# This can't use `query.get_field` because it gets confused on introspection below if `field_defn` isn't `nil`,
|
388
|
+
# because of how `is_introspection` is used to call `.authorized_new` later on.
|
389
|
+
field_defn = @fields_cache[owner_type][field_name] ||= owner_type.get_field(field_name, @context)
|
388
390
|
is_introspection = false
|
389
391
|
if field_defn.nil?
|
390
392
|
field_defn = if owner_type == schema.query && (entry_point_field = schema.introspection_system.entry_point(name: field_name))
|
@@ -419,10 +421,10 @@ module GraphQL
|
|
419
421
|
object = authorized_new(field_defn.owner, object, context)
|
420
422
|
end
|
421
423
|
|
422
|
-
total_args_count = field_defn.arguments.size
|
424
|
+
total_args_count = field_defn.arguments(context).size
|
423
425
|
if total_args_count == 0
|
424
|
-
|
425
|
-
evaluate_selection_with_args(
|
426
|
+
resolved_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
|
427
|
+
evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selections_result, parent_object)
|
426
428
|
else
|
427
429
|
# TODO remove all arguments(...) usages?
|
428
430
|
@query.arguments_cache.dataload_for(ast_node, field_defn, object) do |resolved_arguments|
|
@@ -431,10 +433,10 @@ module GraphQL
|
|
431
433
|
end
|
432
434
|
end
|
433
435
|
|
434
|
-
def evaluate_selection_with_args(
|
436
|
+
def evaluate_selection_with_args(arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selection_result, parent_object) # rubocop:disable Metrics/ParameterLists
|
435
437
|
context.scoped_context = scoped_context
|
436
438
|
return_type = field_defn.type
|
437
|
-
after_lazy(
|
439
|
+
after_lazy(arguments, owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, scoped_context: context.scoped_context, owner_object: object, arguments: arguments, result_name: result_name, result: selection_result) do |resolved_arguments|
|
438
440
|
if resolved_arguments.is_a?(GraphQL::ExecutionError) || resolved_arguments.is_a?(GraphQL::UnauthorizedError)
|
439
441
|
continue_value(next_path, resolved_arguments, owner_type, field_defn, return_type.non_null?, ast_node, result_name, selection_result)
|
440
442
|
next
|
@@ -485,7 +487,7 @@ module GraphQL
|
|
485
487
|
resolved_arguments.keyword_arguments
|
486
488
|
end
|
487
489
|
|
488
|
-
set_all_interpreter_context(nil, nil,
|
490
|
+
set_all_interpreter_context(nil, nil, resolved_arguments, nil)
|
489
491
|
|
490
492
|
# Optimize for the case that field is selected only once
|
491
493
|
if field_ast_nodes.nil? || field_ast_nodes.size == 1
|
@@ -511,7 +513,7 @@ module GraphQL
|
|
511
513
|
rescue GraphQL::ExecutionError => err
|
512
514
|
err
|
513
515
|
end
|
514
|
-
after_lazy(app_result, owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, scoped_context: context.scoped_context, owner_object: object, arguments:
|
516
|
+
after_lazy(app_result, owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, scoped_context: context.scoped_context, owner_object: object, arguments: resolved_arguments, result_name: result_name, result: selection_result) do |inner_result|
|
515
517
|
continue_value = continue_value(next_path, inner_result, owner_type, field_defn, return_type.non_null?, ast_node, result_name, selection_result)
|
516
518
|
if HALT != continue_value
|
517
519
|
continue_field(next_path, continue_value, owner_type, field_defn, return_type, ast_node, next_selections, false, object, kwarg_arguments, result_name, selection_result)
|
@@ -637,14 +639,20 @@ module GraphQL
|
|
637
639
|
when Array
|
638
640
|
# It's an array full of execution errors; add them all.
|
639
641
|
if value.any? && value.all? { |v| v.is_a?(GraphQL::ExecutionError) }
|
642
|
+
list_type_at_all = (field && (field.type.list?))
|
640
643
|
if selection_result.nil? || !dead_result?(selection_result)
|
641
644
|
value.each_with_index do |error, index|
|
642
645
|
error.ast_node ||= ast_node
|
643
|
-
error.path ||= path + (
|
646
|
+
error.path ||= path + (list_type_at_all ? [index] : [])
|
644
647
|
context.errors << error
|
645
648
|
end
|
646
649
|
if selection_result
|
647
|
-
|
650
|
+
if list_type_at_all
|
651
|
+
result_without_errors = value.map { |v| v.is_a?(GraphQL::ExecutionError) ? nil : v }
|
652
|
+
set_result(selection_result, result_name, result_without_errors)
|
653
|
+
else
|
654
|
+
set_result(selection_result, result_name, nil)
|
655
|
+
end
|
648
656
|
end
|
649
657
|
end
|
650
658
|
HALT
|
@@ -862,16 +870,20 @@ module GraphQL
|
|
862
870
|
# but don't wrap the continuation below
|
863
871
|
inner_obj = begin
|
864
872
|
query.with_error_handling do
|
865
|
-
|
866
|
-
|
873
|
+
begin
|
874
|
+
if trace
|
875
|
+
query.trace("execute_field_lazy", {owner: owner, field: field, path: path, query: query, object: owner_object, arguments: arguments, ast_node: ast_node}) do
|
876
|
+
schema.sync_lazy(lazy_obj)
|
877
|
+
end
|
878
|
+
else
|
867
879
|
schema.sync_lazy(lazy_obj)
|
868
880
|
end
|
869
|
-
|
870
|
-
|
881
|
+
rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => err
|
882
|
+
err
|
871
883
|
end
|
872
884
|
end
|
873
|
-
|
874
|
-
|
885
|
+
rescue GraphQL::ExecutionError => ex_err
|
886
|
+
ex_err
|
875
887
|
end
|
876
888
|
yield(inner_obj)
|
877
889
|
end
|
@@ -254,14 +254,14 @@ module GraphQL
|
|
254
254
|
subselections_on_type = selections_on_type
|
255
255
|
if (t = ast_selection.type)
|
256
256
|
# Assuming this is valid, that `t` will be found.
|
257
|
-
on_type = @query.
|
257
|
+
on_type = @query.get_type(t.name).type_class
|
258
258
|
subselections_on_type = subselections_by_type[on_type] ||= {}
|
259
259
|
end
|
260
260
|
find_selections(subselections_by_type, subselections_on_type, on_type, ast_selection.selections, arguments)
|
261
261
|
when GraphQL::Language::Nodes::FragmentSpread
|
262
262
|
frag_defn = @query.fragments[ast_selection.name] || raise("Invariant: Can't look ahead to nonexistent fragment #{ast_selection.name} (found: #{@query.fragments.keys})")
|
263
263
|
# Again, assuming a valid AST
|
264
|
-
on_type = @query.
|
264
|
+
on_type = @query.get_type(frag_defn.type.name).type_class
|
265
265
|
subselections_on_type = subselections_by_type[on_type] ||= {}
|
266
266
|
find_selections(subselections_by_type, subselections_on_type, on_type, frag_defn.selections, arguments)
|
267
267
|
else
|
@@ -35,7 +35,7 @@ module GraphQL
|
|
35
35
|
@queries = queries
|
36
36
|
@queries.each { |q| q.multiplex = self }
|
37
37
|
@context = context
|
38
|
-
@
|
38
|
+
@dataloader = @context[:dataloader] ||= @schema.dataloader_class.new
|
39
39
|
@tracers = schema.tracers + (context[:tracers] || [])
|
40
40
|
# Support `context: {backtrace: true}`
|
41
41
|
if context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
|
@@ -151,6 +151,9 @@ module GraphQL
|
|
151
151
|
|
152
152
|
result
|
153
153
|
end
|
154
|
+
if query.context.namespace?(:__query_result_extensions__)
|
155
|
+
query.result_values["extensions"] = query.context.namespace(:__query_result_extensions__)
|
156
|
+
end
|
154
157
|
end
|
155
158
|
|
156
159
|
# use the old `query_execution_strategy` etc to run this query
|
data/lib/graphql/float_type.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
GraphQL::FLOAT_TYPE = GraphQL::Types::Float.graphql_definition
|
2
|
+
GraphQL::FLOAT_TYPE = GraphQL::Types::Float.graphql_definition(silence_deprecation_warning: true)
|
data/lib/graphql/id_type.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
GraphQL::ID_TYPE = GraphQL::Types::ID.graphql_definition
|
2
|
+
GraphQL::ID_TYPE = GraphQL::Types::ID.graphql_definition(silence_deprecation_warning: true)
|
data/lib/graphql/int_type.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
GraphQL::INT_TYPE = GraphQL::Types::Int.graphql_definition
|
2
|
+
GraphQL::INT_TYPE = GraphQL::Types::Int.graphql_definition(silence_deprecation_warning: true)
|
@@ -10,7 +10,7 @@ module GraphQL
|
|
10
10
|
"skipping a field. Directives provide this by describing additional information "\
|
11
11
|
"to the executor."
|
12
12
|
field :name, String, null: false, method: :graphql_name
|
13
|
-
field :description, String
|
13
|
+
field :description, String
|
14
14
|
field :locations, [GraphQL::Schema::LateBoundType.new("__DirectiveLocation")], null: false
|
15
15
|
field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
|
16
16
|
argument :include_deprecated, Boolean, required: false, default_value: false
|
@@ -3,8 +3,8 @@ module GraphQL
|
|
3
3
|
module Introspection
|
4
4
|
class EntryPoints < Introspection::BaseObject
|
5
5
|
field :__schema, GraphQL::Schema::LateBoundType.new("__Schema"), "This GraphQL schema", null: false
|
6
|
-
field :__type, GraphQL::Schema::LateBoundType.new("__Type"), "A type in the GraphQL system"
|
7
|
-
argument :name, String
|
6
|
+
field :__type, GraphQL::Schema::LateBoundType.new("__Type"), "A type in the GraphQL system" do
|
7
|
+
argument :name, String
|
8
8
|
end
|
9
9
|
|
10
10
|
def __schema
|