graphql 2.0.28 → 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.
- checksums.yaml +4 -4
- data/lib/graphql/execution/interpreter/runtime.rb +23 -21
- 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/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 +3 -5
- 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,14 +1,14 @@
|
|
|
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
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: benchmark-ips
|
|
@@ -331,7 +331,6 @@ files:
|
|
|
331
331
|
- lib/graphql/execution/lookahead.rb
|
|
332
332
|
- lib/graphql/execution/multiplex.rb
|
|
333
333
|
- lib/graphql/execution_error.rb
|
|
334
|
-
- lib/graphql/filter.rb
|
|
335
334
|
- lib/graphql/integer_decoding_error.rb
|
|
336
335
|
- lib/graphql/integer_encoding_error.rb
|
|
337
336
|
- lib/graphql/introspection.rb
|
|
@@ -536,7 +535,6 @@ files:
|
|
|
536
535
|
- lib/graphql/static_validation/rules/variables_are_input_types_error.rb
|
|
537
536
|
- lib/graphql/static_validation/rules/variables_are_used_and_defined.rb
|
|
538
537
|
- lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb
|
|
539
|
-
- lib/graphql/static_validation/type_stack.rb
|
|
540
538
|
- lib/graphql/static_validation/validation_context.rb
|
|
541
539
|
- lib/graphql/static_validation/validation_timeout_error.rb
|
|
542
540
|
- lib/graphql/static_validation/validator.rb
|
|
@@ -623,7 +621,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
623
621
|
- !ruby/object:Gem::Version
|
|
624
622
|
version: '0'
|
|
625
623
|
requirements: []
|
|
626
|
-
rubygems_version: 3.
|
|
624
|
+
rubygems_version: 3.4.10
|
|
627
625
|
signing_key:
|
|
628
626
|
specification_version: 4
|
|
629
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
|