connection_template.go

  1package connections
  2
  3import (
  4	"fmt"
  5
  6	"github.com/MichaelMure/git-bug/graphql/models"
  7	"github.com/cheekybits/genny/generic"
  8)
  9
 10// NodeType define the node type handled by this relay connection
 11type NodeType generic.Type
 12
 13// EdgeType define the edge type handled by this relay connection
 14type EdgeType generic.Type
 15
 16// ConnectionType define the connection type handled by this relay connection
 17type ConnectionType generic.Type
 18
 19// NodeTypeEdger define a function that take a NodeType and an offset and
 20// create an Edge.
 21type NodeTypeEdger func(value NodeType, offset int) Edge
 22
 23// NodeTypeConMaker define a function that create a ConnectionType
 24type NodeTypeConMaker func(
 25	edges []EdgeType,
 26	nodes []NodeType,
 27	info models.PageInfo,
 28	totalCount int) (ConnectionType, error)
 29
 30// NodeTypeCon will paginate a source according to the input of a relay connection
 31func NodeTypeCon(source []NodeType, edger NodeTypeEdger, conMaker NodeTypeConMaker, input models.ConnectionInput) (ConnectionType, error) {
 32	var nodes []NodeType
 33	var edges []EdgeType
 34	var pageInfo models.PageInfo
 35
 36	emptyCon, _ := conMaker(edges, nodes, pageInfo, 0)
 37
 38	offset := 0
 39
 40	if input.After != nil {
 41		for i, value := range source {
 42			edge := edger(value, i)
 43			if edge.GetCursor() == *input.After {
 44				// remove all previous element including the "after" one
 45				source = source[i+1:]
 46				offset = i + 1
 47				break
 48			}
 49		}
 50	}
 51
 52	if input.Before != nil {
 53		for i, value := range source {
 54			edge := edger(value, i+offset)
 55
 56			if edge.GetCursor() == *input.Before {
 57				// remove all after element including the "before" one
 58				break
 59			}
 60
 61			edges = append(edges, edge.(EdgeType))
 62			nodes = append(nodes, value)
 63		}
 64	} else {
 65		edges = make([]EdgeType, len(source))
 66		nodes = source
 67
 68		for i, value := range source {
 69			edges[i] = edger(value, i+offset).(EdgeType)
 70		}
 71	}
 72
 73	if input.First != nil {
 74		if *input.First < 0 {
 75			return emptyCon, fmt.Errorf("first less than zero")
 76		}
 77
 78		if len(edges) > *input.First {
 79			// Slice result to be of length first by removing edges from the end
 80			edges = edges[:*input.First]
 81			nodes = nodes[:*input.First]
 82			pageInfo.HasNextPage = true
 83		}
 84	}
 85
 86	if input.Last != nil {
 87		if *input.Last < 0 {
 88			return emptyCon, fmt.Errorf("last less than zero")
 89		}
 90
 91		if len(edges) > *input.Last {
 92			// Slice result to be of length last by removing edges from the start
 93			edges = edges[len(edges)-*input.Last:]
 94			nodes = nodes[len(nodes)-*input.Last:]
 95			pageInfo.HasPreviousPage = true
 96		}
 97	}
 98
 99	return conMaker(edges, nodes, pageInfo, len(source))
100}