graphql 1.9.0.pre3 → 1.9.0.pre4
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 +5 -0
- data/lib/graphql/execution/interpreter/hash_response.rb +1 -1
- data/lib/graphql/execution/interpreter/resolve.rb +2 -0
- data/lib/graphql/execution/interpreter/runtime.rb +11 -2
- data/lib/graphql/execution/lookahead.rb +1 -1
- data/lib/graphql/internal_representation/rewrite.rb +5 -5
- data/lib/graphql/language/parser.rb +1 -1
- data/lib/graphql/language/parser.y +1 -1
- data/lib/graphql/language/printer.rb +1 -1
- data/lib/graphql/language/visitor.rb +1 -1
- data/lib/graphql/query.rb +1 -1
- data/lib/graphql/query/arguments.rb +1 -1
- data/lib/graphql/query/arguments_cache.rb +1 -1
- data/lib/graphql/query/validation_pipeline.rb +3 -3
- data/lib/graphql/schema.rb +1 -1
- data/lib/graphql/schema/field.rb +25 -11
- data/lib/graphql/schema/field/connection_extension.rb +1 -1
- data/lib/graphql/schema/field_extension.rb +11 -3
- data/lib/graphql/schema/mutation.rb +1 -1
- data/lib/graphql/static_validation/base_visitor.rb +1 -1
- data/lib/graphql/static_validation/definition_dependencies.rb +3 -3
- data/lib/graphql/static_validation/literal_validator.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +1 -1
- data/lib/graphql/static_validation/validator.rb +1 -1
- data/lib/graphql/types/relay/node_field.rb +15 -0
- data/lib/graphql/types/relay/nodes_field.rb +17 -1
- data/lib/graphql/version.rb +1 -1
- data/spec/graphql/analysis/ast_spec.rb +12 -0
- data/spec/graphql/execution/interpreter_spec.rb +83 -0
- data/spec/graphql/schema/field_extension_spec.rb +26 -4
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +3 -3
- data/spec/integration/rails/graphql/relay/mutation_spec.rb +48 -0
- data/spec/integration/tmp/app/graphql/types/family_type.rb +9 -0
- metadata +4 -98
- data/spec/integration/tmp/app/graphql/types/bird_type.rb +0 -7
- data/spec/integration/tmp/dummy/Gemfile +0 -45
- data/spec/integration/tmp/dummy/README.rdoc +0 -28
- data/spec/integration/tmp/dummy/Rakefile +0 -6
- data/spec/integration/tmp/dummy/app/assets/javascripts/application.js +0 -16
- data/spec/integration/tmp/dummy/app/assets/stylesheets/application.css +0 -15
- data/spec/integration/tmp/dummy/app/controllers/application_controller.rb +0 -5
- data/spec/integration/tmp/dummy/app/controllers/graphql_controller.rb +0 -43
- data/spec/integration/tmp/dummy/app/graphql/dummy_schema.rb +0 -34
- data/spec/integration/tmp/dummy/app/graphql/types/base_enum.rb +0 -4
- data/spec/integration/tmp/dummy/app/graphql/types/base_input_object.rb +0 -4
- data/spec/integration/tmp/dummy/app/graphql/types/base_interface.rb +0 -5
- data/spec/integration/tmp/dummy/app/graphql/types/base_object.rb +0 -4
- data/spec/integration/tmp/dummy/app/graphql/types/base_scalar.rb +0 -4
- data/spec/integration/tmp/dummy/app/graphql/types/base_union.rb +0 -4
- data/spec/integration/tmp/dummy/app/graphql/types/mutation_type.rb +0 -10
- data/spec/integration/tmp/dummy/app/graphql/types/query_type.rb +0 -15
- data/spec/integration/tmp/dummy/app/helpers/application_helper.rb +0 -2
- data/spec/integration/tmp/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/integration/tmp/dummy/bin/bundle +0 -3
- data/spec/integration/tmp/dummy/bin/rails +0 -4
- data/spec/integration/tmp/dummy/bin/rake +0 -4
- data/spec/integration/tmp/dummy/bin/setup +0 -29
- data/spec/integration/tmp/dummy/config.ru +0 -4
- data/spec/integration/tmp/dummy/config/application.rb +0 -32
- data/spec/integration/tmp/dummy/config/boot.rb +0 -3
- data/spec/integration/tmp/dummy/config/environment.rb +0 -5
- data/spec/integration/tmp/dummy/config/environments/development.rb +0 -38
- data/spec/integration/tmp/dummy/config/environments/production.rb +0 -76
- data/spec/integration/tmp/dummy/config/environments/test.rb +0 -42
- data/spec/integration/tmp/dummy/config/initializers/assets.rb +0 -11
- data/spec/integration/tmp/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/integration/tmp/dummy/config/initializers/cookies_serializer.rb +0 -3
- data/spec/integration/tmp/dummy/config/initializers/filter_parameter_logging.rb +0 -4
- data/spec/integration/tmp/dummy/config/initializers/inflections.rb +0 -16
- data/spec/integration/tmp/dummy/config/initializers/mime_types.rb +0 -4
- data/spec/integration/tmp/dummy/config/initializers/session_store.rb +0 -3
- data/spec/integration/tmp/dummy/config/initializers/to_time_preserves_timezone.rb +0 -10
- data/spec/integration/tmp/dummy/config/initializers/wrap_parameters.rb +0 -9
- data/spec/integration/tmp/dummy/config/locales/en.yml +0 -23
- data/spec/integration/tmp/dummy/config/routes.rb +0 -61
- data/spec/integration/tmp/dummy/config/secrets.yml +0 -22
- data/spec/integration/tmp/dummy/db/seeds.rb +0 -7
- data/spec/integration/tmp/dummy/public/404.html +0 -67
- data/spec/integration/tmp/dummy/public/422.html +0 -67
- data/spec/integration/tmp/dummy/public/500.html +0 -66
- data/spec/integration/tmp/dummy/public/favicon.ico +0 -0
- data/spec/integration/tmp/dummy/public/robots.txt +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e4a203b440499962202563a6c4c834e14881c5c
|
4
|
+
data.tar.gz: 76c0395eb02e5bea7652869c9c665df092cd54ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b689670d32855deefb65dacf51f1ea3e37123e5934b2eb8ca43070ad3ee562405f99ce3c420faee173fa77badde9c11089975238c0de1782a5692ebab1319808
|
7
|
+
data.tar.gz: 3b48af200dccfdd63783f980e8c808f52823c46bb711d1b7f2c63867ae819e1e458e0dc796034ab703d002bac33723a30816b1e2ad17d6536709523b8f07fd03
|
@@ -32,6 +32,11 @@ module GraphQL
|
|
32
32
|
# @return [Array<GraphQL::ObjectType>] Types whose scope we've entered
|
33
33
|
attr_reader :object_types
|
34
34
|
|
35
|
+
def visit
|
36
|
+
return unless @document
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
35
40
|
# Visit Helpers
|
36
41
|
|
37
42
|
# @return [GraphQL::Query::Arguments] Arguments for this node, merging default values, literal values and query variables
|
@@ -192,18 +192,27 @@ module GraphQL
|
|
192
192
|
field_ast_nodes.each { |f| next_selections.concat(f.selections) }
|
193
193
|
end
|
194
194
|
|
195
|
-
resolve_with_directives(object, ast_node) do
|
195
|
+
field_result = resolve_with_directives(object, ast_node) do
|
196
196
|
# Actually call the field resolver and capture the result
|
197
197
|
app_result = query.trace("execute_field", {field: field_defn, path: next_path}) do
|
198
198
|
field_defn.resolve(object, kwarg_arguments, context)
|
199
199
|
end
|
200
|
-
after_lazy(app_result, field: field_defn, path: next_path
|
200
|
+
after_lazy(app_result, field: field_defn, path: next_path) do |inner_result|
|
201
201
|
continue_value = continue_value(next_path, inner_result, field_defn, return_type.non_null?, ast_node)
|
202
202
|
if HALT != continue_value
|
203
203
|
continue_field(next_path, continue_value, field_defn, return_type, ast_node, next_selections, false)
|
204
204
|
end
|
205
205
|
end
|
206
206
|
end
|
207
|
+
|
208
|
+
# If this field is a root mutation field, immediately resolve
|
209
|
+
# all of its child fields before moving on to the next root mutation field.
|
210
|
+
# (Subselections of this mutation will still be resolved level-by-level.)
|
211
|
+
if root_operation_type == "mutation"
|
212
|
+
Interpreter::Resolve.resolve_all([field_result])
|
213
|
+
else
|
214
|
+
field_result
|
215
|
+
end
|
207
216
|
end
|
208
217
|
end
|
209
218
|
|
@@ -102,13 +102,13 @@ module GraphQL
|
|
102
102
|
@rewrite_skip_nodes.add(node)
|
103
103
|
end
|
104
104
|
|
105
|
-
if @rewrite_skip_nodes.
|
105
|
+
if @rewrite_skip_nodes.empty?
|
106
106
|
@rewrite_scopes_stack.push(@rewrite_scopes_stack.last.enter(context.type_definition))
|
107
107
|
end
|
108
108
|
|
109
109
|
super
|
110
110
|
|
111
|
-
if @rewrite_skip_nodes.
|
111
|
+
if @rewrite_skip_nodes.empty?
|
112
112
|
@rewrite_scopes_stack.pop
|
113
113
|
end
|
114
114
|
|
@@ -122,7 +122,7 @@ module GraphQL
|
|
122
122
|
@rewrite_skip_nodes.add(ast_node)
|
123
123
|
end
|
124
124
|
|
125
|
-
if @rewrite_skip_nodes.
|
125
|
+
if @rewrite_skip_nodes.empty?
|
126
126
|
node_name = ast_node.alias || ast_node.name
|
127
127
|
parent_nodes = @rewrite_nodes_stack.last
|
128
128
|
next_nodes = []
|
@@ -156,7 +156,7 @@ module GraphQL
|
|
156
156
|
|
157
157
|
super
|
158
158
|
|
159
|
-
if @rewrite_skip_nodes.
|
159
|
+
if @rewrite_skip_nodes.empty?
|
160
160
|
@rewrite_nodes_stack.pop
|
161
161
|
@rewrite_scopes_stack.pop
|
162
162
|
end
|
@@ -167,7 +167,7 @@ module GraphQL
|
|
167
167
|
end
|
168
168
|
|
169
169
|
def on_fragment_spread(ast_node, ast_parent)
|
170
|
-
if @rewrite_skip_nodes.
|
170
|
+
if @rewrite_skip_nodes.empty? && !skip?(ast_node)
|
171
171
|
# Register the irep nodes that depend on this AST node:
|
172
172
|
@rewrite_spread_parents[ast_node].merge(@rewrite_nodes_stack.last)
|
173
173
|
@rewrite_spread_scopes[ast_node] = @rewrite_scopes_stack.last
|
@@ -135,7 +135,7 @@ module GraphQL
|
|
135
135
|
if (schema.query.nil? || schema.query == 'Query') &&
|
136
136
|
(schema.mutation.nil? || schema.mutation == 'Mutation') &&
|
137
137
|
(schema.subscription.nil? || schema.subscription == 'Subscription') &&
|
138
|
-
(schema.directives.
|
138
|
+
(schema.directives.empty?)
|
139
139
|
return
|
140
140
|
end
|
141
141
|
|
@@ -96,7 +96,7 @@ module GraphQL
|
|
96
96
|
else
|
97
97
|
# Run hooks if there are any
|
98
98
|
new_node = node
|
99
|
-
begin_hooks_ok = @visitors.
|
99
|
+
begin_hooks_ok = @visitors.empty? || begin_visit(new_node, parent)
|
100
100
|
if begin_hooks_ok
|
101
101
|
node.children.each do |child_node|
|
102
102
|
new_child_and_node = on_node_with_modifications(child_node, new_node)
|
data/lib/graphql/query.rb
CHANGED
@@ -8,7 +8,7 @@ module GraphQL
|
|
8
8
|
Hash.new do |h1, irep_or_ast_node|
|
9
9
|
h1[irep_or_ast_node] = Hash.new do |h2, definition|
|
10
10
|
ast_node = irep_or_ast_node.is_a?(GraphQL::InternalRepresentation::Node) ? irep_or_ast_node.ast_node : irep_or_ast_node
|
11
|
-
h2[definition] = if definition.arguments.
|
11
|
+
h2[definition] = if definition.arguments.empty?
|
12
12
|
GraphQL::Query::Arguments::NO_ARGS
|
13
13
|
else
|
14
14
|
GraphQL::Query::LiteralInput.from_arguments(
|
@@ -76,11 +76,11 @@ module GraphQL
|
|
76
76
|
@validation_errors.concat(validation_result[:errors])
|
77
77
|
@internal_representation = validation_result[:irep]
|
78
78
|
|
79
|
-
if @validation_errors.
|
79
|
+
if @validation_errors.empty?
|
80
80
|
@validation_errors.concat(@query.variables.errors)
|
81
81
|
end
|
82
82
|
|
83
|
-
if @validation_errors.
|
83
|
+
if @validation_errors.empty?
|
84
84
|
@query_analyzers = build_analyzers(
|
85
85
|
@schema,
|
86
86
|
@max_depth,
|
@@ -89,7 +89,7 @@ module GraphQL
|
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
|
-
@valid = @validation_errors.
|
92
|
+
@valid = @validation_errors.empty?
|
93
93
|
end
|
94
94
|
|
95
95
|
# If there are max_* values, add them,
|
data/lib/graphql/schema.rb
CHANGED
data/lib/graphql/schema/field.rb
CHANGED
@@ -63,6 +63,16 @@ module GraphQL
|
|
63
63
|
# @return [GraphQL::Schema:Field] an instance of `self
|
64
64
|
# @see {.initialize} for other options
|
65
65
|
def self.from_options(name = nil, type = nil, desc = nil, resolver: nil, mutation: nil, subscription: nil,**kwargs, &block)
|
66
|
+
if kwargs[:field]
|
67
|
+
if kwargs[:field] == GraphQL::Relay::Node.field
|
68
|
+
warn("Legacy-style `GraphQL::Relay::Node.field` is being added to a class-based type. See `GraphQL::Types::Relay::NodeField` for a replacement.")
|
69
|
+
return GraphQL::Types::Relay::NodeField
|
70
|
+
elsif kwargs[:field] == GraphQL::Relay::Node.plural_field
|
71
|
+
warn("Legacy-style `GraphQL::Relay::Node.plural_field` is being added to a class-based type. See `GraphQL::Types::Relay::NodesField` for a replacement.")
|
72
|
+
return GraphQL::Types::Relay::NodesField
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
66
76
|
if (parent_config = resolver || mutation || subscription)
|
67
77
|
# Get the parent config, merge in local overrides
|
68
78
|
kwargs = parent_config.field_options.merge(kwargs)
|
@@ -602,7 +612,7 @@ MSG
|
|
602
612
|
# Written iteratively to avoid big stack traces.
|
603
613
|
# @return [Object] Whatever the
|
604
614
|
def with_extensions(obj, args, ctx)
|
605
|
-
if @extensions.
|
615
|
+
if @extensions.empty?
|
606
616
|
yield(obj, args)
|
607
617
|
else
|
608
618
|
# Save these so that the originals can be re-given to `after_resolve` handlers.
|
@@ -610,17 +620,9 @@ MSG
|
|
610
620
|
original_obj = obj
|
611
621
|
|
612
622
|
memos = []
|
613
|
-
|
614
|
-
|
615
|
-
# update this scope with the yielded value
|
616
|
-
obj = extended_obj
|
617
|
-
args = extended_args
|
618
|
-
# record the memo (or nil if none was yielded)
|
619
|
-
memos << memo
|
620
|
-
end
|
623
|
+
value = run_extensions_before_resolve(memos, obj, args, ctx) do |extended_obj, extended_args|
|
624
|
+
yield(extended_obj, extended_args)
|
621
625
|
end
|
622
|
-
# Call the block which actually calls resolve
|
623
|
-
value = yield(obj, args)
|
624
626
|
|
625
627
|
ctx.schema.after_lazy(value) do |resolved_value|
|
626
628
|
@extensions.each_with_index do |ext, idx|
|
@@ -632,6 +634,18 @@ MSG
|
|
632
634
|
end
|
633
635
|
end
|
634
636
|
end
|
637
|
+
|
638
|
+
def run_extensions_before_resolve(memos, obj, args, ctx, idx: 0)
|
639
|
+
extension = @extensions[idx]
|
640
|
+
if extension
|
641
|
+
extension.resolve(object: obj, arguments: args, context: ctx) do |extended_obj, extended_args, memo|
|
642
|
+
memos << memo
|
643
|
+
run_extensions_before_resolve(memos, extended_obj, extended_args, ctx, idx: idx + 1) { |o, a| yield(o, a) }
|
644
|
+
end
|
645
|
+
else
|
646
|
+
yield(obj, args)
|
647
|
+
end
|
648
|
+
end
|
635
649
|
end
|
636
650
|
end
|
637
651
|
end
|
@@ -12,7 +12,7 @@ module GraphQL
|
|
12
12
|
end
|
13
13
|
|
14
14
|
# Remove pagination args before passing it to a user method
|
15
|
-
def
|
15
|
+
def resolve(object:, arguments:, context:)
|
16
16
|
next_args = arguments.dup
|
17
17
|
next_args.delete(:first)
|
18
18
|
next_args.delete(:last)
|
@@ -33,25 +33,33 @@ module GraphQL
|
|
33
33
|
end
|
34
34
|
|
35
35
|
# Called before resolving {#field}. It should either:
|
36
|
+
#
|
36
37
|
# - `yield` values to continue execution; OR
|
37
38
|
# - return something else to shortcut field execution.
|
39
|
+
#
|
40
|
+
# Whatever this method returns will be used for execution.
|
41
|
+
#
|
38
42
|
# @param object [Object] The object the field is being resolved on
|
39
43
|
# @param arguments [Hash] Ruby keyword arguments for resolving this field
|
40
44
|
# @param context [Query::Context] the context for this query
|
41
45
|
# @yieldparam object [Object] The object to continue resolving the field on
|
42
46
|
# @yieldparam arguments [Hash] The keyword arguments to continue resolving with
|
43
47
|
# @yieldparam memo [Object] Any extension-specific value which will be passed to {#after_resolve} later
|
44
|
-
|
48
|
+
# @return [Object] The return value for this field.
|
49
|
+
def resolve(object:, arguments:, context:)
|
45
50
|
yield(object, arguments, nil)
|
46
51
|
end
|
47
52
|
|
48
|
-
# Called after {#field} was resolved,
|
53
|
+
# Called after {#field} was resolved, and after any lazy values (like `Promise`s) were synced,
|
54
|
+
# but before the value was added to the GraphQL response.
|
55
|
+
#
|
49
56
|
# Whatever this hook returns will be used as the return value.
|
57
|
+
#
|
50
58
|
# @param object [Object] The object the field is being resolved on
|
51
59
|
# @param arguments [Hash] Ruby keyword arguments for resolving this field
|
52
60
|
# @param context [Query::Context] the context for this query
|
53
61
|
# @param value [Object] Whatever the field previously returned
|
54
|
-
# @param memo [Object] The third value yielded by {#
|
62
|
+
# @param memo [Object] The third value yielded by {#resolve}, or `nil` if there wasn't one
|
55
63
|
# @return [Object] The return value for this field.
|
56
64
|
def after_resolve(object:, arguments:, context:, value:, memo:)
|
57
65
|
value
|
@@ -65,7 +65,7 @@ module GraphQL
|
|
65
65
|
class << self
|
66
66
|
# Override this method to handle legacy-style usages of `MyMutation.field`
|
67
67
|
def field(*args, &block)
|
68
|
-
if args.
|
68
|
+
if args.empty?
|
69
69
|
raise ArgumentError, "#{name}.field is used for adding fields to this mutation. Use `mutation: #{name}` to attach this mutation instead."
|
70
70
|
else
|
71
71
|
super
|
@@ -35,7 +35,7 @@ module GraphQL
|
|
35
35
|
# @param rewrite [Boolean] if `false`, don't include rewrite
|
36
36
|
# @return [Class] A class for validating `rules` during visitation
|
37
37
|
def self.including_rules(rules, rewrite: true)
|
38
|
-
if rules.
|
38
|
+
if rules.empty?
|
39
39
|
if rewrite
|
40
40
|
NoValidateVisitor
|
41
41
|
else
|
@@ -134,7 +134,7 @@ module GraphQL
|
|
134
134
|
# That way, we can use the remainder to identify cycles
|
135
135
|
@defdep_immediate_dependencies.delete(fragment_node)
|
136
136
|
fragment_usages = @defdep_dependent_definitions[fragment_node]
|
137
|
-
if fragment_usages.
|
137
|
+
if fragment_usages.empty?
|
138
138
|
# If we didn't record any usages during the visit,
|
139
139
|
# then this fragment is unused.
|
140
140
|
dependency_map.unused_dependencies << @defdep_node_paths[fragment_node]
|
@@ -151,7 +151,7 @@ module GraphQL
|
|
151
151
|
if block_given?
|
152
152
|
yield(definition_node, removed, fragment_node)
|
153
153
|
end
|
154
|
-
if remaining.
|
154
|
+
if remaining.empty? && definition_node.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
|
155
155
|
# If all of this definition's dependencies have
|
156
156
|
# been resolved, we can now resolve its
|
157
157
|
# own dependents.
|
@@ -171,7 +171,7 @@ module GraphQL
|
|
171
171
|
deps.delete(spread)
|
172
172
|
end
|
173
173
|
end
|
174
|
-
if deps.
|
174
|
+
if deps.empty?
|
175
175
|
@defdep_immediate_dependencies.delete(defn_node)
|
176
176
|
end
|
177
177
|
end
|
@@ -87,7 +87,7 @@ module GraphQL
|
|
87
87
|
present_field_names = ast_node.arguments.map(&:name)
|
88
88
|
missing_required_field_names = required_field_names - present_field_names
|
89
89
|
if @context.schema.error_bubbling
|
90
|
-
missing_required_field_names.
|
90
|
+
missing_required_field_names.empty?
|
91
91
|
else
|
92
92
|
missing_required_field_names.all? do |name|
|
93
93
|
validate(GraphQL::Language::Nodes::NullValue.new(name: name), @warden.arguments(type).find { |f| f.name == name }.type )
|
@@ -43,7 +43,7 @@ module GraphQL
|
|
43
43
|
# the same as the node we were checking here.
|
44
44
|
matched = if arg_defn.type.kind.list?
|
45
45
|
# for a list we claim an error if the node is contained in our list
|
46
|
-
node.value.include?(err.ast_value)
|
46
|
+
Array(node.value).include?(err.ast_value)
|
47
47
|
elsif arg_defn.type.kind.input_object? && node.value.is_a?(GraphQL::Language::Nodes::InputObject)
|
48
48
|
# for an input object we check the arguments
|
49
49
|
node.value.arguments.include?(err.ast_value)
|
@@ -31,7 +31,7 @@ module GraphQL
|
|
31
31
|
else
|
32
32
|
"Selections can't be made on scalars (%{node_name} returns #{resolved_type.name} but has selections [#{ast_node.selections.map(&:name).join(", ")}])"
|
33
33
|
end
|
34
|
-
elsif resolved_type.kind.fields? && ast_node.selections.
|
34
|
+
elsif resolved_type.kind.fields? && ast_node.selections.empty?
|
35
35
|
"Field must have selections (%{node_name} returns #{resolved_type.name} but has no selections. Did you mean '#{ast_node.name} { ... }'?)"
|
36
36
|
else
|
37
37
|
nil
|
@@ -300,7 +300,7 @@ module GraphQL
|
|
300
300
|
NO_SELECTIONS = [{}.freeze, [].freeze].freeze
|
301
301
|
|
302
302
|
def fields_and_fragments_from_selection(node, owner_type:, parents:)
|
303
|
-
if node.selections.
|
303
|
+
if node.selections.empty?
|
304
304
|
NO_SELECTIONS
|
305
305
|
else
|
306
306
|
fields, fragment_spreads = find_fields_and_fragments(node.selections, owner_type: owner_type, parents: parents, fields: [], fragment_spreads: [])
|