Use dedicated type for each order field
Signed-off-by: gearnode <bryan@frimin.fr>
This commit is contained in:
@@ -19,17 +19,17 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
Cursor struct {
|
||||
Cursor[T OrderField] struct {
|
||||
Size int
|
||||
Position Position
|
||||
Key *CursorKey
|
||||
OrderBy OrderBy
|
||||
OrderBy OrderBy[T]
|
||||
}
|
||||
|
||||
Position string
|
||||
|
||||
OrderBy struct {
|
||||
Field OrderField
|
||||
OrderBy[T OrderField] struct {
|
||||
Field T
|
||||
Direction OrderDirection
|
||||
}
|
||||
)
|
||||
@@ -41,27 +41,20 @@ const (
|
||||
Head Position = "HEAD"
|
||||
)
|
||||
|
||||
func NewCursor(size int, from *CursorKey, pos Position, orderBy *OrderBy) *Cursor {
|
||||
func NewCursor[T OrderField](size int, from *CursorKey, pos Position, orderBy OrderBy[T]) *Cursor[T] {
|
||||
if size == 0 {
|
||||
size = DefaultCursorSize
|
||||
}
|
||||
|
||||
if orderBy == nil {
|
||||
orderBy = &OrderBy{
|
||||
Field: OrderFieldCreatedAt,
|
||||
Direction: OrderDirectionDesc,
|
||||
}
|
||||
}
|
||||
|
||||
return &Cursor{
|
||||
return &Cursor[T]{
|
||||
Size: size,
|
||||
Key: from,
|
||||
Position: pos,
|
||||
OrderBy: *orderBy,
|
||||
OrderBy: orderBy,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cursor) SQLFragment() string {
|
||||
func (c *Cursor[T]) SQLFragment() string {
|
||||
fieldName := c.OrderBy.Field.Column()
|
||||
|
||||
var orderDirection string
|
||||
@@ -88,7 +81,7 @@ func (c *Cursor) SQLFragment() string {
|
||||
return whereClause + " ORDER BY " + orderByClause + " LIMIT @cursor_limit"
|
||||
}
|
||||
|
||||
func (c *Cursor) SQLArguments() pgx.NamedArgs {
|
||||
func (c *Cursor[T]) SQLArguments() pgx.NamedArgs {
|
||||
var size = c.Size
|
||||
if c.Key == nil {
|
||||
size += 1
|
||||
|
||||
@@ -21,51 +21,6 @@ import (
|
||||
type (
|
||||
OrderField interface {
|
||||
Column() string
|
||||
fmt.Stringer
|
||||
}
|
||||
|
||||
GenericOrderField string
|
||||
)
|
||||
|
||||
const (
|
||||
OrderFieldCreatedAt GenericOrderField = "CREATED_AT"
|
||||
OrderFieldUpdatedAt GenericOrderField = "UPDATED_AT"
|
||||
OrderFieldName GenericOrderField = "NAME"
|
||||
)
|
||||
|
||||
func (of GenericOrderField) String() string {
|
||||
return string(of)
|
||||
}
|
||||
|
||||
func (of GenericOrderField) Column() string {
|
||||
switch of {
|
||||
case OrderFieldCreatedAt:
|
||||
return "created_at"
|
||||
case OrderFieldUpdatedAt:
|
||||
return "updated_at"
|
||||
case OrderFieldName:
|
||||
return "name"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (of GenericOrderField) MarshalText() ([]byte, error) {
|
||||
return []byte(of.String()), nil
|
||||
}
|
||||
|
||||
func (of *GenericOrderField) UnmarshalText(data []byte) error {
|
||||
val := string(data)
|
||||
|
||||
switch val {
|
||||
case OrderFieldCreatedAt.String():
|
||||
*of = OrderFieldCreatedAt
|
||||
case OrderFieldUpdatedAt.String():
|
||||
*of = OrderFieldUpdatedAt
|
||||
case OrderFieldName.String():
|
||||
*of = OrderFieldName
|
||||
default:
|
||||
return fmt.Errorf("invalid GenericOrderField value: %q", val)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
package page
|
||||
|
||||
type (
|
||||
Paginable interface {
|
||||
CursorKey(orderBy OrderField) CursorKey
|
||||
Paginable[T OrderField] interface {
|
||||
CursorKey(orderBy T) CursorKey
|
||||
}
|
||||
|
||||
PageInfo struct {
|
||||
@@ -24,14 +24,14 @@ type (
|
||||
HasPrev bool
|
||||
}
|
||||
|
||||
Page[T Paginable] struct {
|
||||
Page[T Paginable[U], U OrderField] struct {
|
||||
Info *PageInfo
|
||||
Cursor *Cursor
|
||||
Cursor *Cursor[U]
|
||||
Data []T
|
||||
}
|
||||
)
|
||||
|
||||
func (p *Page[T]) First() T {
|
||||
func (p *Page[T, U]) First() T {
|
||||
if len(p.Data) == 0 {
|
||||
var zero T
|
||||
return zero
|
||||
@@ -40,7 +40,7 @@ func (p *Page[T]) First() T {
|
||||
return p.Data[0]
|
||||
}
|
||||
|
||||
func (p *Page[T]) Last() T {
|
||||
func (p *Page[T, U]) Last() T {
|
||||
if len(p.Data) == 0 {
|
||||
var zero T
|
||||
return zero
|
||||
@@ -49,11 +49,11 @@ func (p *Page[T]) Last() T {
|
||||
return p.Data[len(p.Data)-1]
|
||||
}
|
||||
|
||||
func NewPage[T Paginable](data []T, c *Cursor) *Page[T] {
|
||||
func NewPage[T Paginable[U], U OrderField](data []T, c *Cursor[U]) *Page[T, U] {
|
||||
pi := &PageInfo{}
|
||||
|
||||
if len(data) == 0 {
|
||||
return &Page[T]{
|
||||
return &Page[T, U]{
|
||||
Info: pi,
|
||||
Data: data,
|
||||
}
|
||||
@@ -109,7 +109,7 @@ func NewPage[T Paginable](data []T, c *Cursor) *Page[T] {
|
||||
}
|
||||
}
|
||||
|
||||
return &Page[T]{
|
||||
return &Page[T, U]{
|
||||
Info: pi,
|
||||
Cursor: c,
|
||||
Data: edges,
|
||||
|
||||
Reference in New Issue
Block a user