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