Documentation
¶
Index ¶
- Constants
- Variables
- func DecodeCursor(cursor string) (int, error)
- func EncodeCursor(id int) string
- func Error(w http.ResponseWriter, statusCode int, code, message string, details any)
- func ParseListLimit(r *http.Request) int
- func SendJSON(w http.ResponseWriter, statusCode int, resp Response)
- func Success(w http.ResponseWriter, data any)
- func SuccessList(w http.ResponseWriter, items any, meta any)
- type ErrorInfo
- type ListMeta
- type Pagination
- type Response
Constants ¶
const ( DefaultListLimit = 50 MinListLimit = 1 MaxListLimit = 100 )
List limit bounds shared by all cursor-paginated list endpoints.
Variables ¶
var ErrInvalidCursor = errors.New("invalid cursor")
ErrInvalidCursor is the single failure returned by DecodeCursor for any unparseable, non-numeric, or non-positive cursor token. List handlers map it to 400 VALIDATION_ERROR without disclosing why the token was bad.
Functions ¶
func DecodeCursor ¶ added in v0.8.0
DecodeCursor inverts EncodeCursor. An empty cursor means "first page" → (0, nil). Any token that fails base64 decoding, is not a decimal integer, or decodes to id <= 0 is rejected with ErrInvalidCursor.
func EncodeCursor ¶ added in v0.8.0
EncodeCursor produces an opaque, URL-safe keyset token for the given id using unpadded base64 (RawURLEncoding) so the token contains no `=` padding — clients can drop it into a query string verbatim without worrying about padding being trimmed or mis-encoded by intermediaries. Clients must echo the token verbatim and never construct it. Opacity is for contract stability, not secrecy — the token is NOT signed; tamper-evidence is a post-MVP concern. The underlying value is the decimal id, so id DESC paging is stable across concurrent inserts/deletes (a new row lands on page 1; a deleted row never shifts later pages).
func Error ¶
func Error(w http.ResponseWriter, statusCode int, code, message string, details any)
Error sends an error response with structured error info
func ParseListLimit ¶ added in v0.8.0
ParseListLimit clamps the ?limit query param into [MinListLimit, MaxListLimit] with a default of DefaultListLimit. Missing/invalid/negative → default; over-max → max.
func SendJSON ¶
func SendJSON(w http.ResponseWriter, statusCode int, resp Response)
SendJSON sends a JSON response with the given status code
func Success ¶
func Success(w http.ResponseWriter, data any)
Success sends a successful response with data
func SuccessList ¶
func SuccessList(w http.ResponseWriter, items any, meta any)
SuccessList sends a list response whose Data is never omitted (so empty lists render as "data":[]) and whose optional Meta carries pagination. Use this for the agent v1 list endpoints instead of Success (see listResponse for the omitempty rationale).
Types ¶
type ErrorInfo ¶
type ErrorInfo struct {
Code string `json:"code"`
Message string `json:"message"`
Details any `json:"details,omitempty"`
}
ErrorInfo represents structured error information
type ListMeta ¶
type ListMeta struct {
Pagination Pagination `json:"pagination"`
}
ListMeta wraps pagination metadata under the canonical "pagination" key.
type Pagination ¶
type Pagination struct {
NextCursor string `json:"nextCursor,omitempty"`
HasMore bool `json:"hasMore"`
// Total is the number of items matching the current filters, regardless of the
// page. Populated only by offset-paginated endpoints.
Total *int `json:"total,omitempty"`
// Limit and Offset echo the page parameters the client requested. Populated only
// by offset-paginated endpoints.
Limit *int `json:"limit,omitempty"`
Offset *int `json:"offset,omitempty"`
}
Pagination is the list-pagination metadata carried in a list response's meta. It is generic so the media list (Story 2.3) reuses the same envelope. Two pagination models share this struct: cursor endpoints populate NextCursor (keyset, stable under concurrent inserts/deletes), while offset endpoints populate Total/Limit/Offset so clients know how many items match the current filters.