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// Name define the name of the connection
 11type Name generic.Type
 12
 13// NodeType define the node type handled by this relay connection
 14type NodeType generic.Type
 15
 16// EdgeType define the edge type handled by this relay connection
 17type EdgeType generic.Type
 18
 19// ConnectionType define the connection type handled by this relay connection
 20type ConnectionType generic.Type
 21
 22// NodeTypeEdgeMaker define a function that take a NodeType and an offset and
 23// create an Edge.
 24type NameEdgeMaker func(value NodeType, offset int) Edge
 25
 26// NameConMaker define a function that create a ConnectionType
 27type NameConMaker func(
 28	edges []EdgeType,
 29	nodes []NodeType,
 30	info models.PageInfo,
 31	totalCount int) (ConnectionType, error)
 32
 33// NameCon will paginate a source according to the input of a relay connection
 34func NameCon(source []NodeType, edgeMaker NameEdgeMaker, conMaker NameConMaker, input models.ConnectionInput) (ConnectionType, error) {
 35	var nodes []NodeType
 36	var edges []EdgeType
 37	var cursors []string
 38	var pageInfo models.PageInfo
 39	var totalCount = len(source)
 40
 41	emptyCon, _ := conMaker(edges, nodes, pageInfo, 0)
 42
 43	offset := 0
 44
 45	if input.After != nil {
 46		for i, value := range source {
 47			edge := edgeMaker(value, i)
 48			if edge.GetCursor() == *input.After {
 49				// remove all previous element including the "after" one
 50				source = source[i+1:]
 51				offset = i + 1
 52				pageInfo.HasPreviousPage = true
 53				break
 54			}
 55		}
 56	}
 57
 58	if input.Before != nil {
 59		for i, value := range source {
 60			edge := edgeMaker(value, i+offset)
 61
 62			if edge.GetCursor() == *input.Before {
 63				// remove all after element including the "before" one
 64				pageInfo.HasNextPage = true
 65				break
 66			}
 67
 68			edges = append(edges, edge.(EdgeType))
 69			cursors = append(cursors, edge.GetCursor())
 70			nodes = append(nodes, value)
 71		}
 72	} else {
 73		edges = make([]EdgeType, len(source))
 74		cursors = make([]string, len(source))
 75		nodes = source
 76
 77		for i, value := range source {
 78			edge := edgeMaker(value, i+offset)
 79			edges[i] = edge.(EdgeType)
 80			cursors[i] = edge.GetCursor()
 81		}
 82	}
 83
 84	if input.First != nil {
 85		if *input.First < 0 {
 86			return emptyCon, fmt.Errorf("first less than zero")
 87		}
 88
 89		if len(edges) > *input.First {
 90			// Slice result to be of length first by removing edges from the end
 91			edges = edges[:*input.First]
 92			cursors = cursors[:*input.First]
 93			nodes = nodes[:*input.First]
 94			pageInfo.HasNextPage = true
 95		}
 96	}
 97
 98	if input.Last != nil {
 99		if *input.Last < 0 {
100			return emptyCon, fmt.Errorf("last less than zero")
101		}
102
103		if len(edges) > *input.Last {
104			// Slice result to be of length last by removing edges from the start
105			edges = edges[len(edges)-*input.Last:]
106			cursors = cursors[len(cursors)-*input.Last:]
107			nodes = nodes[len(nodes)-*input.Last:]
108			pageInfo.HasPreviousPage = true
109		}
110	}
111
112	// Fill up pageInfo cursors
113	if len(cursors) > 0 {
114		pageInfo.StartCursor = cursors[0]
115		pageInfo.EndCursor = cursors[len(cursors)-1]
116	}
117
118	return conMaker(edges, nodes, pageInfo, totalCount)
119}