79 lines
1.8 KiB
Go
79 lines
1.8 KiB
Go
package mongo
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
|
)
|
|
|
|
const (
|
|
// DefaultListLimit is the default page size for admin list endpoints.
|
|
DefaultListLimit = 10
|
|
// MaxListLimit is the maximum allowed page size.
|
|
MaxListLimit = 100
|
|
)
|
|
|
|
// ListPaginationOptions configures optional list pagination behavior.
|
|
type ListPaginationOptions struct {
|
|
Projection bson.M
|
|
}
|
|
|
|
// BuildListPagination converts API pagination parameters into MongoDB pagination options.
|
|
// filter is used to bind cursors to the active query filters via a hash.
|
|
func BuildListPagination(
|
|
limit, offset int,
|
|
cursor, sortField, sortOrder string,
|
|
filter bson.M,
|
|
opts ListPaginationOptions,
|
|
) (Pagination, error) {
|
|
if limit <= 0 {
|
|
limit = DefaultListLimit
|
|
}
|
|
if limit > MaxListLimit {
|
|
return Pagination{}, fmt.Errorf("%w: limit must be between 1 and %d", ErrInvalidPagination, MaxListLimit)
|
|
}
|
|
|
|
if sortField == "" {
|
|
sortField = "created_at"
|
|
}
|
|
if sortOrder == "" {
|
|
sortOrder = "desc"
|
|
}
|
|
|
|
sortOrderInt := -1
|
|
if sortOrder == "asc" {
|
|
sortOrderInt = 1
|
|
}
|
|
|
|
filtersHash := HashFilter(filter)
|
|
|
|
pb := NewPaginationBuilder().
|
|
Limit(limit).
|
|
SortBy(sortField, sortOrder)
|
|
|
|
if len(opts.Projection) > 0 {
|
|
pb.Projection(opts.Projection)
|
|
}
|
|
|
|
if cursor != "" {
|
|
pageCursor, err := decodePageCursor(cursor)
|
|
if err != nil {
|
|
return Pagination{}, err
|
|
}
|
|
if !pageCursor.matches(sortField, sortOrderInt) {
|
|
return Pagination{}, fmt.Errorf("%w: cursor does not match requested sort", ErrInvalidCursor)
|
|
}
|
|
if pageCursor.FiltersHash != filtersHash {
|
|
return Pagination{}, fmt.Errorf("%w: cursor does not match current filters", ErrInvalidCursor)
|
|
}
|
|
pb.Cursor(cursor)
|
|
} else {
|
|
if offset < 0 {
|
|
return Pagination{}, fmt.Errorf("%w: offset cannot be negative", ErrInvalidPagination)
|
|
}
|
|
pb.Skip(offset)
|
|
}
|
|
|
|
return pb.Build(), nil
|
|
}
|