Documentation
¶
Overview ¶
Package query provides allowlist-based filtering, sorting, and pagination for list endpoints, driven by bracketed query parameters.
URL contract:
GET /tasks?filter[completed]=true&filter[title]=report
&filter[created_at][gte]=2026-01-01
&sort=-created_at,title&page=2&per_page=25
Only developer-declared filters and sorts are accepted; unknown names, unsupported operators, and malformed pagination values are rejected with a canonical 400 invalid_query error. Column names reach SQL exclusively from the allowlist and user values only ever bind as arguments.
Index ¶
- func EncodeCursor(c Cursor) string
- func NextCursor[T any](r Result, items []T, key func(T) (value, id string)) ([]T, string)
- type Cursor
- type CursorMeta
- type Filter
- type FilterValue
- type Meta
- type Op
- type Options
- type Result
- func (r Result) ApplyCursorGORM(db *gorm.DB) *gorm.DB
- func (r Result) ApplyGORM(db *gorm.DB) *gorm.DB
- func (r Result) BuildCountSQL(base string) (string, []any)
- func (r Result) BuildCursorSQL(base string) (string, []any)
- func (r Result) BuildSQL(base string) (string, []any)
- func (r Result) CountGORM(db *gorm.DB) (int64, error)
- func (r Result) CursorLimit() int
- func (r Result) CursorMeta(next string) CursorMeta
- func (r Result) FiltersGORM(db *gorm.DB) *gorm.DB
- func (r Result) Meta(total int64) Meta
- func (r Result) Offset() int
- func (r Result) OrderSQL() string
- func (r Result) WhereSQL() (string, []any)
- type Sort
- type SortValue
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EncodeCursor ¶
EncodeCursor renders the cursor as an opaque, unpadded base64url token.
func NextCursor ¶
NextCursor trims the probe row fetched by CursorLimit and derives the next request's cursor from the last visible item. It returns the visible page and the encoded next cursor, or "" when the page was not full.
Types ¶
type Cursor ¶
type Cursor struct {
// Value store data used by this type.
Value string
// ID store data used by this type.
ID string
}
Cursor is a decoded keyset-pagination position: the sort value and id of the last row on the previous page. Both bind as strings, like Compare filter values.
func DecodeCursor ¶
DecodeCursor parses a token produced by EncodeCursor.
type CursorMeta ¶
type CursorMeta struct {
// NextCursor store data used by this type.
NextCursor *string `json:"next_cursor"`
// PerPage store data used by this type.
PerPage int `json:"per_page"`
}
CursorMeta is the pagination metadata for cursor mode. NextCursor is null on the last page.
type Filter ¶
type Filter struct {
// contains filtered or unexported fields
}
Filter declares one allowed filter parameter.
func Compare ¶
Compare matches filter[name]=v as equality and filter[name][gte|lte|gt|lt]=v as range comparisons.
type FilterValue ¶
type FilterValue struct {
// Name store data used by this type.
Name string
// Column store data used by this type.
Column string
// Op store data used by this type.
Op Op
// Values store data used by this type.
Values []string
// Bool marks values that bind as native booleans.
Bool bool
}
FilterValue is one accepted filter with its bound values.
type Meta ¶
type Meta struct {
// Page store data used by this type.
Page int `json:"page"`
// PerPage store data used by this type.
PerPage int `json:"per_page"`
// Total store data used by this type.
Total int64 `json:"total"`
// TotalPages store data used by this type.
TotalPages int64 `json:"total_pages"`
}
Meta is the standard pagination metadata for httpx.List.
type Op ¶
type Op string
Op identifies a filter operator.
const ( // OpEq define package-level implementation state. OpEq Op = "eq" // OpLike define package-level implementation state. OpLike Op = "like" // OpIn define package-level implementation state. OpIn Op = "in" // OpGte define package-level implementation state. OpGte Op = "gte" // OpLte define package-level implementation state. OpLte Op = "lte" // OpGt define package-level implementation state. OpGt Op = "gt" // OpLt define package-level implementation state. OpLt Op = "lt" )
type Options ¶
type Options struct {
// AllowedFilters store data used by this type.
AllowedFilters []Filter
// AllowedSorts store data used by this type.
AllowedSorts []Sort
// DefaultSort is applied when the request has no sort parameter, e.g.
// "-created_at". It must reference an allowed sort.
DefaultSort string
// DefaultPerPage defaults to 25.
DefaultPerPage int
// MaxPerPage clamps per_page and defaults to 100.
MaxPerPage int
// CursorSort switches the endpoint to cursor (keyset) pagination on the
// named allowed sort. In cursor mode the page and sort parameters are
// rejected, the sort is forced to CursorSort (descending when DefaultSort
// starts with "-"), rows are tie-broken on the id column, and the cursor
// parameter carries the keyset position.
CursorSort string
}
Options declares what a list endpoint accepts.
type Result ¶
type Result struct {
// Filters store data used by this type.
Filters []FilterValue
// Sorts store data used by this type.
Sorts []SortValue
// Page store data used by this type.
Page int
// PerPage store data used by this type.
PerPage int
// CursorMode reports that the endpoint uses cursor (keyset) pagination.
CursorMode bool
// Cursor is the decoded keyset position, or nil on the first page.
Cursor *Cursor
}
Result is a validated, normalized query ready to apply to a data source.
func Parse ¶
Parse validates the request's filter, sort, page, and per_page parameters against options. Rejections return a 400 *httpx.Error with code invalid_query listing the offending parameters; allowlist configuration mistakes return a 500-class *httpx.Error. When Options.CursorSort is set the endpoint uses cursor (keyset) pagination instead: page and sort are rejected and the cursor parameter is decoded into Result.Cursor.
func (Result) ApplyCursorGORM ¶
ApplyCursorGORM applies filters, the keyset predicate, the forced cursor ordering, and the probe-row limit (CursorLimit — never an offset) to a GORM chain. Trim the probe row with NextCursor before responding.
func (Result) BuildCountSQL ¶
BuildCountSQL appends only WHERE to a base statement such as "SELECT COUNT(*) FROM tasks".
func (Result) BuildCursorSQL ¶
BuildCursorSQL appends WHERE (filters plus the keyset predicate), ORDER BY, and "LIMIT ?" bound to CursorLimit — never OFFSET — to a base statement such as "SELECT id, title FROM tasks". sqlx callers pass the final statement through Rebind for their dialect.
func (Result) BuildSQL ¶
BuildSQL appends WHERE, ORDER BY, LIMIT, and OFFSET to a base statement such as "SELECT id, title FROM tasks".
func (Result) CountGORM ¶
CountGORM counts the rows matching the filters in an isolated session, so the caller's chain can still receive ApplyGORM afterwards.
func (Result) CursorLimit ¶
CursorLimit returns the row limit for cursor mode: PerPage plus one probe row that detects whether a next page exists. Trim the probe row with NextCursor before responding.
func (Result) CursorMeta ¶
func (r Result) CursorMeta(next string) CursorMeta
CursorMeta builds cursor pagination metadata for httpx.List; next == "" marks the last page and serializes next_cursor as null.
func (Result) FiltersGORM ¶
FiltersGORM applies only the filters, for use in count queries or custom chains.