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