package connection import ( "errors" "fmt" "github.com/samber/lo" "math" ) type Connection[T Cursor] struct { Edges []T `json:"edges"` PageInfo *PageInfo `json:"page_info"` } func (c *Connection[T]) Reverse() { c.Edges = lo.Reverse[T](c.Edges) } func (c *Connection[T]) Grain(after, before *string) error { if after != nil && before != nil { return errors.New("illegal arguments: only one of `after` or `before` can be used at a time") } if len(c.Edges) == 0 { c.PageInfo = new(PageInfo) return nil } edges := lo.FlatMap[T, string](c.Edges, func(item T, _ int) []string { return []string{item.Cursor()} }) c.PageInfo = &PageInfo{ StartCursor: lo.ToPtr(edges[0]), EndCursor: lo.ToPtr(edges[(len(edges) - 1)]), } if after != nil { if idx := lo.IndexOf(edges, *after); idx != -1 { c.Edges = lo.Slice[T](c.Edges, idx+1, math.MaxUint32) } } if before != nil { if idx := lo.IndexOf(edges, *before); idx != -1 { c.Edges = lo.Subset[T](c.Edges, -idx, math.MaxUint32) } } return nil } func (c *Connection[T]) Slice(first, last *int) error { if first != nil && last != nil { return fmt.Errorf("illegal agruments: only one of `first` or `last` can be used at a time") } if first != nil { c.Edges = lo.Slice[T](c.Edges, 0, *first) } if last != nil { c.Edges = lo.Subset[T](c.Edges, -*last, math.MaxUint32) } if len(c.Edges) < 1 { c.PageInfo.HasPreviousPage = c.PageInfo.StartCursor != nil c.PageInfo.HasNextPage = c.PageInfo.EndCursor != nil c.PageInfo.StartCursor = nil c.PageInfo.EndCursor = nil } else { c.PageInfo.HasPreviousPage = !(*c.PageInfo.StartCursor == c.Edges[0].Cursor()) c.PageInfo.HasNextPage = !(*c.PageInfo.EndCursor == c.Edges[len(c.Edges)-1].Cursor()) c.PageInfo.StartCursor = lo.ToPtr(c.Edges[0].Cursor()) c.PageInfo.EndCursor = lo.ToPtr(c.Edges[len(c.Edges)-1].Cursor()) } return nil }