pagination

package
v0.3.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 31, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package pagination adapts typed database pages to HTTP request and response contracts. Applications supply domain filters, page reads and explicit DTOs; the framework owns parsing, limits, metadata and navigation links.

Index

Constants

View Source
const (
	NumberLabelKey i18n.MessageKey = "http.pagination.page"
	SizeLabelKey   i18n.MessageKey = "http.pagination.size"
)

Label keys of the page number and page size parameters. Validation issues and exported parameter metadata carry them; their English labels are built in, and an application translates them, English included, in its catalog.

View Source
const DefaultMaximumPage = 10_000

DefaultMaximumPage bounds offset scans at MaximumPage*MaximumSize rows.

View Source
const MaximumPageWindow = 10

MaximumPageWindow bounds the per-response link generation of a page window.

Variables

This section is empty.

Functions

func Authenticated

func Authenticated[P, F, W, A, Page, Response any](endpoint pageEndpoint[P, F, W, Page, Response], binding foundryhttp.GuardBinding[A], options ...foundryhttp.GuardOption[A]) authenticatedPageEndpoint[P, F, W, A, Page, Response]

Authenticated binds a Guarded numbered, simple or cursor endpoint to its concrete actor. Configure scope, middleware, limits, errors and validation on the page before binding. Authentication and authority retain the ordinary HTTP lifecycle.

func AuthenticatedEndpointID added in v0.2.0

func AuthenticatedEndpointID[P, F, W, A, Page, Response any](e authenticatedPageEndpoint[P, F, W, A, Page, Response]) foundryhttp.RouteID

func AuthenticatedEndpointMethod added in v0.2.0

func AuthenticatedEndpointMethod[P, F, W, A, Page, Response any](e authenticatedPageEndpoint[P, F, W, A, Page, Response]) foundryhttp.Method

func AuthenticatedEndpointPattern added in v0.2.0

func AuthenticatedEndpointPattern[P, F, W, A, Page, Response any](e authenticatedPageEndpoint[P, F, W, A, Page, Response]) string

func AuthenticatedURL added in v0.3.0

func AuthenticatedURL[P, F, W, A, Page, Response any](e authenticatedPageEndpoint[P, F, W, A, Page, Response], ctx context.Context, path P, filters F, page W) (string, error)

AuthenticatedURL validates the guarded endpoint and builds a URL from concrete route, filter and pagination values using the public adapter's link policy.

func AuthorizeActor added in v0.2.0

func AuthorizeActor[P, F, W, A, Page, Response any](e authenticatedPageEndpoint[P, F, W, A, Page, Response], authorize func(context.Context, A, pageRequest[P, F, W]) error) authenticatedPageEndpoint[P, F, W, A, Page, Response]

AuthorizeActor receives the actor and validated page request before the read. It uses HTTP request-hook isolation and error mapping, including nil validation.

func Configure added in v0.2.0

func Configure[P, F, W, Page, Response any](endpoint pageEndpoint[P, F, W, Page, Response], options ...foundryhttp.EndpointOption) pageEndpoint[P, F, W, Page, Response]

func ConfigureAuthenticated added in v0.2.0

func ConfigureAuthenticated[P, F, W, A, Page, Response any](endpoint authenticatedPageEndpoint[P, F, W, A, Page, Response], options ...foundryhttp.GuardOption[A]) authenticatedPageEndpoint[P, F, W, A, Page, Response]

func CursorJSON

func CursorJSON[T any](item contract.JSON[T]) contract.JSON[CursorResponse[T]]

CursorJSON composes an explicit item DTO with count-free cursor metadata.

func CursorQuery

func CursorQuery[M any]() foundryhttp.QueryCodec[orm.Cursor[M]]

CursorQuery supplies the same typed, bounded cursor codec to custom query declarations. Its scalar metadata preserves the original model/result owner. Successful parsing validates structure; query execution verifies scope.

func EndpointID added in v0.2.0

func EndpointID[P, F, W, Page, Response any](e pageEndpoint[P, F, W, Page, Response]) foundryhttp.RouteID

func EndpointMethod added in v0.2.0

func EndpointMethod[P, F, W, Page, Response any](e pageEndpoint[P, F, W, Page, Response]) foundryhttp.Method

func EndpointPattern added in v0.2.0

