Module: Relay::Connection

Defined in:
lib/relay/connection/array.rb,
lib/relay/connection/connection.rb

Defined Under Namespace

Classes: ArrayConnection, ConnectionConfiguration, Edge, PageInfo

Constant Summary collapse

ARRAY_CONNECTION_PREFIX =
'arrayconnection'
EmptyConnection =
ArrayConnection.new([], PageInfo.new(nil, nil, false, false))
ConnectionArguments =
[
  GraphQL::GraphQLArgument.new(:before, GraphQL::GraphQLString),
  GraphQL::GraphQLArgument.new(:after, GraphQL::GraphQLString),
  GraphQL::GraphQLArgument.new(:first, GraphQL::GraphQLInt),
  GraphQL::GraphQLArgument.new(:last, GraphQL::GraphQLInt)
]
PageInfoType =
GraphQL::GraphQLObjectType.new do
  name          'PageInfo'
  description   'Information about pagination in a connection.'

  field :hasNextPage, !GraphQL::GraphQLBoolean do
    description 'When paginating forwards, are there more items?'
  end

  field :hasPreviousPage, !GraphQL::GraphQLBoolean do
    description 'When paginating backwards, are there more items?'
  end

  field :startCursor, GraphQL::GraphQLString do
    description 'When paginating backwards, the cursor to continue.'
  end

  field :endCursor, GraphQL::GraphQLString do
    description 'When paginating forwards, the cursor to continue.'
  end
end

Class Method Summary collapse

Class Method Details

.connection_definitions(configuration) ⇒ Object



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
# File 'lib/relay/connection/connection.rb', line 20

def self.connection_definitions(configuration)
  name, node_type = configuration.name, configuration.node_type

  edge_type = GraphQL::GraphQLObjectType.new do
    name        name + 'Edge'
    description 'An edge in a connection'

    field :node, node_type do
      description 'The item at the end of the edge'
    end

    field :cursor, ! GraphQL::GraphQLString do
      description 'A cursor for use in pagination'
    end

    fields configuration.edge_fields
  end

  connection_type = GraphQL::GraphQLObjectType.new do
    name          name + 'Connection'
    description   'A connection to a list of items.'

    field :pageInfo, !PageInfoType do
      description 'Information to aid in pagination.'
    end

    field :edges, +edge_type do
      description 'Information to aid in pagination.'
    end

    fields configuration.connection_fields
  end

  return edge_type, connection_type
end

.connection_from_array(data, args) ⇒ Object



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
# File 'lib/relay/connection/array.rb', line 13

def self.connection_from_array(data, args)
  edges   = data.each_with_index.map { |item, i| Edge.new(offset_to_cursor(i), item) }

  start   = [get_offset(args[:after], -1), -1].max + 1
  finish  = [get_offset(args[:before], edges.size + 1), edges.size + 1].min

  edges = edges.slice(start, finish)

  return EmptyConnection if edges.size == 0

  first_preslice_cursor = edges.first[:cursor]
  last_preslice_cursor  = edges.last[:cursor]

  edges = edges.slice(0, args[:first]) unless args[:first].nil?
  egdes = edges.slice!(- args[:last], edges.size) unless args[:last].nil?

  return EmptyConnection if edges.size == 0

  ArrayConnection.new(edges, PageInfo.new(
    edges.first[:cursor],
    edges.last[:cursor],
    edges.first[:cursor]  != first_preslice_cursor,
    edges.last[:cursor]   != last_preslice_cursor
  ))
end

.cursor_to_offset(cursor) ⇒ Object



43
44
45
# File 'lib/relay/connection/array.rb', line 43

def self.cursor_to_offset(cursor)
  Base64.strict_decode64(cursor).split(':').last.to_i
end

.get_offset(cursor, default_offset) ⇒ Object



47
48
49
50
51
# File 'lib/relay/connection/array.rb', line 47

def self.get_offset(cursor, default_offset)
  return default_offset unless cursor
  offset = cursor_to_offset(cursor)
  offset.nil? ? default_offset : offset
end

.offset_to_cursor(index) ⇒ Object



39
40
41
# File 'lib/relay/connection/array.rb', line 39

def self.offset_to_cursor(index)
  Base64.strict_encode64([ARRAY_CONNECTION_PREFIX, index].join(':'))
end