Documentation
¶
Overview ¶
Package parser builds Bun pagination and search query modifiers from request query parameters.
Index ¶
- func Count(search string, columnsSearchable []string) func(*bun.SelectQuery) *bun.SelectQuery
- func DecodeCursor(s string) ([]any, error)
- func EncodeCursor(vals []any) string
- func Keyset(kq KeysetQuery, cols []KeysetColumn) func(*bun.SelectQuery) *bun.SelectQuery
- func Paginate(pq *PaginationQuery, columnsSearchable []string) func(*bun.SelectQuery) *bun.SelectQuery
- type KeysetColumn
- type KeysetQuery
- type PaginationQuery
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Count ¶
func Count(search string, columnsSearchable []string) func(*bun.SelectQuery) *bun.SelectQuery
Count returns a Bun query modifier that applies only the search filter, for use with a COUNT query. Use it via query.Apply(Count(search, columns)).
func DecodeCursor ¶ added in v1.1.0
DecodeCursor reverses EncodeCursor. It returns an error for malformed input.
func EncodeCursor ¶ added in v1.1.0
EncodeCursor encodes column values into an opaque, URL-safe cursor (base64 of a JSON array).
func Keyset ¶ added in v1.1.0
func Keyset(kq KeysetQuery, cols []KeysetColumn) func(*bun.SelectQuery) *bun.SelectQuery
Keyset returns a Bun query modifier that applies the keyset seek predicate, ORDER BY, and LIMIT+1 (one extra row, so pagination.NewCursorPage can detect a further page). The cursor is decoded into one value per column; an empty or malformed cursor yields the first page (no seek predicate). When any column name is not a simple identifier, ordering is skipped (defence-in-depth against injection) and only the limit is applied.
Use it via query.Apply(Keyset(kq, cols)).
func Paginate ¶
func Paginate(pq *PaginationQuery, columnsSearchable []string) func(*bun.SelectQuery) *bun.SelectQuery
Paginate returns a Bun query modifier that applies search, sorting, and page/limit offsets. Use it via query.Apply(Paginate(pq, columns)).
pq.Page and pq.Limit are normalised in place to their defaults (1 and 10) when non-positive. Invalid sort/order values are ignored; call pq.Validate first to surface them as errors.
Types ¶
type KeysetColumn ¶ added in v1.1.0
KeysetColumn is one ordering column of a keyset. Name is the column (a plain or table-qualified identifier); Desc selects descending order. The columns, in order, must form a unique total ordering — make the last one a unique tiebreaker (typically the primary key).
type KeysetQuery ¶ added in v1.1.0
type KeysetQuery struct {
Limit int `query:"limit"`
Cursor string `query:"cursor"` // opaque; "" = first page
Before bool `query:"before"` // true = page backward (toward previous)
}
KeysetQuery holds keyset (cursor) paging parameters, bindable from the query string.
type PaginationQuery ¶
type PaginationQuery struct {
Page int `query:"page"`
Limit int `query:"limit"`
Search string `query:"search"`
Sort string `query:"sort"`
Order string `query:"order"`
}
PaginationQuery is a struct for holding pagination query parameters.
func (*PaginationQuery) Validate ¶
func (p *PaginationQuery) Validate(sortOptions []string) error
Validate validates the pagination query parameters.
Example ¶
Validate guards the incoming query against an allow-list of sortable columns and the asc/desc order values before it touches the database.
package main
import (
"fmt"
"github.com/rahmadafandi/fibr/parser"
)
func main() {
pq := &parser.PaginationQuery{Page: 1, Limit: 20, Sort: "name", Order: "asc"}
if err := pq.Validate([]string{"name", "created_at"}); err != nil {
fmt.Println("err:", err)
} else {
fmt.Println("ok")
}
bad := &parser.PaginationQuery{Sort: "password", Order: "sideways"}
fmt.Println("bad:", bad.Validate([]string{"name", "created_at"}))
}
Output: ok bad: validation failed: sort must be one of name, created_at, order must be one of asc or desc