graphql 2.0.30 → 2.1.0
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.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/graphql/execution/interpreter/runtime.rb +24 -22
- data/lib/graphql/language/document_from_schema_definition.rb +6 -16
- data/lib/graphql/language/nodes.rb +1 -1
- data/lib/graphql/language/printer.rb +233 -145
- data/lib/graphql/language/sanitized_printer.rb +14 -21
- data/lib/graphql/language/visitor.rb +18 -81
- data/lib/graphql/pagination/connection.rb +23 -1
- data/lib/graphql/query.rb +2 -19
- data/lib/graphql/rake_task.rb +3 -12
- data/lib/graphql/schema/field/scope_extension.rb +7 -1
- data/lib/graphql/schema/interface.rb +1 -5
- data/lib/graphql/schema/member/scoped.rb +19 -0
- data/lib/graphql/schema/object.rb +8 -0
- data/lib/graphql/schema/printer.rb +8 -7
- data/lib/graphql/schema/subscription.rb +11 -4
- data/lib/graphql/schema/warden.rb +3 -34
- data/lib/graphql/schema.rb +4 -20
- data/lib/graphql/static_validation/validation_context.rb +0 -3
- data/lib/graphql/static_validation.rb +0 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +2 -1
- data/lib/graphql/subscriptions.rb +11 -6
- data/lib/graphql/tracing/data_dog_trace.rb +34 -21
- data/lib/graphql/tracing/data_dog_tracing.rb +21 -7
- data/lib/graphql/types/relay/connection_behaviors.rb +19 -2
- data/lib/graphql/types/relay/edge_behaviors.rb +7 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +0 -1
- metadata +21 -37
- data/lib/graphql/filter.rb +0 -59
- data/lib/graphql/static_validation/type_stack.rb +0 -216
@@ -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
|
@@ -67,9 +67,8 @@ module GraphQL
|
|
67
67
|
type: [edge_type_class, null: edge_nullable],
|
68
68
|
null: edges_nullable,
|
69
69
|
description: "A list of edges.",
|
70
|
+
scope: false, # Assume that the connection was already scoped.
|
70
71
|
connection: false,
|
71
|
-
# Assume that the connection was scoped before this step:
|
72
|
-
scope: false,
|
73
72
|
}
|
74
73
|
|
75
74
|
if field_options
|
@@ -170,6 +169,24 @@ module GraphQL
|
|
170
169
|
obj_type.field :page_info, GraphQL::Types::Relay::PageInfo, null: false, description: "Information to aid in pagination."
|
171
170
|
end
|
172
171
|
end
|
172
|
+
|
173
|
+
def edges
|
174
|
+
# Assume that whatever authorization needed to happen
|
175
|
+
# already happened at the connection level.
|
176
|
+
current_runtime_state = Thread.current[:__graphql_runtime_info]
|
177
|
+
query_runtime_state = current_runtime_state[context.query]
|
178
|
+
query_runtime_state.was_authorized_by_scope_items = @object.was_authorized_by_scope_items?
|
179
|
+
@object.edges
|
180
|
+
end
|
181
|
+
|
182
|
+
def nodes
|
183
|
+
# Assume that whatever authorization needed to happen
|
184
|
+
# already happened at the connection level.
|
185
|
+
current_runtime_state = Thread.current[:__graphql_runtime_info]
|
186
|
+
query_runtime_state = current_runtime_state[context.query]
|
187
|
+
query_runtime_state.was_authorized_by_scope_items = @object.was_authorized_by_scope_items?
|
188
|
+
@object.nodes
|
189
|
+
end
|
173
190
|
end
|
174
191
|
end
|
175
192
|
end
|
@@ -12,6 +12,13 @@ module GraphQL
|
|
12
12
|
child_class.node_nullable(true)
|
13
13
|
end
|
14
14
|
|
15
|
+
def node
|
16
|
+
current_runtime_state = Thread.current[:__graphql_runtime_info]
|
17
|
+
query_runtime_state = current_runtime_state[context.query]
|
18
|
+
query_runtime_state.was_authorized_by_scope_items = @object.was_authorized_by_scope_items?
|
19
|
+
@object.node
|
20
|
+
end
|
21
|
+
|
15
22
|
module ClassMethods
|
16
23
|
def inherited(child_class)
|
17
24
|
super
|
data/lib/graphql/version.rb
CHANGED
data/lib/graphql.rb
CHANGED
@@ -103,7 +103,6 @@ require "graphql/schema"
|
|
103
103
|
require "graphql/query"
|
104
104
|
require "graphql/types"
|
105
105
|
require "graphql/dataloader"
|
106
|
-
require "graphql/filter"
|
107
106
|
require "graphql/static_validation"
|
108
107
|
require "graphql/execution"
|
109
108
|
require "graphql/schema/built_in_types"
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.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-08-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: base64
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: benchmark-ips
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,61 +53,61 @@ dependencies:
|
|
67
53
|
- !ruby/object:Gem::Version
|
68
54
|
version: '0'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
56
|
+
name: minitest
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
59
|
- - "~>"
|
74
60
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
61
|
+
version: 5.9.0
|
76
62
|
type: :development
|
77
63
|
prerelease: false
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
79
65
|
requirements:
|
80
66
|
- - "~>"
|
81
67
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
68
|
+
version: 5.9.0
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
|
-
name: minitest
|
70
|
+
name: minitest-focus
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
86
72
|
requirements:
|
87
|
-
- - "
|
73
|
+
- - "~>"
|
88
74
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
75
|
+
version: '1.1'
|
90
76
|
type: :development
|
91
77
|
prerelease: false
|
92
78
|
version_requirements: !ruby/object:Gem::Requirement
|
93
79
|
requirements:
|
94
|
-
- - "
|
80
|
+
- - "~>"
|
95
81
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
82
|
+
version: '1.1'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
|
-
name: minitest-
|
84
|
+
name: minitest-reporters
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
100
86
|
requirements:
|
101
|
-
- - "
|
87
|
+
- - "~>"
|
102
88
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
89
|
+
version: '1.0'
|
104
90
|
type: :development
|
105
91
|
prerelease: false
|
106
92
|
version_requirements: !ruby/object:Gem::Requirement
|
107
93
|
requirements:
|
108
|
-
- - "
|
94
|
+
- - "~>"
|
109
95
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
96
|
+
version: '1.0'
|
111
97
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
98
|
+
name: racc
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
114
100
|
requirements:
|
115
|
-
- - "
|
101
|
+
- - "~>"
|
116
102
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
103
|
+
version: '1.4'
|
118
104
|
type: :development
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
107
|
requirements:
|
122
|
-
- - "
|
108
|
+
- - "~>"
|
123
109
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
110
|
+
version: '1.4'
|
125
111
|
- !ruby/object:Gem::Dependency
|
126
112
|
name: rake
|
127
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -345,7 +331,6 @@ files:
|
|
345
331
|
- lib/graphql/execution/lookahead.rb
|
346
332
|
- lib/graphql/execution/multiplex.rb
|
347
333
|
- lib/graphql/execution_error.rb
|
348
|
-
- lib/graphql/filter.rb
|
349
334
|
- lib/graphql/integer_decoding_error.rb
|
350
335
|
- lib/graphql/integer_encoding_error.rb
|
351
336
|
- lib/graphql/introspection.rb
|
@@ -550,7 +535,6 @@ files:
|
|
550
535
|
- lib/graphql/static_validation/rules/variables_are_input_types_error.rb
|
551
536
|
- lib/graphql/static_validation/rules/variables_are_used_and_defined.rb
|
552
537
|
- lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb
|
553
|
-
- lib/graphql/static_validation/type_stack.rb
|
554
538
|
- lib/graphql/static_validation/validation_context.rb
|
555
539
|
- lib/graphql/static_validation/validation_timeout_error.rb
|
556
540
|
- lib/graphql/static_validation/validator.rb
|
@@ -637,7 +621,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
637
621
|
- !ruby/object:Gem::Version
|
638
622
|
version: '0'
|
639
623
|
requirements: []
|
640
|
-
rubygems_version: 3.
|
624
|
+
rubygems_version: 3.4.10
|
641
625
|
signing_key:
|
642
626
|
specification_version: 4
|
643
627
|
summary: A GraphQL language and runtime for Ruby
|
data/lib/graphql/filter.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require "graphql/deprecation"
|
3
|
-
|
4
|
-
module GraphQL
|
5
|
-
# @api private
|
6
|
-
class Filter
|
7
|
-
def initialize(only: nil, except: nil, silence_deprecation_warning: false)
|
8
|
-
if !silence_deprecation_warning
|
9
|
-
line = caller(2, 10).find { |l| !l.include?("lib/graphql") }
|
10
|
-
GraphQL::Deprecation.warn("GraphQL::Filter, `only:`, `except:`, and `.merge_filters` are deprecated and will be removed in v2.1.0. Implement `visible?` on your schema members instead (https://graphql-ruby.org/authorization/visibility.html).\n #{line}")
|
11
|
-
end
|
12
|
-
@only = only
|
13
|
-
@except = except
|
14
|
-
end
|
15
|
-
|
16
|
-
# Returns true if `member, ctx` passes this filter
|
17
|
-
def call(member, ctx)
|
18
|
-
(@only ? @only.call(member, ctx) : true) &&
|
19
|
-
(@except ? !@except.call(member, ctx) : true)
|
20
|
-
end
|
21
|
-
|
22
|
-
def merge(only: nil, except: nil)
|
23
|
-
onlies = [self].concat(Array(only))
|
24
|
-
merged_only = MergedOnly.build(onlies)
|
25
|
-
merged_except = MergedExcept.build(Array(except))
|
26
|
-
self.class.new(only: merged_only, except: merged_except, silence_deprecation_warning: true)
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
class MergedOnly
|
32
|
-
def initialize(first, second)
|
33
|
-
@first = first
|
34
|
-
@second = second
|
35
|
-
end
|
36
|
-
|
37
|
-
def call(member, ctx)
|
38
|
-
@first.call(member, ctx) && @second.call(member, ctx)
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.build(onlies)
|
42
|
-
case onlies.size
|
43
|
-
when 0
|
44
|
-
nil
|
45
|
-
when 1
|
46
|
-
onlies[0]
|
47
|
-
else
|
48
|
-
onlies.reduce { |memo, only| self.new(memo, only) }
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
class MergedExcept < MergedOnly
|
54
|
-
def call(member, ctx)
|
55
|
-
@first.call(member, ctx) || @second.call(member, ctx)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
@@ -1,216 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module GraphQL
|
3
|
-
module StaticValidation
|
4
|
-
# - Ride along with `GraphQL::Language::Visitor`
|
5
|
-
# - Track type info, expose it to validators
|
6
|
-
class TypeStack
|
7
|
-
# These are jumping-off points for infering types down the tree
|
8
|
-
TYPE_INFERRENCE_ROOTS = [
|
9
|
-
GraphQL::Language::Nodes::OperationDefinition,
|
10
|
-
GraphQL::Language::Nodes::FragmentDefinition,
|
11
|
-
]
|
12
|
-
|
13
|
-
# @return [GraphQL::Schema] the schema whose types are present in this document
|
14
|
-
attr_reader :schema
|
15
|
-
|
16
|
-
# When it enters an object (starting with query or mutation root), it's pushed on this stack.
|
17
|
-
# When it exits, it's popped off.
|
18
|
-
# @return [Array<GraphQL::ObjectType, GraphQL::Union, GraphQL::Interface>]
|
19
|
-
attr_reader :object_types
|
20
|
-
|
21
|
-
# When it enters a field, it's pushed on this stack (useful for nested fields, args).
|
22
|
-
# When it exits, it's popped off.
|
23
|
-
# @return [Array<GraphQL::Field>] fields which have been entered
|
24
|
-
attr_reader :field_definitions
|
25
|
-
|
26
|
-
# Directives are pushed on, then popped off while traversing the tree
|
27
|
-
# @return [Array<GraphQL::Node::Directive>] directives which have been entered
|
28
|
-
attr_reader :directive_definitions
|
29
|
-
|
30
|
-
# @return [Array<GraphQL::Node::Argument>] arguments which have been entered
|
31
|
-
attr_reader :argument_definitions
|
32
|
-
|
33
|
-
# @return [Array<String>] fields which have been entered (by their AST name)
|
34
|
-
attr_reader :path
|
35
|
-
|
36
|
-
# @param schema [GraphQL::Schema] the schema whose types to use when climbing this document
|
37
|
-
# @param visitor [GraphQL::Language::Visitor] a visitor to follow & watch the types
|
38
|
-
def initialize(schema, visitor)
|
39
|
-
@schema = schema
|
40
|
-
@object_types = []
|
41
|
-
@field_definitions = []
|
42
|
-
@directive_definitions = []
|
43
|
-
@argument_definitions = []
|
44
|
-
@path = []
|
45
|
-
|
46
|
-
PUSH_STRATEGIES.each do |node_class, strategy|
|
47
|
-
visitor[node_class].enter << EnterWithStrategy.new(self, strategy)
|
48
|
-
visitor[node_class].leave << LeaveWithStrategy.new(self, strategy)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
|
55
|
-
module FragmentWithTypeStrategy
|
56
|
-
def push(stack, node)
|
57
|
-
object_type = if node.type
|
58
|
-
stack.schema.get_type(node.type.name)
|
59
|
-
else
|
60
|
-
stack.object_types.last
|
61
|
-
end
|
62
|
-
if !object_type.nil?
|
63
|
-
object_type = object_type.unwrap
|
64
|
-
end
|
65
|
-
stack.object_types.push(object_type)
|
66
|
-
push_path_member(stack, node)
|
67
|
-
end
|
68
|
-
|
69
|
-
def pop(stack, node)
|
70
|
-
stack.object_types.pop
|
71
|
-
stack.path.pop
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
module FragmentDefinitionStrategy
|
76
|
-
extend FragmentWithTypeStrategy
|
77
|
-
module_function
|
78
|
-
def push_path_member(stack, node)
|
79
|
-
stack.path.push("fragment #{node.name}")
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
module InlineFragmentStrategy
|
84
|
-
extend FragmentWithTypeStrategy
|
85
|
-
module_function
|
86
|
-
def push_path_member(stack, node)
|
87
|
-
stack.path.push("...#{node.type ? " on #{node.type.to_query_string}" : ""}")
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
module OperationDefinitionStrategy
|
92
|
-
module_function
|
93
|
-
def push(stack, node)
|
94
|
-
# eg, QueryType, MutationType
|
95
|
-
object_type = stack.schema.root_type_for_operation(node.operation_type)
|
96
|
-
stack.object_types.push(object_type)
|
97
|
-
stack.path.push("#{node.operation_type}#{node.name ? " #{node.name}" : ""}")
|
98
|
-
end
|
99
|
-
|
100
|
-
def pop(stack, node)
|
101
|
-
stack.object_types.pop
|
102
|
-
stack.path.pop
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
module FieldStrategy
|
107
|
-
module_function
|
108
|
-
def push(stack, node)
|
109
|
-
parent_type = stack.object_types.last
|
110
|
-
parent_type = parent_type.unwrap
|
111
|
-
|
112
|
-
field_definition = stack.schema.get_field(parent_type, node.name)
|
113
|
-
stack.field_definitions.push(field_definition)
|
114
|
-
if !field_definition.nil?
|
115
|
-
next_object_type = field_definition.type
|
116
|
-
stack.object_types.push(next_object_type)
|
117
|
-
else
|
118
|
-
stack.object_types.push(nil)
|
119
|
-
end
|
120
|
-
stack.path.push(node.alias || node.name)
|
121
|
-
end
|
122
|
-
|
123
|
-
def pop(stack, node)
|
124
|
-
stack.field_definitions.pop
|
125
|
-
stack.object_types.pop
|
126
|
-
stack.path.pop
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
module DirectiveStrategy
|
131
|
-
module_function
|
132
|
-
def push(stack, node)
|
133
|
-
directive_defn = stack.schema.directives[node.name]
|
134
|
-
stack.directive_definitions.push(directive_defn)
|
135
|
-
end
|
136
|
-
|
137
|
-
def pop(stack, node)
|
138
|
-
stack.directive_definitions.pop
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
module ArgumentStrategy
|
143
|
-
module_function
|
144
|
-
# Push `argument_defn` onto the stack.
|
145
|
-
# It's possible that `argument_defn` will be nil.
|
146
|
-
# Push it anyways so `pop` has something to pop.
|
147
|
-
def push(stack, node)
|
148
|
-
if stack.argument_definitions.last
|
149
|
-
arg_type = stack.argument_definitions.last.type.unwrap
|
150
|
-
if arg_type.kind.input_object?
|
151
|
-
argument_defn = arg_type.arguments[node.name]
|
152
|
-
else
|
153
|
-
argument_defn = nil
|
154
|
-
end
|
155
|
-
elsif stack.directive_definitions.last
|
156
|
-
argument_defn = stack.directive_definitions.last.arguments[node.name]
|
157
|
-
elsif stack.field_definitions.last
|
158
|
-
argument_defn = stack.field_definitions.last.arguments[node.name]
|
159
|
-
else
|
160
|
-
argument_defn = nil
|
161
|
-
end
|
162
|
-
stack.argument_definitions.push(argument_defn)
|
163
|
-
stack.path.push(node.name)
|
164
|
-
end
|
165
|
-
|
166
|
-
def pop(stack, node)
|
167
|
-
stack.argument_definitions.pop
|
168
|
-
stack.path.pop
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
module FragmentSpreadStrategy
|
173
|
-
module_function
|
174
|
-
def push(stack, node)
|
175
|
-
stack.path.push("... #{node.name}")
|
176
|
-
end
|
177
|
-
|
178
|
-
def pop(stack, node)
|
179
|
-
stack.path.pop
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
PUSH_STRATEGIES = {
|
184
|
-
GraphQL::Language::Nodes::FragmentDefinition => FragmentDefinitionStrategy,
|
185
|
-
GraphQL::Language::Nodes::InlineFragment => InlineFragmentStrategy,
|
186
|
-
GraphQL::Language::Nodes::FragmentSpread => FragmentSpreadStrategy,
|
187
|
-
GraphQL::Language::Nodes::Argument => ArgumentStrategy,
|
188
|
-
GraphQL::Language::Nodes::Field => FieldStrategy,
|
189
|
-
GraphQL::Language::Nodes::Directive => DirectiveStrategy,
|
190
|
-
GraphQL::Language::Nodes::OperationDefinition => OperationDefinitionStrategy,
|
191
|
-
}
|
192
|
-
|
193
|
-
class EnterWithStrategy
|
194
|
-
def initialize(stack, strategy)
|
195
|
-
@stack = stack
|
196
|
-
@strategy = strategy
|
197
|
-
end
|
198
|
-
|
199
|
-
def call(node, parent)
|
200
|
-
@strategy.push(@stack, node)
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
class LeaveWithStrategy
|
205
|
-
def initialize(stack, strategy)
|
206
|
-
@stack = stack
|
207
|
-
@strategy = strategy
|
208
|
-
end
|
209
|
-
|
210
|
-
def call(node, parent)
|
211
|
-
@strategy.pop(@stack, node)
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|