func EndpointPattern[P, F, W, Page, Response any](e pageEndpoint[P, F, W, Page, Response]) string

func Handle added in v0.3.0

func Handle[P, F, W, Page, Response any](e pageEndpoint[P, F, W, Page, Response], handler func(context.Context, pageRequest[P, F, W]) (Page, error)) foundryhttp.RouteRegistration

Handle binds a domain page read. Input validation completes first; response metadata and links are completed before native JSON commits any success bytes.

func HandleAuthenticated added in v0.3.0

func HandleAuthenticated[P, F, W, A, Page, Response any](e authenticatedPageEndpoint[P, F, W, A, Page, Response], handler func(context.Context, A, pageRequest[P, F, W]) (Page, error)) foundryhttp.RouteRegistration

HandleAuthenticated preserves actor, request and ORM page types through the ordinary guarded HTTP handler. Page validation, navigation and response completion are shared with the public adapter; authority is never inferred from a cursor token.

func Inspect added in v0.2.0

func Inspect[P, F, W, Page, Response any](e pageEndpoint[P, F, W, Page, Response]) (foundryhttp.EndpointInfo, error)

func InspectAuthenticated added in v0.2.0

func InspectAuthenticated[P, F, W, A, Page, Response any](e authenticatedPageEndpoint[P, F, W, A, Page, Response]) (foundryhttp.EndpointInfo, error)

func MapPage

func MapPage[From, To any](ctx context.Context, page orm.PageResult[From], mapper func(From) (To, error)) (orm.PageResult[To], error)

MapPage converts complete source rows into explicitly chosen DTO values while preserving the ORM's page metadata. The mapper selects stored fields/getters; no persisted model is automatically exposed. Failure returns a zero page.

func MapSimplePage

func MapSimplePage[From, To any](ctx context.Context, page orm.SimplePage[From], mapper func(From) (To, error)) (orm.SimplePage[To], error)

MapSimplePage retains count-free metadata. It never adds a total or page count.

func MessageDefinitions

func MessageDefinitions() []i18n.MessageDefinition

MessageDefinitions declares the pagination labels for a catalog, beside validation.MessageDefinitions and http.MessageDefinitions. Configured applications register them automatically.

func NumberedJSON

func NumberedJSON[T any](item contract.JSON[T]) contract.JSON[NumberedResponse[T]]

NumberedJSON composes an explicitly declared item DTO with the framework's numbered response. The template's Go fields/tags own its property names; item fields and codecs remain owned by the supplied typed JSON descriptor.

func SimpleJSON

func SimpleJSON[T any](item contract.JSON[T]) contract.JSON[SimpleResponse[T]]

SimpleJSON retains the count-free response shape and the concrete item DTO.

func URL added in v0.3.0

func URL[P, F, W, Page, Response any](e pageEndpoint[P, F, W, Page, Response], ctx context.Context, path P, filters F, page W) (string, error)

URL builds a page URL from concrete route, filter and ORM request values. It uses the same query codecs/default declarations as the handler boundary and never derives an origin from an arbitrary incoming request Host.

func Validate added in v0.2.0

func Validate[P, F, W, Page, Response any](e pageEndpoint[P, F, W, Page, Response]) error

func ValidateAuthenticated added in v0.2.0

func ValidateAuthenticated[P, F, W, A, Page, Response any](e authenticatedPageEndpoint[P, F, W, A, Page, Response]) error

func ValidateFilters added in v0.2.0

func ValidateFilters[P, F, W, Page, Response any](e pageEndpoint[P, F, W, Page, Response], rules ...validation.Rule[F]) pageEndpoint[P, F, W, Page, Response]

ValidateFilters reuses generated field rules without adding a synthetic 'filters' prefix to actual query names or exported validation metadata.

func ValidatePath added in v0.2.0

func ValidatePath[P, F, W, Page, Response any](e pageEndpoint[P, F, W, Page, Response], rules ...validation.Rule[P]) pageEndpoint[P, F, W, Page, Response]

Types

type AuthenticatedCursorEndpoint

type AuthenticatedCursorEndpoint[P, F, M, A, T any] = authenticatedPageEndpoint[P, F, orm.CursorRequest[M], A, CursorResult[M, T], CursorResponse[T]]

AuthenticatedCursorEndpoint keeps cursor owner M, actor A and public DTO T distinct.

type AuthenticatedNumberedEndpoint

