1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
# frozen_string_literal: true
module Graphql
class FieldSelection
delegate :empty?, :blank?, :to_h, to: :selection
delegate :size, to: :paths
attr_reader :selection
def initialize(selection = {})
@selection = selection.to_h
end
def to_s
serialize_field_selection(selection)
end
def paths
selection.flat_map do |field, subselection|
paths_in([field], subselection)
end
end
private
def paths_in(path, leaves)
return [path] if leaves.nil?
leaves.to_a.flat_map do |k, v|
paths_in([k], v).map { |tail| path + tail }
end
end
def serialize_field_selection(hash, level = 0)
indent = ' ' * level
hash.map do |field, subselection|
if subselection.nil?
"#{indent}#{field}"
else
subfields = serialize_field_selection(subselection, level + 1)
"#{indent}#{field} {\n#{subfields}\n#{indent}}"
end
end.join("\n")
end
NO_SKIP = ->(_name, _field) { false }
def self.select_fields(type, skip = NO_SKIP, parent_types = Set.new, max_depth = 3)
return new if max_depth <= 0 || !type.kind.fields?
new(type.fields.flat_map do |name, field|
next [] if skip[name, field]
inspected = ::Graphql::FieldInspection.new(field)
singular_field_type = inspected.type
# If field type is the same as parent type, then we're hitting into
# mutual dependency. Break it from infinite recursion
next [] if parent_types.include?(singular_field_type)
if inspected.nested_fields?
subselection = select_fields(singular_field_type, skip, parent_types | [type], max_depth - 1)
next [] if subselection.empty?
[[name, subselection.to_h]]
else
[[name, nil]]
end
end)
end
end
end
|