graphql 2.0.16 → 2.0.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql/analysis/ast/visitor.rb +42 -35
- data/lib/graphql/analysis/ast.rb +2 -2
- data/lib/graphql/backtrace/trace.rb +96 -0
- data/lib/graphql/backtrace/tracer.rb +1 -1
- data/lib/graphql/backtrace.rb +6 -1
- data/lib/graphql/execution/interpreter/arguments.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +2 -3
- data/lib/graphql/execution/interpreter/resolve.rb +19 -0
- data/lib/graphql/execution/interpreter/runtime.rb +264 -211
- data/lib/graphql/execution/interpreter.rb +15 -10
- data/lib/graphql/execution/lazy.rb +6 -12
- data/lib/graphql/execution/multiplex.rb +2 -1
- data/lib/graphql/filter.rb +7 -2
- data/lib/graphql/introspection/directive_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +2 -2
- data/lib/graphql/introspection/type_type.rb +5 -5
- data/lib/graphql/language/document_from_schema_definition.rb +25 -9
- data/lib/graphql/language/lexer.rb +216 -1505
- data/lib/graphql/language/nodes.rb +66 -40
- data/lib/graphql/language/parser.rb +509 -491
- data/lib/graphql/language/parser.y +43 -38
- data/lib/graphql/language/visitor.rb +191 -83
- data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
- data/lib/graphql/pagination/connection.rb +5 -5
- data/lib/graphql/query/context.rb +62 -31
- data/lib/graphql/query/null_context.rb +1 -1
- data/lib/graphql/query.rb +22 -5
- data/lib/graphql/schema/argument.rb +7 -13
- data/lib/graphql/schema/build_from_definition.rb +15 -3
- data/lib/graphql/schema/directive.rb +12 -2
- data/lib/graphql/schema/enum.rb +24 -17
- data/lib/graphql/schema/enum_value.rb +2 -3
- data/lib/graphql/schema/field.rb +68 -57
- data/lib/graphql/schema/field_extension.rb +1 -4
- data/lib/graphql/schema/find_inherited_value.rb +2 -7
- data/lib/graphql/schema/interface.rb +0 -10
- data/lib/graphql/schema/late_bound_type.rb +2 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +17 -14
- data/lib/graphql/schema/member/has_arguments.rb +105 -58
- data/lib/graphql/schema/member/has_ast_node.rb +12 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
- data/lib/graphql/schema/member/has_directives.rb +15 -10
- data/lib/graphql/schema/member/has_fields.rb +95 -38
- data/lib/graphql/schema/member/has_interfaces.rb +49 -8
- data/lib/graphql/schema/member/has_validators.rb +32 -6
- data/lib/graphql/schema/member/relay_shortcuts.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +17 -0
- data/lib/graphql/schema/object.rb +2 -4
- data/lib/graphql/schema/resolver/has_payload_type.rb +9 -9
- data/lib/graphql/schema/resolver.rb +4 -4
- data/lib/graphql/schema/timeout.rb +24 -28
- data/lib/graphql/schema/validator.rb +1 -1
- data/lib/graphql/schema/warden.rb +29 -5
- data/lib/graphql/schema.rb +76 -25
- data/lib/graphql/static_validation/literal_validator.rb +15 -1
- 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/static_validation/validator.rb +1 -1
- data/lib/graphql/subscriptions/event.rb +2 -7
- data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
- data/lib/graphql/tracing/appoptics_trace.rb +231 -0
- data/lib/graphql/tracing/appsignal_trace.rb +77 -0
- data/lib/graphql/tracing/data_dog_trace.rb +148 -0
- data/lib/graphql/tracing/legacy_trace.rb +65 -0
- data/lib/graphql/tracing/new_relic_trace.rb +75 -0
- data/lib/graphql/tracing/notifications_trace.rb +42 -0
- data/lib/graphql/tracing/platform_trace.rb +109 -0
- data/lib/graphql/tracing/platform_tracing.rb +15 -3
- data/lib/graphql/tracing/prometheus_trace.rb +89 -0
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +1 -1
- data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
- data/lib/graphql/tracing/scout_trace.rb +72 -0
- data/lib/graphql/tracing/statsd_trace.rb +56 -0
- data/lib/graphql/tracing/trace.rb +75 -0
- data/lib/graphql/tracing.rb +16 -39
- data/lib/graphql/type_kinds.rb +6 -3
- data/lib/graphql/types/relay/base_connection.rb +1 -1
- data/lib/graphql/types/relay/connection_behaviors.rb +24 -6
- data/lib/graphql/types/relay/edge_behaviors.rb +16 -6
- data/lib/graphql/types/relay/node_behaviors.rb +7 -1
- data/lib/graphql/types/relay/page_info_behaviors.rb +7 -2
- data/lib/graphql/types/relay.rb +0 -1
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +16 -9
- metadata +34 -9
- data/lib/graphql/language/lexer.rl +0 -280
- data/lib/graphql/types/relay/default_relay.rb +0 -27
@@ -14,7 +14,7 @@ module GraphQL
|
|
14
14
|
class << self
|
15
15
|
# Used internally to signal that the query shouldn't be executed
|
16
16
|
# @api private
|
17
|
-
NO_OPERATION =
|
17
|
+
NO_OPERATION = GraphQL::EmptyObjects::EMPTY_HASH
|
18
18
|
|
19
19
|
# @param schema [GraphQL::Schema]
|
20
20
|
# @param queries [Array<GraphQL::Query, Hash>]
|
@@ -34,11 +34,12 @@ module GraphQL
|
|
34
34
|
end
|
35
35
|
|
36
36
|
multiplex = Execution::Multiplex.new(schema: schema, queries: queries, context: context, max_complexity: max_complexity)
|
37
|
-
multiplex.
|
37
|
+
multiplex.current_trace.execute_multiplex(multiplex: multiplex) do
|
38
38
|
schema = multiplex.schema
|
39
39
|
queries = multiplex.queries
|
40
40
|
query_instrumenters = schema.instrumenters[:query]
|
41
41
|
multiplex_instrumenters = schema.instrumenters[:multiplex]
|
42
|
+
lazies_at_depth = Hash.new { |h, k| h[k] = [] }
|
42
43
|
|
43
44
|
# First, run multiplex instrumentation, then query instrumentation for each query
|
44
45
|
call_hooks(multiplex_instrumenters, multiplex, :before_multiplex, :after_multiplex) do
|
@@ -67,10 +68,10 @@ module GraphQL
|
|
67
68
|
# Although queries in a multiplex _share_ an Interpreter instance,
|
68
69
|
# they also have another item of state, which is private to that query
|
69
70
|
# in particular, assign it here:
|
70
|
-
runtime = Runtime.new(query: query)
|
71
|
+
runtime = Runtime.new(query: query, lazies_at_depth: lazies_at_depth)
|
71
72
|
query.context.namespace(:interpreter_runtime)[:runtime] = runtime
|
72
73
|
|
73
|
-
query.
|
74
|
+
query.current_trace.execute_query(query: query) do
|
74
75
|
runtime.run_eager
|
75
76
|
end
|
76
77
|
rescue GraphQL::ExecutionError => err
|
@@ -95,16 +96,13 @@ module GraphQL
|
|
95
96
|
runtime ? runtime.final_result : nil
|
96
97
|
end
|
97
98
|
final_values.compact!
|
98
|
-
tracer.
|
99
|
-
Interpreter::Resolve.
|
99
|
+
tracer.current_trace.execute_query_lazy(multiplex: multiplex, query: query) do
|
100
|
+
Interpreter::Resolve.resolve_each_depth(lazies_at_depth, multiplex.dataloader)
|
100
101
|
end
|
101
102
|
queries.each do |query|
|
102
103
|
runtime = query.context.namespace(:interpreter_runtime)[:runtime]
|
103
104
|
if runtime
|
104
|
-
runtime.
|
105
|
-
runtime.delete_interpreter_context(:current_field)
|
106
|
-
runtime.delete_interpreter_context(:current_object)
|
107
|
-
runtime.delete_interpreter_context(:current_arguments)
|
105
|
+
runtime.delete_all_interpreter_context
|
108
106
|
end
|
109
107
|
end
|
110
108
|
}
|
@@ -146,6 +144,13 @@ module GraphQL
|
|
146
144
|
# Assign values here so that the query's `@executed` becomes true
|
147
145
|
queries.map { |q| q.result_values ||= {} }
|
148
146
|
raise
|
147
|
+
ensure
|
148
|
+
queries.map { |query|
|
149
|
+
runtime = query.context.namespace(:interpreter_runtime)[:runtime]
|
150
|
+
if runtime
|
151
|
+
runtime.delete_all_interpreter_context
|
152
|
+
end
|
153
|
+
}
|
149
154
|
end
|
150
155
|
end
|
151
156
|
end
|
@@ -12,16 +12,14 @@ module GraphQL
|
|
12
12
|
# - It has no error-catching functionality
|
13
13
|
# @api private
|
14
14
|
class Lazy
|
15
|
-
attr_reader :
|
15
|
+
attr_reader :field
|
16
16
|
|
17
17
|
# Create a {Lazy} which will get its inner value by calling the block
|
18
|
-
# @param path [Array<String, Integer>]
|
19
18
|
# @param field [GraphQL::Schema::Field]
|
20
19
|
# @param get_value_func [Proc] a block to get the inner value (later)
|
21
|
-
def initialize(
|
20
|
+
def initialize(field: nil, &get_value_func)
|
22
21
|
@get_value_func = get_value_func
|
23
22
|
@resolved = false
|
24
|
-
@path = path
|
25
23
|
@field = field
|
26
24
|
end
|
27
25
|
|
@@ -29,15 +27,11 @@ module GraphQL
|
|
29
27
|
def value
|
30
28
|
if !@resolved
|
31
29
|
@resolved = true
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
v = v.value
|
36
|
-
end
|
37
|
-
v
|
38
|
-
rescue GraphQL::ExecutionError => err
|
39
|
-
err
|
30
|
+
v = @get_value_func.call
|
31
|
+
if v.is_a?(Lazy)
|
32
|
+
v = v.value
|
40
33
|
end
|
34
|
+
@value = v
|
41
35
|
end
|
42
36
|
|
43
37
|
# `SKIP` was made into a subclass of `GraphQL::Error` to improve runtime performance
|
@@ -25,13 +25,14 @@ module GraphQL
|
|
25
25
|
class Multiplex
|
26
26
|
include Tracing::Traceable
|
27
27
|
|
28
|
-
attr_reader :context, :queries, :schema, :max_complexity, :dataloader
|
28
|
+
attr_reader :context, :queries, :schema, :max_complexity, :dataloader, :current_trace
|
29
29
|
|
30
30
|
def initialize(schema:, queries:, context:, max_complexity:)
|
31
31
|
@schema = schema
|
32
32
|
@queries = queries
|
33
33
|
@queries.each { |q| q.multiplex = self }
|
34
34
|
@context = context
|
35
|
+
@current_trace = @context[:trace] || schema.new_trace(multiplex: self)
|
35
36
|
@dataloader = @context[:dataloader] ||= @schema.dataloader_class.new
|
36
37
|
@tracers = schema.tracers + (context[:tracers] || [])
|
37
38
|
# Support `context: {backtrace: true}`
|
data/lib/graphql/filter.rb
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require "graphql/deprecation"
|
3
|
+
|
2
4
|
module GraphQL
|
3
5
|
# @api private
|
4
6
|
class Filter
|
5
|
-
def initialize(only: nil, except: nil)
|
7
|
+
def initialize(only: nil, except: nil, silence_deprecation_warning: false)
|
8
|
+
if !silence_deprecation_warning
|
9
|
+
GraphQL::Deprecation.warn("GraphQL::Filter is deprecated and will be removed in v2.1.0. Implement `visible?` on your schema members instead (https://graphql-ruby.org/authorization/visibility.html).")
|
10
|
+
end
|
6
11
|
@only = only
|
7
12
|
@except = except
|
8
13
|
end
|
@@ -17,7 +22,7 @@ module GraphQL
|
|
17
22
|
onlies = [self].concat(Array(only))
|
18
23
|
merged_only = MergedOnly.build(onlies)
|
19
24
|
merged_except = MergedExcept.build(Array(except))
|
20
|
-
self.class.new(only: merged_only, except: merged_except)
|
25
|
+
self.class.new(only: merged_only, except: merged_except, silence_deprecation_warning: true)
|
21
26
|
end
|
22
27
|
|
23
28
|
private
|
@@ -11,8 +11,8 @@ module GraphQL
|
|
11
11
|
"to the executor."
|
12
12
|
field :name, String, null: false, method: :graphql_name
|
13
13
|
field :description, String
|
14
|
-
field :locations, [GraphQL::Schema::LateBoundType.new("__DirectiveLocation")], null: false
|
15
|
-
field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
|
14
|
+
field :locations, [GraphQL::Schema::LateBoundType.new("__DirectiveLocation")], null: false, scope: false
|
15
|
+
field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false, scope: false do
|
16
16
|
argument :include_deprecated, Boolean, required: false, default_value: false
|
17
17
|
end
|
18
18
|
field :on_operation, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_operation?
|
@@ -7,7 +7,7 @@ module GraphQL
|
|
7
7
|
"a name, potentially a list of arguments, and a return type."
|
8
8
|
field :name, String, null: false
|
9
9
|
field :description, String
|
10
|
-
field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
|
10
|
+
field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false, scope: false do
|
11
11
|
argument :include_deprecated, Boolean, required: false, default_value: false
|
12
12
|
end
|
13
13
|
field :type, GraphQL::Schema::LateBoundType.new("__Type"), null: false
|
@@ -8,11 +8,11 @@ module GraphQL
|
|
8
8
|
"available types and directives on the server, as well as the entry points for "\
|
9
9
|
"query, mutation, and subscription operations."
|
10
10
|
|
11
|
-
field :types, [GraphQL::Schema::LateBoundType.new("__Type")], "A list of all types supported by this server.", null: false
|
11
|
+
field :types, [GraphQL::Schema::LateBoundType.new("__Type")], "A list of all types supported by this server.", null: false, scope: false
|
12
12
|
field :query_type, GraphQL::Schema::LateBoundType.new("__Type"), "The type that query operations will be rooted at.", null: false
|
13
13
|
field :mutation_type, GraphQL::Schema::LateBoundType.new("__Type"), "If this server supports mutation, the type that mutation operations will be rooted at."
|
14
14
|
field :subscription_type, GraphQL::Schema::LateBoundType.new("__Type"), "If this server support subscription, the type that subscription operations will be rooted at."
|
15
|
-
field :directives, [GraphQL::Schema::LateBoundType.new("__Directive")], "A list of all directives supported by this server.", null: false
|
15
|
+
field :directives, [GraphQL::Schema::LateBoundType.new("__Directive")], "A list of all directives supported by this server.", null: false, scope: false
|
16
16
|
field :description, String, resolver_method: :schema_description
|
17
17
|
|
18
18
|
def schema_description
|
@@ -14,15 +14,15 @@ module GraphQL
|
|
14
14
|
field :kind, GraphQL::Schema::LateBoundType.new("__TypeKind"), null: false
|
15
15
|
field :name, String, method: :graphql_name
|
16
16
|
field :description, String
|
17
|
-
field :fields, [GraphQL::Schema::LateBoundType.new("__Field")] do
|
17
|
+
field :fields, [GraphQL::Schema::LateBoundType.new("__Field")], scope: false do
|
18
18
|
argument :include_deprecated, Boolean, required: false, default_value: false
|
19
19
|
end
|
20
|
-
field :interfaces, [GraphQL::Schema::LateBoundType.new("__Type")]
|
21
|
-
field :possible_types, [GraphQL::Schema::LateBoundType.new("__Type")]
|
22
|
-
field :enum_values, [GraphQL::Schema::LateBoundType.new("__EnumValue")] do
|
20
|
+
field :interfaces, [GraphQL::Schema::LateBoundType.new("__Type")], scope: false
|
21
|
+
field :possible_types, [GraphQL::Schema::LateBoundType.new("__Type")], scope: false
|
22
|
+
field :enum_values, [GraphQL::Schema::LateBoundType.new("__EnumValue")], scope: false do
|
23
23
|
argument :include_deprecated, Boolean, required: false, default_value: false
|
24
24
|
end
|
25
|
-
field :input_fields, [GraphQL::Schema::LateBoundType.new("__InputValue")] do
|
25
|
+
field :input_fields, [GraphQL::Schema::LateBoundType.new("__InputValue")], scope: false do
|
26
26
|
argument :include_deprecated, Boolean, required: false, default_value: false
|
27
27
|
end
|
28
28
|
field :of_type, GraphQL::Schema::LateBoundType.new("__Type")
|
@@ -22,8 +22,9 @@ module GraphQL
|
|
22
22
|
@include_introspection_types = include_introspection_types
|
23
23
|
@include_built_in_scalars = include_built_in_scalars
|
24
24
|
@include_built_in_directives = include_built_in_directives
|
25
|
+
@include_one_of = false
|
25
26
|
|
26
|
-
filter = GraphQL::Filter.new(only: only, except: except)
|
27
|
+
filter = GraphQL::Filter.new(only: only, except: except, silence_deprecation_warning: true)
|
27
28
|
if @schema.respond_to?(:visible?)
|
28
29
|
filter = filter.merge(only: @schema.method(:visible?))
|
29
30
|
end
|
@@ -245,20 +246,30 @@ module GraphQL
|
|
245
246
|
end
|
246
247
|
|
247
248
|
def build_directive_nodes(directives)
|
248
|
-
if !include_built_in_directives
|
249
|
-
directives = directives.reject { |directive| directive.default_directive? }
|
250
|
-
end
|
251
|
-
|
252
249
|
directives
|
253
250
|
.map { |directive| build_directive_node(directive) }
|
254
251
|
.sort_by(&:name)
|
255
252
|
end
|
256
253
|
|
257
254
|
def build_definition_nodes
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
255
|
+
dirs_to_build = warden.directives
|
256
|
+
if !include_built_in_directives
|
257
|
+
dirs_to_build = dirs_to_build.reject { |directive| directive.default_directive? }
|
258
|
+
end
|
259
|
+
dir_nodes = build_directive_nodes(dirs_to_build)
|
260
|
+
|
261
|
+
type_nodes = build_type_definition_nodes(warden.reachable_types)
|
262
|
+
|
263
|
+
if @include_one_of
|
264
|
+
# This may have been set to true when iterating over all types
|
265
|
+
dir_nodes.concat(build_directive_nodes([GraphQL::Schema::Directive::OneOf]))
|
266
|
+
end
|
267
|
+
|
268
|
+
definitions = [*dir_nodes, *type_nodes]
|
269
|
+
if include_schema_node?
|
270
|
+
definitions.unshift(build_schema_node)
|
271
|
+
end
|
272
|
+
|
262
273
|
definitions
|
263
274
|
end
|
264
275
|
|
@@ -318,6 +329,11 @@ module GraphQL
|
|
318
329
|
)
|
319
330
|
end
|
320
331
|
end
|
332
|
+
|
333
|
+
# If this schema uses this built-in directive definition,
|
334
|
+
# include it in the print-out since it's not part of the spec yet.
|
335
|
+
@include_one_of ||= dir.class == GraphQL::Schema::Directive::OneOf
|
336
|
+
|
321
337
|
GraphQL::Language::Nodes::Directive.new(
|
322
338
|
name: dir.class.graphql_name,
|
323
339
|
arguments: args
|