graphql 2.0.20 → 2.0.22
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql/backtrace/trace.rb +96 -0
- data/lib/graphql/backtrace.rb +6 -1
- data/lib/graphql/execution/interpreter/arguments.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +33 -33
- data/lib/graphql/execution/interpreter/runtime.rb +274 -209
- data/lib/graphql/execution/interpreter.rb +2 -3
- data/lib/graphql/execution/lookahead.rb +1 -1
- data/lib/graphql/filter.rb +8 -2
- data/lib/graphql/language/document_from_schema_definition.rb +37 -17
- data/lib/graphql/language/lexer.rb +5 -3
- data/lib/graphql/language/nodes.rb +2 -2
- data/lib/graphql/language/parser.rb +475 -458
- data/lib/graphql/language/parser.y +5 -1
- data/lib/graphql/pagination/connection.rb +5 -5
- data/lib/graphql/query/context.rb +22 -12
- data/lib/graphql/query/null_context.rb +4 -1
- data/lib/graphql/query.rb +25 -11
- data/lib/graphql/schema/argument.rb +12 -14
- data/lib/graphql/schema/build_from_definition.rb +15 -3
- data/lib/graphql/schema/enum_value.rb +2 -5
- data/lib/graphql/schema/field/connection_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +17 -16
- data/lib/graphql/schema/field_extension.rb +1 -4
- data/lib/graphql/schema/find_inherited_value.rb +2 -7
- data/lib/graphql/schema/input_object.rb +1 -1
- data/lib/graphql/schema/member/has_arguments.rb +10 -8
- data/lib/graphql/schema/member/has_directives.rb +4 -6
- data/lib/graphql/schema/member/has_fields.rb +80 -36
- data/lib/graphql/schema/member/has_validators.rb +2 -2
- data/lib/graphql/schema/object.rb +1 -1
- data/lib/graphql/schema/printer.rb +3 -1
- data/lib/graphql/schema/relay_classic_mutation.rb +1 -1
- data/lib/graphql/schema/resolver.rb +8 -8
- data/lib/graphql/schema/validator.rb +1 -1
- data/lib/graphql/schema/warden.rb +11 -3
- data/lib/graphql/schema.rb +41 -12
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +2 -2
- data/lib/graphql/tracing/appsignal_trace.rb +6 -0
- data/lib/graphql/tracing/legacy_trace.rb +65 -0
- data/lib/graphql/tracing/notifications_trace.rb +5 -1
- data/lib/graphql/tracing/platform_trace.rb +21 -19
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +1 -1
- data/lib/graphql/tracing/trace.rb +75 -0
- data/lib/graphql/tracing.rb +4 -123
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +4 -0
- data/readme.md +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2564f5f0788db163950385832a4255c88b47b72ddb45175ec30f0f42c6dc0b04
|
4
|
+
data.tar.gz: c1760c1a43453ece3baed09bde3e30f6012bd4357ec597781e4616a7c67a2bc4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e1d1747ceb4450228b9b7cb9b123f61585fe8eea3d6442627b56818f4a146e2b507e5a0b8665e25334a64dca79eb8a089c2aa0ff3e8d710fb6adec080623da0
|
7
|
+
data.tar.gz: f1ec3b93d97f4546184496aed5bc03d5ba1a5af1655aaeeb40ac20461e7c722431a116ca8e1a019d8b7e7eda59e7748f862985ea1dd131b3005ceb9ca3c9fa7c
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
class Backtrace
|
4
|
+
module Trace
|
5
|
+
def validate(query:, validate:)
|
6
|
+
if query.multiplex
|
7
|
+
push_query_backtrace_context(query)
|
8
|
+
end
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def analyze_query(query:)
|
13
|
+
if query.multiplex # missing for stand-alone static validation
|
14
|
+
push_query_backtrace_context(query)
|
15
|
+
end
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute_query(query:)
|
20
|
+
push_query_backtrace_context(query)
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def execute_query_lazy(query:, multiplex:)
|
25
|
+
query ||= multiplex.queries.first
|
26
|
+
push_query_backtrace_context(query)
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
30
|
+
def execute_field(field:, query:, ast_node:, arguments:, object:)
|
31
|
+
push_field_backtrace_context(field, query, ast_node, arguments, object)
|
32
|
+
super
|
33
|
+
end
|
34
|
+
|
35
|
+
def execute_field_lazy(field:, query:, ast_node:, arguments:, object:)
|
36
|
+
push_field_backtrace_context(field, query, ast_node, arguments, object)
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
40
|
+
def execute_multiplex(multiplex:)
|
41
|
+
super
|
42
|
+
rescue StandardError => err
|
43
|
+
# This is an unhandled error from execution,
|
44
|
+
# Re-raise it with a GraphQL trace.
|
45
|
+
multiplex_context = multiplex.context
|
46
|
+
potential_context = multiplex_context[:last_graphql_backtrace_context]
|
47
|
+
|
48
|
+
if potential_context.is_a?(GraphQL::Query::Context) ||
|
49
|
+
potential_context.is_a?(Backtrace::Frame)
|
50
|
+
raise TracedError.new(err, potential_context)
|
51
|
+
else
|
52
|
+
raise
|
53
|
+
end
|
54
|
+
ensure
|
55
|
+
multiplex_context = multiplex.context
|
56
|
+
multiplex_context.delete(:graphql_backtrace_contexts)
|
57
|
+
multiplex_context.delete(:last_graphql_backtrace_context)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def push_query_backtrace_context(query)
|
63
|
+
push_data = query
|
64
|
+
multiplex = query.multiplex
|
65
|
+
push_key = []
|
66
|
+
push_storage = multiplex.context[:graphql_backtrace_contexts] ||= {}
|
67
|
+
push_storage[push_key] = push_data
|
68
|
+
multiplex.context[:last_graphql_backtrace_context] = push_data
|
69
|
+
end
|
70
|
+
|
71
|
+
def push_field_backtrace_context(field, query, ast_node, arguments, object)
|
72
|
+
multiplex = query.multiplex
|
73
|
+
push_key = query.context[:current_path]
|
74
|
+
push_storage = multiplex.context[:graphql_backtrace_contexts]
|
75
|
+
parent_frame = push_storage[push_key[0..-2]]
|
76
|
+
|
77
|
+
if parent_frame.is_a?(GraphQL::Query)
|
78
|
+
parent_frame = parent_frame.context
|
79
|
+
end
|
80
|
+
|
81
|
+
push_data = Frame.new(
|
82
|
+
query: query,
|
83
|
+
path: push_key,
|
84
|
+
ast_node: ast_node,
|
85
|
+
field: field,
|
86
|
+
object: object,
|
87
|
+
arguments: arguments,
|
88
|
+
parent_frame: parent_frame,
|
89
|
+
)
|
90
|
+
|
91
|
+
push_storage[push_key] = push_data
|
92
|
+
multiplex.context[:last_graphql_backtrace_context] = push_data
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/graphql/backtrace.rb
CHANGED
@@ -3,6 +3,7 @@ require "graphql/backtrace/inspect_result"
|
|
3
3
|
require "graphql/backtrace/table"
|
4
4
|
require "graphql/backtrace/traced_error"
|
5
5
|
require "graphql/backtrace/tracer"
|
6
|
+
require "graphql/backtrace/trace"
|
6
7
|
module GraphQL
|
7
8
|
# Wrap unhandled errors with {TracedError}.
|
8
9
|
#
|
@@ -23,7 +24,7 @@ module GraphQL
|
|
23
24
|
def_delegators :to_a, :each, :[]
|
24
25
|
|
25
26
|
def self.use(schema_defn)
|
26
|
-
schema_defn.
|
27
|
+
schema_defn.trace_with(self::Trace)
|
27
28
|
end
|
28
29
|
|
29
30
|
def initialize(context, value: nil)
|
@@ -54,5 +55,9 @@ module GraphQL
|
|
54
55
|
@parent_frame = parent_frame
|
55
56
|
end
|
56
57
|
end
|
58
|
+
|
59
|
+
class DefaultBacktraceTrace < GraphQL::Tracing::Trace
|
60
|
+
include GraphQL::Backtrace::Trace
|
61
|
+
end
|
57
62
|
end
|
58
63
|
end
|
@@ -7,57 +7,57 @@ module GraphQL
|
|
7
7
|
def initialize(query)
|
8
8
|
@query = query
|
9
9
|
@dataloader = query.context.dataloader
|
10
|
-
@storage = Hash.new do |h,
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
h3[parent_object] = NO_ARGUMENTS
|
22
|
-
else
|
23
|
-
h3[parent_object]
|
24
|
-
end
|
10
|
+
@storage = Hash.new do |h, argument_owner|
|
11
|
+
args_by_parent = if argument_owner.arguments_statically_coercible?
|
12
|
+
shared_values_cache = {}
|
13
|
+
Hash.new do |h2, ignored_parent_object|
|
14
|
+
h2[ignored_parent_object] = shared_values_cache
|
15
|
+
end
|
16
|
+
else
|
17
|
+
Hash.new do |h2, parent_object|
|
18
|
+
args_by_node = {}
|
19
|
+
args_by_node.compare_by_identity
|
20
|
+
h2[parent_object] = args_by_node
|
25
21
|
end
|
26
22
|
end
|
23
|
+
args_by_parent.compare_by_identity
|
24
|
+
h[argument_owner] = args_by_parent
|
27
25
|
end
|
26
|
+
@storage.compare_by_identity
|
28
27
|
end
|
29
28
|
|
30
29
|
def fetch(ast_node, argument_owner, parent_object)
|
31
|
-
#
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
@
|
36
|
-
@storage[
|
30
|
+
# This runs eagerly if no block is given
|
31
|
+
@storage[argument_owner][parent_object][ast_node] ||= begin
|
32
|
+
args_hash = self.class.prepare_args_hash(@query, ast_node)
|
33
|
+
kwarg_arguments = argument_owner.coerce_arguments(parent_object, args_hash, @query.context)
|
34
|
+
@query.after_lazy(kwarg_arguments) do |resolved_args|
|
35
|
+
@storage[argument_owner][parent_object][ast_node] = resolved_args
|
37
36
|
end
|
38
37
|
end
|
39
|
-
|
40
|
-
# overridden with an immutable arguments instance.
|
41
|
-
# The first call queues up the job,
|
42
|
-
# then this call fetches the result.
|
43
|
-
# TODO this should be better, find a solution
|
44
|
-
# that works with merging the runtime.rb code
|
45
|
-
@storage[ast_node][argument_owner][parent_object]
|
38
|
+
|
46
39
|
end
|
47
40
|
|
48
41
|
# @yield [Interpreter::Arguments, Lazy<Interpreter::Arguments>] The finally-loaded arguments
|
49
42
|
def dataload_for(ast_node, argument_owner, parent_object, &block)
|
50
43
|
# First, normalize all AST or Ruby values to a plain Ruby hash
|
51
|
-
|
52
|
-
|
44
|
+
arg_storage = @storage[argument_owner][parent_object]
|
45
|
+
if (args = arg_storage[ast_node])
|
46
|
+
yield(args)
|
47
|
+
else
|
48
|
+
args_hash = self.class.prepare_args_hash(@query, ast_node)
|
49
|
+
argument_owner.coerce_arguments(parent_object, args_hash, @query.context) do |resolved_args|
|
50
|
+
arg_storage[ast_node] = resolved_args
|
51
|
+
yield(resolved_args)
|
52
|
+
end
|
53
|
+
end
|
53
54
|
nil
|
54
55
|
end
|
55
56
|
|
56
57
|
private
|
57
58
|
|
58
|
-
NO_ARGUMENTS =
|
59
|
-
|
60
|
-
NO_VALUE_GIVEN = Object.new
|
59
|
+
NO_ARGUMENTS = GraphQL::EmptyObjects::EMPTY_HASH
|
60
|
+
NO_VALUE_GIVEN = NOT_CONFIGURED
|
61
61
|
|
62
62
|
def self.prepare_args_hash(query, ast_arg_or_hash_or_value)
|
63
63
|
case ast_arg_or_hash_or_value
|