graphql 1.12.10 → 1.13.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/generators/graphql/core.rb +3 -1
- data/lib/generators/graphql/install_generator.rb +9 -2
- data/lib/generators/graphql/mutation_generator.rb +1 -1
- data/lib/generators/graphql/object_generator.rb +2 -1
- data/lib/generators/graphql/relay.rb +19 -11
- data/lib/generators/graphql/templates/schema.erb +14 -2
- data/lib/generators/graphql/type_generator.rb +0 -1
- data/lib/graphql/analysis/ast/field_usage.rb +28 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +10 -14
- data/lib/graphql/analysis/ast/visitor.rb +4 -4
- data/lib/graphql/backtrace/table.rb +15 -3
- data/lib/graphql/backtrace/tracer.rb +7 -4
- data/lib/graphql/base_type.rb +4 -2
- data/lib/graphql/boolean_type.rb +1 -1
- data/lib/graphql/dataloader/null_dataloader.rb +1 -0
- data/lib/graphql/dataloader/source.rb +50 -2
- data/lib/graphql/dataloader.rb +110 -41
- data/lib/graphql/define/instance_definable.rb +1 -1
- data/lib/graphql/deprecated_dsl.rb +11 -3
- data/lib/graphql/deprecation.rb +1 -5
- data/lib/graphql/directive/deprecated_directive.rb +1 -1
- data/lib/graphql/directive/include_directive.rb +1 -1
- data/lib/graphql/directive/skip_directive.rb +1 -1
- data/lib/graphql/directive.rb +0 -4
- data/lib/graphql/enum_type.rb +5 -1
- data/lib/graphql/execution/errors.rb +1 -0
- data/lib/graphql/execution/execute.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -4
- data/lib/graphql/execution/interpreter/resolve.rb +6 -2
- data/lib/graphql/execution/interpreter/runtime.rb +513 -213
- data/lib/graphql/execution/interpreter.rb +4 -8
- data/lib/graphql/execution/lazy.rb +5 -1
- data/lib/graphql/execution/lookahead.rb +2 -2
- data/lib/graphql/execution/multiplex.rb +4 -1
- data/lib/graphql/float_type.rb +1 -1
- data/lib/graphql/id_type.rb +1 -1
- data/lib/graphql/int_type.rb +1 -1
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/introspection/directive_type.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +2 -2
- data/lib/graphql/introspection/enum_value_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +2 -2
- data/lib/graphql/introspection/input_value_type.rb +10 -4
- data/lib/graphql/introspection/schema_type.rb +3 -3
- data/lib/graphql/introspection/type_type.rb +10 -10
- data/lib/graphql/language/block_string.rb +2 -6
- data/lib/graphql/language/document_from_schema_definition.rb +10 -4
- data/lib/graphql/language/lexer.rb +0 -3
- data/lib/graphql/language/lexer.rl +0 -4
- data/lib/graphql/language/nodes.rb +13 -3
- data/lib/graphql/language/parser.rb +442 -434
- data/lib/graphql/language/parser.y +5 -4
- data/lib/graphql/language/printer.rb +6 -1
- data/lib/graphql/language/sanitized_printer.rb +5 -5
- data/lib/graphql/language/token.rb +0 -4
- data/lib/graphql/name_validator.rb +0 -4
- data/lib/graphql/pagination/active_record_relation_connection.rb +43 -6
- data/lib/graphql/pagination/connections.rb +40 -16
- data/lib/graphql/pagination/relation_connection.rb +57 -27
- data/lib/graphql/query/arguments.rb +1 -1
- data/lib/graphql/query/arguments_cache.rb +1 -1
- data/lib/graphql/query/context.rb +15 -2
- data/lib/graphql/query/literal_input.rb +1 -1
- data/lib/graphql/query/null_context.rb +12 -7
- data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
- data/lib/graphql/query/validation_pipeline.rb +1 -1
- data/lib/graphql/query/variables.rb +5 -1
- data/lib/graphql/query.rb +5 -1
- data/lib/graphql/relay/edges_instrumentation.rb +0 -1
- data/lib/graphql/relay/global_id_resolve.rb +1 -1
- data/lib/graphql/relay/page_info.rb +1 -1
- data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
- data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
- data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
- data/lib/graphql/rubocop.rb +4 -0
- data/lib/graphql/schema/addition.rb +247 -0
- data/lib/graphql/schema/argument.rb +103 -45
- data/lib/graphql/schema/build_from_definition.rb +13 -7
- data/lib/graphql/schema/directive/feature.rb +1 -1
- data/lib/graphql/schema/directive/flagged.rb +2 -2
- data/lib/graphql/schema/directive/include.rb +1 -1
- data/lib/graphql/schema/directive/skip.rb +1 -1
- data/lib/graphql/schema/directive/transform.rb +14 -2
- data/lib/graphql/schema/directive.rb +7 -3
- data/lib/graphql/schema/enum.rb +70 -11
- data/lib/graphql/schema/enum_value.rb +6 -0
- data/lib/graphql/schema/field/connection_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +243 -81
- data/lib/graphql/schema/field_extension.rb +89 -2
- data/lib/graphql/schema/find_inherited_value.rb +1 -0
- data/lib/graphql/schema/finder.rb +5 -5
- data/lib/graphql/schema/input_object.rb +39 -29
- data/lib/graphql/schema/interface.rb +11 -20
- data/lib/graphql/schema/introspection_system.rb +1 -1
- data/lib/graphql/schema/list.rb +3 -1
- data/lib/graphql/schema/member/accepts_definition.rb +15 -3
- data/lib/graphql/schema/member/build_type.rb +1 -4
- data/lib/graphql/schema/member/cached_graphql_definition.rb +29 -2
- data/lib/graphql/schema/member/has_arguments.rb +145 -57
- data/lib/graphql/schema/member/has_deprecation_reason.rb +1 -1
- data/lib/graphql/schema/member/has_fields.rb +76 -18
- data/lib/graphql/schema/member/has_interfaces.rb +90 -0
- data/lib/graphql/schema/member.rb +1 -0
- data/lib/graphql/schema/non_null.rb +7 -1
- data/lib/graphql/schema/object.rb +10 -75
- data/lib/graphql/schema/printer.rb +12 -17
- data/lib/graphql/schema/relay_classic_mutation.rb +37 -3
- data/lib/graphql/schema/resolver/has_payload_type.rb +27 -2
- data/lib/graphql/schema/resolver.rb +75 -65
- data/lib/graphql/schema/scalar.rb +2 -0
- data/lib/graphql/schema/subscription.rb +36 -8
- data/lib/graphql/schema/traversal.rb +1 -1
- data/lib/graphql/schema/type_expression.rb +1 -1
- data/lib/graphql/schema/type_membership.rb +18 -4
- data/lib/graphql/schema/union.rb +8 -1
- data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
- data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
- data/lib/graphql/schema/validator/exclusion_validator.rb +3 -1
- data/lib/graphql/schema/validator/format_validator.rb +4 -5
- data/lib/graphql/schema/validator/inclusion_validator.rb +3 -1
- data/lib/graphql/schema/validator/length_validator.rb +5 -3
- data/lib/graphql/schema/validator/numericality_validator.rb +13 -2
- data/lib/graphql/schema/validator/required_validator.rb +29 -15
- data/lib/graphql/schema/validator.rb +33 -25
- data/lib/graphql/schema/warden.rb +116 -52
- data/lib/graphql/schema.rb +162 -227
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/base_visitor.rb +8 -5
- data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
- data/lib/graphql/static_validation/error.rb +3 -1
- data/lib/graphql/static_validation/literal_validator.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +52 -26
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
- data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
- data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +3 -1
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +4 -4
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +13 -7
- data/lib/graphql/static_validation/validation_context.rb +8 -2
- data/lib/graphql/static_validation/validator.rb +15 -12
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/string_type.rb +1 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +36 -6
- data/lib/graphql/subscriptions/event.rb +68 -31
- data/lib/graphql/subscriptions/serialize.rb +23 -3
- data/lib/graphql/subscriptions.rb +17 -19
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +6 -20
- data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
- data/lib/graphql/tracing/notifications_tracing.rb +59 -0
- data/lib/graphql/types/big_int.rb +5 -1
- data/lib/graphql/types/int.rb +1 -1
- data/lib/graphql/types/relay/connection_behaviors.rb +26 -9
- data/lib/graphql/types/relay/default_relay.rb +5 -1
- data/lib/graphql/types/relay/edge_behaviors.rb +13 -2
- data/lib/graphql/types/relay/has_node_field.rb +2 -2
- data/lib/graphql/types/relay/has_nodes_field.rb +2 -2
- data/lib/graphql/types/relay/node_field.rb +15 -4
- data/lib/graphql/types/relay/nodes_field.rb +14 -4
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/unauthorized_error.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +10 -28
- data/readme.md +1 -4
- metadata +17 -21
- data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 51f1e91399e97a5376028af68f7f9c0f01b2d7ff8f342ada08eb984302ea56c3
|
|
4
|
+
data.tar.gz: eb2a62700254c18263f19ae05027f64b725df4bbb100e2c251652a16cfab6afb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 861c8880bf96831e4072f51bcb8dc5e6302040b88ffd7d94cea2288ef281bd317a2235fe98b10ca10687c2f616ac6a740729149ecd44ab4cef2779a9838e7c42
|
|
7
|
+
data.tar.gz: 985e2119a77f367503b133ce37108a7bedaf99c21c6edb6f6eb1b25d2be80954233f9344afb52f19ffbfca864844b180f11b07b09baf58462066b4c1794c830e
|
|
@@ -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,
|
|
@@ -32,20 +32,28 @@ module Graphql
|
|
|
32
32
|
|
|
33
33
|
# Return a string UUID for `object`
|
|
34
34
|
def self.id_from_object(object, type_definition, query_ctx)
|
|
35
|
-
#
|
|
36
|
-
|
|
37
|
-
#
|
|
38
|
-
|
|
35
|
+
# For example, use Rails' GlobalID library (https://github.com/rails/globalid):
|
|
36
|
+
object_id = object.to_global_id.to_s
|
|
37
|
+
# Remove this redundant prefix to make IDs shorter:
|
|
38
|
+
object_id = object_id.sub("gid://\#{GlobalID.app}/", "")
|
|
39
|
+
encoded_id = Base64.urlsafe_encode64(object_id)
|
|
40
|
+
# Remove the "=" padding
|
|
41
|
+
encoded_id = encoded_id.sub(/=+/, "")
|
|
42
|
+
# Add a type hint
|
|
43
|
+
type_hint = type_definition.graphql_name.first
|
|
44
|
+
"\#{type_hint}_\#{encoded_id}"
|
|
39
45
|
end
|
|
40
46
|
|
|
41
47
|
# Given a string UUID, find the object
|
|
42
|
-
def self.object_from_id(
|
|
43
|
-
# For example,
|
|
44
|
-
#
|
|
45
|
-
|
|
46
|
-
#
|
|
47
|
-
|
|
48
|
-
#
|
|
48
|
+
def self.object_from_id(encoded_id_with_hint, query_ctx)
|
|
49
|
+
# For example, use Rails' GlobalID library (https://github.com/rails/globalid):
|
|
50
|
+
# Split off the type hint
|
|
51
|
+
_type_hint, encoded_id = encoded_id_with_hint.split("_", 2)
|
|
52
|
+
# Decode the ID
|
|
53
|
+
id = Base64.urlsafe_decode64(encoded_id)
|
|
54
|
+
# Rebuild it for Rails then find the object:
|
|
55
|
+
full_global_id = "gid://\#{GlobalID.app}/\#{id}"
|
|
56
|
+
GlobalID::Locator.locate(full_global_id)
|
|
49
57
|
end
|
|
50
58
|
RUBY
|
|
51
59
|
inject_into_file schema_file_path, schema_code, before: /^end\n/m, force: false
|
|
@@ -4,11 +4,23 @@ class <%= schema_name %> < GraphQL::Schema
|
|
|
4
4
|
<% if options[:batch] %>
|
|
5
5
|
# GraphQL::Batch setup:
|
|
6
6
|
use GraphQL::Batch
|
|
7
|
+
<% else %>
|
|
8
|
+
# For batch-loading (see https://graphql-ruby.org/dataloader/overview.html)
|
|
9
|
+
use GraphQL::Dataloader
|
|
7
10
|
<% end %>
|
|
11
|
+
# GraphQL-Ruby calls this when something goes wrong while running a query:
|
|
12
|
+
def self.type_error(err, context)
|
|
13
|
+
# if err.is_a?(GraphQL::InvalidNullError)
|
|
14
|
+
# # report to your bug tracker here
|
|
15
|
+
# return nil
|
|
16
|
+
# end
|
|
17
|
+
super
|
|
18
|
+
end
|
|
19
|
+
|
|
8
20
|
# Union and Interface Resolution
|
|
9
21
|
def self.resolve_type(abstract_type, obj, ctx)
|
|
10
|
-
# TODO: Implement this
|
|
11
|
-
# to return the correct object type for `obj`
|
|
22
|
+
# TODO: Implement this method
|
|
23
|
+
# to return the correct GraphQL object type for `obj`
|
|
12
24
|
raise(GraphQL::RequiredImplementationMissingError)
|
|
13
25
|
end
|
|
14
26
|
end
|
|
@@ -7,6 +7,7 @@ module GraphQL
|
|
|
7
7
|
super
|
|
8
8
|
@used_fields = Set.new
|
|
9
9
|
@used_deprecated_fields = Set.new
|
|
10
|
+
@used_deprecated_arguments = Set.new
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
def on_leave_field(node, parent, visitor)
|
|
@@ -14,14 +15,40 @@ module GraphQL
|
|
|
14
15
|
field = "#{visitor.parent_type_definition.graphql_name}.#{field_defn.graphql_name}"
|
|
15
16
|
@used_fields << field
|
|
16
17
|
@used_deprecated_fields << field if field_defn.deprecation_reason
|
|
18
|
+
arguments = visitor.query.arguments_for(node, visitor.field_definition)
|
|
19
|
+
# If there was an error when preparing this argument object,
|
|
20
|
+
# then this might be an error or something:
|
|
21
|
+
if arguments.respond_to?(:argument_values)
|
|
22
|
+
extract_deprecated_arguments(arguments.argument_values)
|
|
23
|
+
end
|
|
17
24
|
end
|
|
18
25
|
|
|
19
26
|
def result
|
|
20
27
|
{
|
|
21
28
|
used_fields: @used_fields.to_a,
|
|
22
|
-
used_deprecated_fields: @used_deprecated_fields.to_a
|
|
29
|
+
used_deprecated_fields: @used_deprecated_fields.to_a,
|
|
30
|
+
used_deprecated_arguments: @used_deprecated_arguments.to_a,
|
|
23
31
|
}
|
|
24
32
|
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def extract_deprecated_arguments(argument_values)
|
|
37
|
+
argument_values.each_pair do |_argument_name, argument|
|
|
38
|
+
if argument.definition.deprecation_reason
|
|
39
|
+
@used_deprecated_arguments << argument.definition.path
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
if argument.definition.type.kind.input_object?
|
|
43
|
+
extract_deprecated_arguments(argument.value.arguments.argument_values) # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
|
|
44
|
+
elsif argument.definition.type.list? && !argument.value.nil?
|
|
45
|
+
argument
|
|
46
|
+
.value
|
|
47
|
+
.select { |value| value.respond_to?(:arguments) }
|
|
48
|
+
.each { |value| extract_deprecated_arguments(value.arguments.argument_values) } # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
25
52
|
end
|
|
26
53
|
end
|
|
27
54
|
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
|
|
@@ -83,13 +83,13 @@ module GraphQL
|
|
|
83
83
|
value = if top && @override_value
|
|
84
84
|
@override_value
|
|
85
85
|
else
|
|
86
|
-
@context.query.context.namespace(:interpreter)[:runtime]
|
|
86
|
+
value_at(@context.query.context.namespace(:interpreter)[:runtime], context_entry.path)
|
|
87
87
|
end
|
|
88
88
|
rows << [
|
|
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)
|
|
@@ -130,7 +130,7 @@ module GraphQL
|
|
|
130
130
|
if object.is_a?(GraphQL::Schema::Object)
|
|
131
131
|
object = object.object
|
|
132
132
|
end
|
|
133
|
-
value = context_entry.namespace(:interpreter)[:runtime]
|
|
133
|
+
value = value_at(context_entry.namespace(:interpreter)[:runtime], [])
|
|
134
134
|
rows << [
|
|
135
135
|
"#{position}",
|
|
136
136
|
"#{op_type}#{op_name ? " #{op_name}" : ""}",
|
|
@@ -142,6 +142,18 @@ module GraphQL
|
|
|
142
142
|
raise "Unexpected get_rows subject #{context_entry.class} (#{context_entry.inspect})"
|
|
143
143
|
end
|
|
144
144
|
end
|
|
145
|
+
|
|
146
|
+
def value_at(runtime, path)
|
|
147
|
+
response = runtime.final_result
|
|
148
|
+
path.each do |key|
|
|
149
|
+
if response && (response = response[key])
|
|
150
|
+
next
|
|
151
|
+
else
|
|
152
|
+
break
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
response
|
|
156
|
+
end
|
|
145
157
|
end
|
|
146
158
|
end
|
|
147
159
|
end
|
|
@@ -15,14 +15,17 @@ module GraphQL
|
|
|
15
15
|
# No query context yet
|
|
16
16
|
nil
|
|
17
17
|
when "validate", "analyze_query", "execute_query", "execute_query_lazy"
|
|
18
|
-
query = metadata[:query] || metadata[:queries].first
|
|
19
18
|
push_key = []
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
if (query = metadata[:query]) || ((queries = metadata[:queries]) && (query = queries.first))
|
|
20
|
+
push_data = query
|
|
21
|
+
multiplex = query.multiplex
|
|
22
|
+
elsif (multiplex = metadata[:multiplex])
|
|
23
|
+
push_data = multiplex.queries.first
|
|
24
|
+
end
|
|
22
25
|
when "execute_field", "execute_field_lazy"
|
|
23
26
|
query = metadata[:query] || raise(ArgumentError, "Add `legacy: true` to use GraphQL::Backtrace without the interpreter runtime.")
|
|
24
27
|
multiplex = query.multiplex
|
|
25
|
-
push_key = metadata[:path]
|
|
28
|
+
push_key = metadata[:path]
|
|
26
29
|
parent_frame = multiplex.context[:graphql_backtrace_contexts][push_key[0..-2]]
|
|
27
30
|
|
|
28
31
|
if parent_frame.is_a?(GraphQL::Query)
|
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)
|
|
@@ -6,7 +6,11 @@ module GraphQL
|
|
|
6
6
|
# Called by {Dataloader} to prepare the {Source}'s internal state
|
|
7
7
|
# @api private
|
|
8
8
|
def setup(dataloader)
|
|
9
|
+
# These keys have been requested but haven't been fetched yet
|
|
9
10
|
@pending_keys = []
|
|
11
|
+
# These keys have been passed to `fetch` but haven't been finished yet
|
|
12
|
+
@fetching_keys = []
|
|
13
|
+
# { key => result }
|
|
10
14
|
@results = {}
|
|
11
15
|
@dataloader = dataloader
|
|
12
16
|
end
|
|
@@ -64,31 +68,68 @@ module GraphQL
|
|
|
64
68
|
# Then run the batch and update the cache.
|
|
65
69
|
# @return [void]
|
|
66
70
|
def sync
|
|
71
|
+
pending_keys = @pending_keys.dup
|
|
67
72
|
@dataloader.yield
|
|
73
|
+
iterations = 0
|
|
74
|
+
while pending_keys.any? { |k| !@results.key?(k) }
|
|
75
|
+
iterations += 1
|
|
76
|
+
if iterations > 1000
|
|
77
|
+
raise "#{self.class}#sync tried 1000 times to load pending keys (#{pending_keys}), but they still weren't loaded. There is likely a circular dependency."
|
|
78
|
+
end
|
|
79
|
+
@dataloader.yield
|
|
80
|
+
end
|
|
81
|
+
nil
|
|
68
82
|
end
|
|
69
83
|
|
|
70
84
|
# @return [Boolean] True if this source has any pending requests for data.
|
|
71
85
|
def pending?
|
|
72
|
-
|
|
86
|
+
!@pending_keys.empty?
|
|
73
87
|
end
|
|
74
88
|
|
|
75
89
|
# Called by {GraphQL::Dataloader} to resolve and pending requests to this source.
|
|
76
90
|
# @api private
|
|
77
91
|
# @return [void]
|
|
78
92
|
def run_pending_keys
|
|
93
|
+
if !@fetching_keys.empty?
|
|
94
|
+
@pending_keys -= @fetching_keys
|
|
95
|
+
end
|
|
79
96
|
return if @pending_keys.empty?
|
|
80
97
|
fetch_keys = @pending_keys.uniq
|
|
98
|
+
@fetching_keys.concat(fetch_keys)
|
|
81
99
|
@pending_keys = []
|
|
82
100
|
results = fetch(fetch_keys)
|
|
83
101
|
fetch_keys.each_with_index do |key, idx|
|
|
84
102
|
@results[key] = results[idx]
|
|
85
103
|
end
|
|
104
|
+
nil
|
|
86
105
|
rescue StandardError => error
|
|
87
106
|
fetch_keys.each { |key| @results[key] = error }
|
|
88
107
|
ensure
|
|
89
|
-
|
|
108
|
+
if fetch_keys
|
|
109
|
+
@fetching_keys -= fetch_keys
|
|
110
|
+
end
|
|
90
111
|
end
|
|
91
112
|
|
|
113
|
+
# These arguments are given to `dataloader.with(source_class, ...)`. The object
|
|
114
|
+
# returned from this method is used to de-duplicate batch loads under the hood
|
|
115
|
+
# by using it as a Hash key.
|
|
116
|
+
#
|
|
117
|
+
# By default, the arguments are all put in an Array. To customize how this source's
|
|
118
|
+
# batches are merged, override this method to return something else.
|
|
119
|
+
#
|
|
120
|
+
# For example, if you pass `ActiveRecord::Relation`s to `.with(...)`, you could override
|
|
121
|
+
# this method to call `.to_sql` on them, thus merging `.load(...)` calls when they apply
|
|
122
|
+
# to equivalent relations.
|
|
123
|
+
#
|
|
124
|
+
# @param batch_args [Array<Object>]
|
|
125
|
+
# @param batch_kwargs [Hash]
|
|
126
|
+
# @return [Object]
|
|
127
|
+
def self.batch_key_for(*batch_args, **batch_kwargs)
|
|
128
|
+
[*batch_args, **batch_kwargs]
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
attr_reader :pending_keys
|
|
132
|
+
|
|
92
133
|
private
|
|
93
134
|
|
|
94
135
|
# Reads and returns the result for the key from the internal cache, or raises an error if the result was an error
|
|
@@ -96,6 +137,13 @@ module GraphQL
|
|
|
96
137
|
# @return [Object] The result from {#fetch} for `key`.
|
|
97
138
|
# @api private
|
|
98
139
|
def result_for(key)
|
|
140
|
+
if !@results.key?(key)
|
|
141
|
+
raise <<-ERR
|
|
142
|
+
Invariant: fetching result for a key on #{self.class} that hasn't been loaded yet (#{key.inspect}, loaded: #{@results.keys})
|
|
143
|
+
|
|
144
|
+
This key should have been loaded already. This is a bug in GraphQL::Dataloader, please report it on GitHub: https://github.com/rmosolgo/graphql-ruby/issues/new.
|
|
145
|
+
ERR
|
|
146
|
+
end
|
|
99
147
|
result = @results[key]
|
|
100
148
|
|
|
101
149
|
raise result if result.class <= StandardError
|