type AuthenticatedNumberedEndpoint[P, F, A, T any] = authenticatedPageEndpoint[P, F, orm.PageRequest, A, orm.PageResult[T], NumberedResponse[T]]

AuthenticatedNumberedEndpoint supplies a concrete actor before a numbered page read.

type AuthenticatedSimpleEndpoint

type AuthenticatedSimpleEndpoint[P, F, A, T any] = authenticatedPageEndpoint[P, F, orm.PageRequest, A, orm.SimplePage[T], SimpleResponse[T]]

AuthenticatedSimpleEndpoint is the count-free authenticated page contract.

type Config

type Config struct {
	NumberParam, SizeParam   string
	DefaultSize, MaximumSize int
	MaximumPage              int
	Links                    LinkMode
	EdgeLinks                bool
	PageWindow               int
}

Config owns wire names, defaults and a maximum size no greater than the ORM's shared bound. Explicit names permit independent paginators without implicit bracket/nesting conventions. Values are rejected, never silently clamped. MaximumPage bounds numbered/simple offset depth so a client cannot request an arbitrarily expensive OFFSET; zero selects DefaultMaximumPage. Deeper pages fail query validation and navigation omits links beyond the bound. Use cursor pagination for unbounded traversal.

EdgeLinks adds first and, for numbered pages, last links. PageWindow lists up to that many numbered pages on each side of the current page with their links (at most MaximumPageWindow); simple pages have no count and ignore it. Both are off by default and absent from the wire when disabled.

func DefaultConfig

func DefaultConfig() Config

func (Config) Validate

func (c Config) Validate() error

type CursorConfig

type CursorConfig struct {
	AfterParam, BeforeParam, SizeParam string
	DefaultSize, MaximumSize           int
	Links                              LinkMode
}

CursorConfig declares two exclusive directions and a bounded page size. The endpoint's ordinary total query-byte limit still applies to cursor tokens.

func DefaultCursorConfig

func DefaultCursorConfig() CursorConfig

func (CursorConfig) Validate

func (c CursorConfig) Validate() error

type CursorEndpoint

type CursorEndpoint[P, F, M, T any] = pageEndpoint[P, F, orm.CursorRequest[M], CursorResult[M, T], CursorResponse[T]]

CursorEndpoint preserves source owner M separately from public DTO T.

func DefineCursor

func DefineCursor[M, P, F, T any](route foundryhttp.Route[P], filters foundryhttp.Query[F], item contract.JSON[T], config CursorConfig, options ...foundryhttp.EndpointOption) CursorEndpoint[P, F, M, T]

DefineCursor declares pagination over model or projection M. Supply M explicitly; the route, generated filters and item descriptor infer the other concrete types. Query execution still validates each token's query scope and authorization must run for every request. Tokens are positions, not signed/encrypted credentials.

type CursorMeta

type CursorMeta struct {
	Size int `json:"per_page"`
}

CursorMeta reports page size only; cursor pagination does not count totals.

type CursorRequest

type CursorRequest[P, F, M any] = pageRequest[P, F, orm.CursorRequest[M]]

CursorRequest retains the original model/projection owner in its ORM request. After and Before contain cursor positions, not credentials or authorization.

type CursorResponse

type CursorResponse[T any] struct {
	Data  []T        `json:"data"`
	Meta  CursorMeta `json:"meta"`
	Links Links      `json:"links"`
}

CursorResponse contains explicit DTOs and source-owned navigation serialized through endpoint URLs. Its data is always an array; empty pages have no links.

type CursorResult

type CursorResult[M, T any] struct {
	// contains filtered or unexported fields
}

CursorResult retains a source-owned navigation position alongside explicit DTO values. MapCursorPage is its constructor; the zero value is invalid. Its private metadata preserves the validated ORM result without retaining original model rows or manufacturing cursors for the DTO type.

func MapCursorPage

func MapCursorPage[M, T any](ctx context.Context, page orm.CursorPage[M], mapper func(M) (T, error)) (CursorResult[M, T], error)

MapCursorPage selects DTO values while preserving the source's cursor owner, validated size and navigation. It never invokes a getter implicitly. Failure returns an invalid zero result and the same callback ownership as MapPage.

func (CursorResult[M, T]) Items

func (p CursorResult[M, T]) Items() []T

func (CursorResult[M, T]) Next

