graphql 2.1.11 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql/dataloader/async_dataloader.rb +88 -0
- data/lib/graphql/dataloader/source.rb +4 -3
- data/lib/graphql/dataloader.rb +35 -21
- data/lib/graphql/language/lexer.rb +271 -177
- data/lib/graphql/language/nodes.rb +72 -54
- data/lib/graphql/language/parser.rb +686 -1986
- data/lib/graphql/language/printer.rb +16 -12
- data/lib/graphql/schema.rb +6 -5
- data/lib/graphql/testing/helpers.rb +125 -0
- data/lib/graphql/testing.rb +2 -0
- data/lib/graphql/tracing/data_dog_trace.rb +34 -21
- data/lib/graphql/tracing/data_dog_tracing.rb +21 -7
- data/lib/graphql/tracing/trace.rb +1 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +1 -0
- metadata +6 -4
- data/lib/graphql/language/parser.y +0 -560
@@ -337,14 +337,16 @@ module GraphQL
|
|
337
337
|
print_string("union ")
|
338
338
|
print_string(union_type.name)
|
339
339
|
print_directives(union_type.directives)
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
340
|
+
if union_type.types.any?
|
341
|
+
print_string(" = ")
|
342
|
+
i = 0
|
343
|
+
union_type.types.each do |t|
|
344
|
+
if i > 0
|
345
|
+
print_string(" | ")
|
346
|
+
end
|
347
|
+
print_string(t.name)
|
348
|
+
i += 1
|
345
349
|
end
|
346
|
-
print_string(t.name)
|
347
|
-
i += 1
|
348
350
|
end
|
349
351
|
end
|
350
352
|
|
@@ -353,12 +355,14 @@ module GraphQL
|
|
353
355
|
print_string("enum ")
|
354
356
|
print_string(enum_type.name)
|
355
357
|
print_directives(enum_type.directives)
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
358
|
+
if enum_type.values.any?
|
359
|
+
print_string(" {\n")
|
360
|
+
enum_type.values.each.with_index do |value, i|
|
361
|
+
print_description(value, indent: " ", first_in_block: i == 0)
|
362
|
+
print_enum_value_definition(value)
|
363
|
+
end
|
364
|
+
print_string("}")
|
360
365
|
end
|
361
|
-
print_string("}")
|
362
366
|
end
|
363
367
|
|
364
368
|
def print_enum_value_definition(enum_value)
|
data/lib/graphql/schema.rb
CHANGED
@@ -384,6 +384,11 @@ module GraphQL
|
|
384
384
|
(superclass.respond_to?(:get_type) ? superclass.get_type(type_name, context) : nil)
|
385
385
|
end
|
386
386
|
|
387
|
+
# @return [Boolean] Does this schema have _any_ definition for a type named `type_name`, regardless of visibility?
|
388
|
+
def has_defined_type?(type_name)
|
389
|
+
own_types.key?(type_name) || introspection_system.types.key?(type_name) || (superclass.respond_to?(:has_defined_type?) ? superclass.has_defined_type?(type_name) : false)
|
390
|
+
end
|
391
|
+
|
387
392
|
# @api private
|
388
393
|
attr_writer :connections
|
389
394
|
|
@@ -939,11 +944,7 @@ module GraphQL
|
|
939
944
|
end
|
940
945
|
|
941
946
|
def resolve_type(type, obj, ctx)
|
942
|
-
|
943
|
-
type
|
944
|
-
else
|
945
|
-
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types or Interface types (tried to resolve: #{type.name})"
|
946
|
-
end
|
947
|
+
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types, Interface types, or `loads:` (tried to resolve: #{type.name})"
|
947
948
|
end
|
948
949
|
# rubocop:enable Lint/DuplicateMethods
|
949
950
|
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module GraphQL
|
3
|
+
module Testing
|
4
|
+
module Helpers
|
5
|
+
# @param schema_class [Class<GraphQL::Schema>]
|
6
|
+
# @return [Module] A helpers module which always uses the given schema
|
7
|
+
def self.for(schema_class)
|
8
|
+
Module.new do
|
9
|
+
include SchemaHelpers
|
10
|
+
@@schema_class_for_helpers = schema_class
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Error < GraphQL::Error
|
15
|
+
end
|
16
|
+
|
17
|
+
class TypeNotVisibleError < Error
|
18
|
+
def initialize(type_name:)
|
19
|
+
message = "`#{type_name}` should be `visible?` this field resolution and `context`, but it was not"
|
20
|
+
super(message)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class FieldNotVisibleError < Error
|
25
|
+
def initialize(type_name:, field_name:)
|
26
|
+
message = "`#{type_name}.#{field_name}` should be `visible?` for this resolution, but it was not"
|
27
|
+
super(message)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class TypeNotDefinedError < Error
|
32
|
+
def initialize(type_name:)
|
33
|
+
message = "No type named `#{type_name}` is defined; choose another type name or define this type."
|
34
|
+
super(message)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class FieldNotDefinedError < Error
|
39
|
+
def initialize(type_name:, field_name:)
|
40
|
+
message = "`#{type_name}` has no field named `#{field_name}`; pick another name or define this field."
|
41
|
+
super(message)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def run_graphql_field(schema, field_path, object, arguments: {}, context: {})
|
46
|
+
type_name, *field_names = field_path.split(".")
|
47
|
+
dummy_query = GraphQL::Query.new(schema, context: context)
|
48
|
+
query_context = dummy_query.context
|
49
|
+
object_type = dummy_query.get_type(type_name) # rubocop:disable Development/ContextIsPassedCop
|
50
|
+
if object_type
|
51
|
+
graphql_result = object
|
52
|
+
field_names.each do |field_name|
|
53
|
+
inner_object = graphql_result
|
54
|
+
graphql_result = object_type.wrap(inner_object, query_context)
|
55
|
+
if graphql_result.nil?
|
56
|
+
return nil
|
57
|
+
end
|
58
|
+
visible_field = dummy_query.get_field(object_type, field_name)
|
59
|
+
if visible_field
|
60
|
+
dummy_query.context.dataloader.run_isolated {
|
61
|
+
field_args = visible_field.coerce_arguments(graphql_result, arguments, query_context)
|
62
|
+
field_args = schema.sync_lazy(field_args)
|
63
|
+
graphql_result = visible_field.resolve(graphql_result, field_args.keyword_arguments, query_context)
|
64
|
+
graphql_result = schema.sync_lazy(graphql_result)
|
65
|
+
}
|
66
|
+
object_type = visible_field.type.unwrap
|
67
|
+
elsif object_type.all_field_definitions.any? { |f| f.graphql_name == field_name }
|
68
|
+
raise FieldNotVisibleError.new(field_name: field_name, type_name: type_name)
|
69
|
+
else
|
70
|
+
raise FieldNotDefinedError.new(type_name: type_name, field_name: field_name)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
graphql_result
|
74
|
+
elsif schema.has_defined_type?(type_name)
|
75
|
+
raise TypeNotVisibleError.new(type_name: type_name)
|
76
|
+
else
|
77
|
+
raise TypeNotDefinedError.new(type_name: type_name)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def with_resolution_context(schema, type:, object:, context:{})
|
82
|
+
resolution_context = ResolutionAssertionContext.new(
|
83
|
+
self,
|
84
|
+
schema: schema,
|
85
|
+
type_name: type,
|
86
|
+
object: object,
|
87
|
+
context: context
|
88
|
+
)
|
89
|
+
yield(resolution_context)
|
90
|
+
end
|
91
|
+
|
92
|
+
class ResolutionAssertionContext
|
93
|
+
def initialize(test, type_name:, object:, schema:, context:)
|
94
|
+
@test = test
|
95
|
+
@type_name = type_name
|
96
|
+
@object = object
|
97
|
+
@schema = schema
|
98
|
+
@context = context
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
def run_graphql_field(field_name, arguments: {})
|
103
|
+
if @schema
|
104
|
+
@test.run_graphql_field(@schema, "#{@type_name}.#{field_name}", @object, arguments: arguments, context: @context)
|
105
|
+
else
|
106
|
+
@test.run_graphql_field("#{@type_name}.#{field_name}", @object, arguments: arguments, context: @context)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
module SchemaHelpers
|
112
|
+
include Helpers
|
113
|
+
|
114
|
+
def run_graphql_field(field_path, object, arguments: {}, context: {})
|
115
|
+
super(@@schema_class_for_helpers, field_path, object, arguments: arguments, context: context)
|
116
|
+
end
|
117
|
+
|
118
|
+
def with_resolution_context(*args, **kwargs, &block)
|
119
|
+
# schema will be added later
|
120
|
+
super(nil, *args, **kwargs, &block)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -3,18 +3,20 @@
|
|
3
3
|
module GraphQL
|
4
4
|
module Tracing
|
5
5
|
module DataDogTrace
|
6
|
-
# @param tracer [#trace] Deprecated
|
7
6
|
# @param analytics_enabled [Boolean] Deprecated
|
8
7
|
# @param analytics_sample_rate [Float] Deprecated
|
9
|
-
def initialize(tracer: nil, analytics_enabled: false, analytics_sample_rate: 1.0, service:
|
8
|
+
def initialize(tracer: nil, analytics_enabled: false, analytics_sample_rate: 1.0, service: "ruby-graphql", **rest)
|
10
9
|
if tracer.nil?
|
11
10
|
tracer = defined?(Datadog::Tracing) ? Datadog::Tracing : Datadog.tracer
|
12
11
|
end
|
13
12
|
@tracer = tracer
|
14
13
|
|
15
|
-
|
16
|
-
|
14
|
+
analytics_available = defined?(Datadog::Contrib::Analytics) \
|
15
|
+
&& Datadog::Contrib::Analytics.respond_to?(:enabled?) \
|
16
|
+
&& Datadog::Contrib::Analytics.respond_to?(:set_sample_rate)
|
17
17
|
|
18
|
+
@analytics_enabled = analytics_available && Datadog::Contrib::Analytics.enabled?(analytics_enabled)
|
19
|
+
@analytics_sample_rate = analytics_sample_rate
|
18
20
|
@service_name = service
|
19
21
|
@has_prepare_span = respond_to?(:prepare_span)
|
20
22
|
super
|
@@ -32,9 +34,12 @@ module GraphQL
|
|
32
34
|
}.each do |trace_method, trace_key|
|
33
35
|
module_eval <<-RUBY, __FILE__, __LINE__
|
34
36
|
def #{trace_method}(**data)
|
35
|
-
@tracer.trace("#{trace_key}", service: @service_name
|
36
|
-
|
37
|
-
|
37
|
+
@tracer.trace("#{trace_key}", service: @service_name) do |span|
|
38
|
+
span.span_type = 'custom'
|
39
|
+
if defined?(Datadog::Tracing::Metadata::Ext) # Introduced in ddtrace 1.0
|
40
|
+
span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT, 'graphql')
|
41
|
+
span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION, '#{trace_method}')
|
42
|
+
end
|
38
43
|
|
39
44
|
#{
|
40
45
|
if trace_method == 'execute_multiplex'
|
@@ -49,8 +54,10 @@ module GraphQL
|
|
49
54
|
end
|
50
55
|
span.resource = resource if resource
|
51
56
|
|
52
|
-
#
|
53
|
-
|
57
|
+
# For top span of query, set the analytics sample rate tag, if available.
|
58
|
+
if @analytics_enabled
|
59
|
+
Datadog::Contrib::Analytics.set_sample_rate(span, @analytics_sample_rate)
|
60
|
+
end
|
54
61
|
RUBY
|
55
62
|
elsif trace_method == 'execute_query'
|
56
63
|
<<-RUBY
|
@@ -82,10 +89,12 @@ module GraphQL
|
|
82
89
|
nil
|
83
90
|
end
|
84
91
|
if platform_key && trace_field
|
85
|
-
@tracer.trace(platform_key, service: @service_name
|
86
|
-
span.
|
87
|
-
|
88
|
-
|
92
|
+
@tracer.trace(platform_key, service: @service_name) do |span|
|
93
|
+
span.span_type = 'custom'
|
94
|
+
if defined?(Datadog::Tracing::Metadata::Ext) # Introduced in ddtrace 1.0
|
95
|
+
span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT, 'graphql')
|
96
|
+
span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION, span_key)
|
97
|
+
end
|
89
98
|
if @has_prepare_span
|
90
99
|
prepare_span_data = { query: query, field: field, ast_node: ast_node, arguments: arguments, object: object }
|
91
100
|
prepare_span(span_key, prepare_span_data, span)
|
@@ -116,10 +125,12 @@ module GraphQL
|
|
116
125
|
|
117
126
|
def authorized_span(span_key, object, type, query)
|
118
127
|
platform_key = @platform_key_cache[DataDogTrace].platform_authorized_key_cache[type]
|
119
|
-
@tracer.trace(platform_key, service: @service_name
|
120
|
-
span.
|
121
|
-
|
122
|
-
|
128
|
+
@tracer.trace(platform_key, service: @service_name) do |span|
|
129
|
+
span.span_type = 'custom'
|
130
|
+
if defined?(Datadog::Tracing::Metadata::Ext) # Introduced in ddtrace 1.0
|
131
|
+
span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT, 'graphql')
|
132
|
+
span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION, span_key)
|
133
|
+
end
|
123
134
|
if @has_prepare_span
|
124
135
|
prepare_span(span_key, {object: object, type: type, query: query}, span)
|
125
136
|
end
|
@@ -147,10 +158,12 @@ module GraphQL
|
|
147
158
|
|
148
159
|
def resolve_type_span(span_key, object, type, query)
|
149
160
|
platform_key = @platform_key_cache[DataDogTrace].platform_resolve_type_key_cache[type]
|
150
|
-
@tracer.trace(platform_key, service: @service_name
|
151
|
-
span.
|
152
|
-
|
153
|
-
|
161
|
+
@tracer.trace(platform_key, service: @service_name) do |span|
|
162
|
+
span.span_type = 'custom'
|
163
|
+
if defined?(Datadog::Tracing::Metadata::Ext) # Introduced in ddtrace 1.0
|
164
|
+
span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT, 'graphql')
|
165
|
+
span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION, span_key)
|
166
|
+
end
|
154
167
|
if @has_prepare_span
|
155
168
|
prepare_span(span_key, {object: object, type: type, query: query}, span)
|
156
169
|
end
|
@@ -15,9 +15,12 @@ module GraphQL
|
|
15
15
|
}
|
16
16
|
|
17
17
|
def platform_trace(platform_key, key, data)
|
18
|
-
tracer.trace(platform_key, service:
|
19
|
-
span.
|
20
|
-
|
18
|
+
tracer.trace(platform_key, service: service_name) do |span|
|
19
|
+
span.span_type = 'custom'
|
20
|
+
if defined?(Datadog::Tracing::Metadata::Ext) # Introduced in ddtrace 1.0
|
21
|
+
span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_COMPONENT, 'graphql')
|
22
|
+
span.set_tag(Datadog::Tracing::Metadata::Ext::TAG_OPERATION, key)
|
23
|
+
end
|
21
24
|
|
22
25
|
if key == 'execute_multiplex'
|
23
26
|
operations = data[:multiplex].queries.map(&:selected_operation_name).join(', ')
|
@@ -30,8 +33,10 @@ module GraphQL
|
|
30
33
|
end
|
31
34
|
span.resource = resource if resource
|
32
35
|
|
33
|
-
#
|
34
|
-
|
36
|
+
# For top span of query, set the analytics sample rate tag, if available.
|
37
|
+
if analytics_enabled?
|
38
|
+
Datadog::Contrib::Analytics.set_sample_rate(span, analytics_sample_rate)
|
39
|
+
end
|
35
40
|
end
|
36
41
|
|
37
42
|
if key == 'execute_query'
|
@@ -46,6 +51,10 @@ module GraphQL
|
|
46
51
|
end
|
47
52
|
end
|
48
53
|
|
54
|
+
def service_name
|
55
|
+
options.fetch(:service, 'ruby-graphql')
|
56
|
+
end
|
57
|
+
|
49
58
|
# Implement this method in a subclass to apply custom tags to datadog spans
|
50
59
|
# @param key [String] The event being traced
|
51
60
|
# @param data [Hash] The runtime data for this event (@see GraphQL::Tracing for keys for each event)
|
@@ -56,13 +65,18 @@ module GraphQL
|
|
56
65
|
def tracer
|
57
66
|
default_tracer = defined?(Datadog::Tracing) ? Datadog::Tracing : Datadog.tracer
|
58
67
|
|
59
|
-
# [Deprecated] options[:tracer] will be removed in the future
|
60
68
|
options.fetch(:tracer, default_tracer)
|
61
69
|
end
|
62
70
|
|
71
|
+
def analytics_available?
|
72
|
+
defined?(Datadog::Contrib::Analytics) \
|
73
|
+
&& Datadog::Contrib::Analytics.respond_to?(:enabled?) \
|
74
|
+
&& Datadog::Contrib::Analytics.respond_to?(:set_sample_rate)
|
75
|
+
end
|
76
|
+
|
63
77
|
def analytics_enabled?
|
64
78
|
# [Deprecated] options[:analytics_enabled] will be removed in the future
|
65
|
-
options.fetch(:analytics_enabled, false)
|
79
|
+
analytics_available? && Datadog::Contrib::Analytics.enabled?(options.fetch(:analytics_enabled, false))
|
66
80
|
end
|
67
81
|
|
68
82
|
def analytics_sample_rate
|
data/lib/graphql/version.rb
CHANGED
data/lib/graphql.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-12-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: racc
|
@@ -309,6 +309,7 @@ files:
|
|
309
309
|
- lib/graphql/backtrace/tracer.rb
|
310
310
|
- lib/graphql/coercion_error.rb
|
311
311
|
- lib/graphql/dataloader.rb
|
312
|
+
- lib/graphql/dataloader/async_dataloader.rb
|
312
313
|
- lib/graphql/dataloader/null_dataloader.rb
|
313
314
|
- lib/graphql/dataloader/request.rb
|
314
315
|
- lib/graphql/dataloader/request_all.rb
|
@@ -360,7 +361,6 @@ files:
|
|
360
361
|
- lib/graphql/language/lexer.rb
|
361
362
|
- lib/graphql/language/nodes.rb
|
362
363
|
- lib/graphql/language/parser.rb
|
363
|
-
- lib/graphql/language/parser.y
|
364
364
|
- lib/graphql/language/printer.rb
|
365
365
|
- lib/graphql/language/sanitized_printer.rb
|
366
366
|
- lib/graphql/language/static_visitor.rb
|
@@ -553,6 +553,8 @@ files:
|
|
553
553
|
- lib/graphql/subscriptions/event.rb
|
554
554
|
- lib/graphql/subscriptions/instrumentation.rb
|
555
555
|
- lib/graphql/subscriptions/serialize.rb
|
556
|
+
- lib/graphql/testing.rb
|
557
|
+
- lib/graphql/testing/helpers.rb
|
556
558
|
- lib/graphql/tracing.rb
|
557
559
|
- lib/graphql/tracing/active_support_notifications_trace.rb
|
558
560
|
- lib/graphql/tracing/active_support_notifications_tracing.rb
|
@@ -629,7 +631,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
629
631
|
- !ruby/object:Gem::Version
|
630
632
|
version: '0'
|
631
633
|
requirements: []
|
632
|
-
rubygems_version: 3.
|
634
|
+
rubygems_version: 3.4.10
|
633
635
|
signing_key:
|
634
636
|
specification_version: 4
|
635
637
|
summary: A GraphQL language and runtime for Ruby
|