File: field_selection.rb

package info (click to toggle)
gitlab 17.6.5-19
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 629,368 kB
  • sloc: ruby: 1,915,304; javascript: 557,307; sql: 60,639; xml: 6,509; sh: 4,567; makefile: 1,239; python: 406
file content (69 lines) | stat: -rw-r--r-- 1,630 bytes parent folder | download
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
# 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, 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 inspected.nested_fields?
          subselection = select_fields(singular_field_type, skip, max_depth - 1)
          next [] if subselection.empty?

          [[name, subselection.to_h]]
        else
          [[name, nil]]
        end
      end)
    end
  end
end