func (p CursorResult[M, T]) Next() value.Optional[orm.Cursor[M]]

func (CursorResult[M, T]) Previous

func (p CursorResult[M, T]) Previous() value.Optional[orm.Cursor[M]]

func (CursorResult[M, T]) Size

func (p CursorResult[M, T]) Size() int

type LinkMode

type LinkMode uint8
const (
	// RelativeLinks emits origin-relative URLs from the endpoint declaration.
	RelativeLinks LinkMode = iota + 1
	// PublicLinks uses the approved PublicURLs origin in the request context.
	PublicLinks
)
type Links struct {
	Next     value.Nullable[string] `json:"next"`
	Previous value.Nullable[string] `json:"prev"`
	First    value.Optional[string] `json:"first,omitzero"`
	Last     value.Optional[string] `json:"last,omitzero"`
	Window   []PageLink             `json:"window,omitzero"`
}

Links contains optional next/previous URLs. A link is a navigation hint, not a guarantee that data will still exist when another request is executed. First, Last and Window are opt-in (Config.EdgeLinks, Config.PageWindow) and omitted from the wire when disabled; cursor pages never carry them. Last and Window need a count, so only numbered pages carry them. No link points beyond Config.MaximumPage.

type NumberedEndpoint

type NumberedEndpoint[P, F, T any] = pageEndpoint[P, F, orm.PageRequest, orm.PageResult[T], NumberedResponse[T]]

NumberedEndpoint receives typed page input and expects an ORM page of explicit response DTOs. Handle supplies metadata and navigation before JSON encoding.

func DefineNumbered

func DefineNumbered[P, F, T any](route foundryhttp.Route[P], filters foundryhttp.Query[F], item contract.JSON[T], config Config, options ...foundryhttp.EndpointOption) NumberedEndpoint[P, F, T]

DefineNumbered composes generated filters, defaulted pagination and a declared item DTO. The endpoint accepts no request body; ordinary route/method rules apply. Config.Links=PublicLinks requires PublicURLs; ApplyMiddleware rejects a router whose PublicLinks routes are not covered by it.

type NumberedMeta

type NumberedMeta struct {
	Number int   `json:"current_page"`
	Size   int   `json:"per_page"`
	Total  int64 `json:"total"`
	Pages  int64 `json:"last_page"`
}

NumberedMeta preserves the ORM's exact numbered-page metadata, including zero last_page for an empty count. Separate count/read operations are not a snapshot.

type NumberedResponse

type NumberedResponse[T any] struct {
	Data  []T          `json:"data"`
	Meta  NumberedMeta `json:"meta"`
	Links Links        `json:"links"`
}

NumberedResponse contains explicit DTO values and shared page metadata.

type PageLink struct {
	Number int    `json:"page"`
	URL    string `json:"url"`
}

PageLink is one numbered page around the current page, in ascending order.

type Parameters

type Parameters[F any] = parameters[F, orm.PageRequest]

Parameters retains generated domain filters and the actual ORM request.

type Request

type Request[P, F any] = pageRequest[P, F, orm.PageRequest]

Request is the thin domain-handler input, with concrete path/filter types. Page is usable directly by an ORM query's Paginate or SimplePaginate method.

type SimpleEndpoint

type SimpleEndpoint[P, F, T any] = pageEndpoint[P, F, orm.PageRequest, orm.SimplePage[T], SimpleResponse[T]]

SimpleEndpoint is the corresponding count-free transport contract.

func DefineSimple

func DefineSimple[P, F, T any](route foundryhttp.Route[P], filters foundryhttp.Query[F], item contract.JSON[T], config Config, options ...foundryhttp.EndpointOption) SimpleEndpoint[P, F, T]

DefineSimple creates the same thin handler boundary without a count query or fabricated total metadata. Handlers return orm.SimplePage[T].

type SimpleMeta

type SimpleMeta struct {
	Number  int  `json:"current_page"`
	Size    int  `json:"per_page"`
	HasMore bool `json:"has_more"`
}

SimpleMeta retains navigation information without claiming a total count.

type SimpleResponse

type SimpleResponse[T any] struct {
	Data  []T        `json:"data"`
	Meta  SimpleMeta `json:"meta"`
	Links Links      `json:"links"`
}

SimpleResponse contains explicit DTO values and count-free metadata.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL