r3url

package
v0.5.1 Latest Latest
Warning

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

Go to latest
Published: Sep 7, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package r3url is the serialization dialect between r3 query types and URL query parameters. Two parsing modes:

  • Unified: the whole query is one JSON parameter (?query={...}), same schema as r3json.
  • Decomposed: one URL parameter per r3 component (?fields=a,b&filters=[...]&sort=name:asc&page=2&page_size=25).

ModeAuto (default) picks unified when a "query" param is present, else decomposed. Param names, sort formats, and filter styles are configurable via Option. Django-style shorthand filters (?status=active&age__gte=18) are opt-in (WithDjangoStyleFilters).

Index

Constants

This section is empty.

Variables

View Source
var ErrURLDialectorFailed = errors.New("url dialector failed")

ErrURLDialectorFailed wraps every error returned from r3url.

Functions

func FormatCursorPagination

func FormatCursorPagination(c *r3.CursorSpec, paramNames ParamNames) url.Values

FormatCursorPagination writes cursor params into url.Values; nil cursor adds none.

func FormatDjangoFilters

func FormatDjangoFilters(filters r3.Filters, cfg Config) url.Values

FormatDjangoFilters formats r3.Filters as Django-style URL parameters. AND/OR group filters aren't representable in this style and are silently skipped.

func FormatFields

func FormatFields(fields r3.Fields) string

FormatFields joins r3.Fields into a comma-separated string ("id,name").

func FormatFilters

func FormatFilters(filters r3.Filters) (string, error)

FormatFilters formats r3.Filters into a JSON string.

func FormatPagination

func FormatPagination(p *r3.PaginationSpec, paramNames ParamNames) url.Values

FormatPagination writes pagination params into url.Values; nil pagination adds none.

func FormatQuery

func FormatQuery(q r3.Query, opts ...Option) (url.Values, error)

FormatQuery formats an r3.Query into url.Values using the configured Mode and options. ModeAuto formats as decomposed (more readable URLs); use WithMode(ModeUnified) for a single JSON "query" param.

values, err := r3url.FormatQuery(q)
// values.Encode() -> "fields=id,name&sort=name:asc&page=1&page_size=25"

func FormatSort

func FormatSort(sorts r3.Sorts, format SortFormat) (string, error)

FormatSort formats r3.Sorts into a string using the specified format.

func IsErrDialectorFailure

func IsErrDialectorFailure(err error) bool

IsErrDialectorFailure reports whether err is an r3url failure.

func ParseCursorPagination

func ParseCursorPagination(values url.Values, paramNames ParamNames) (*r3.CursorSpec, error)

ParseCursorPagination reads the after/before/limit params into a r3.CursorSpec, or nil when none are present.

func ParseDjangoFilters

func ParseDjangoFilters(values url.Values, cfg Config) (r3.Filters, error)

ParseDjangoFilters parses "field__operator=value" params into r3.Filters. A param with no separator is an "eq" filter; reserved param names are skipped. The cfg.DjangoFields whitelist gates fields (empty = all, validated for identifier safety).

?status=active          -> {f: "status", op: "eq", v: "active"}
?age__gte=18            -> {f: "age", op: "gte", v: "18"}
?tags__in=a,b,c         -> {f: "tags", op: "in", v: ["a","b","c"]}

func ParseFields

func ParseFields(raw string) (r3.Fields, error)

ParseFields parses a comma-separated field list ("id,name,status") into r3.Fields; empty string returns nil.

func ParseFilters

func ParseFilters(raw string) (r3.Filters, error)

ParseFilters parses a JSON array of filter objects (r3json schema) into r3.Filters; empty string returns nil.

[{"f":"status","op":"eq","v":"active"},{"f":"age","op":"gte","v":18}]

func ParsePagination

func ParsePagination(values url.Values, paramNames ParamNames) (*r3.PaginationSpec, error)

ParsePagination reads the pagination params into a r3.PaginationSpec, or nil when none is present. It accepts either a page number (paramNames.PageNum) or a raw 0-based row offset (paramNames.Offset), each paired with an optional size (paramNames.PageSize). Page and offset are mutually exclusive; supplying both is an error.

func ParseQuery

func ParseQuery(values url.Values, opts ...Option) (r3.Query, error)

ParseQuery parses url.Values into an r3.Query using the configured Mode and options.

q, err := r3url.ParseQuery(r.URL.Query(),
    r3url.WithMode(r3url.ModeDecomposed),
    r3url.WithSortFormat(r3url.SortFormatSignPrefix),
    r3url.WithDjangoStyleFilters("status", "age", "name"),
)

func ParseSort

func ParseSort(raw string, format SortFormat) (r3.Sorts, error)

ParseSort parses a raw sort string into r3.Sorts using the specified format.

Empty string returns nil (no sorts specified).

Types

type Config

type Config struct {
	// Mode determines the parsing strategy. Default: ModeAuto.
	Mode Mode

	// ParamNames customizes the URL parameter names.
	ParamNames ParamNames

	// Sort configures sort parsing and formatting.
	Sort SortConfig

	// Filter configures filter parsing.
	Filter FilterConfig
}

Config controls how the URL dialect parses and formats query parameters.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a Config with sensible defaults.

type FilterConfig

type FilterConfig struct {
	// AllowDjangoStyle enables parsing field__op=value params as filters. Default: false.
	AllowDjangoStyle bool

	// DjangoSeparator separates field name from operator. Default: "__".
	DjangoSeparator string

	// DjangoFields whitelists which fields may appear in Django-style filters. Empty means
	// all fields (validated for identifier safety) - set it as a security safeguard so
	// arbitrary query params aren't interpreted as filters.
	DjangoFields []string

	// AllowWhen enables the ?when= recurring time-pattern filter. Default: false.
	AllowWhen bool

	// WhenField is the time column the ?when= filter targets. Required when
	// AllowWhen is set; validated for identifier safety.
	WhenField string
}

FilterConfig configures filter parsing.

type Mode

type Mode int

Mode determines the parsing/formatting strategy for URL query parameters.

const (
	// ModeAuto (default) uses unified mode when the "query" param is present, else decomposed.
	ModeAuto Mode = iota
	// ModeUnified accepts only the single JSON "query" parameter.
	ModeUnified
	// ModeDecomposed accepts only decomposed parameters (fields, filters, sort, page, page_size).
	ModeDecomposed
)

type Option

type Option func(*Config)

Option is a functional option for configuring the URL dialect.

func WithDjangoSeparator

func WithDjangoSeparator(sep string) Option

WithDjangoSeparator sets the field/operator separator for Django-style params (default "__").

func WithDjangoStyleFilters

func WithDjangoStyleFilters(fields ...string) Option

WithDjangoStyleFilters enables Django-style filter parsing, whitelisted to the given fields. No fields means all fields are allowed (not recommended - see FilterConfig).

func WithMode

func WithMode(m Mode) Option

WithMode sets the parsing/formatting mode.

func WithParamNames

func WithParamNames(p ParamNames) Option

WithParamNames sets custom parameter names.

func WithSortFormat

func WithSortFormat(f SortFormat) Option

WithSortFormat sets the sort format.

func WithWhenFilter added in v0.1.5

func WithWhenFilter(field string) Option

WithWhenFilter enables the ?when= recurring time-pattern filter, targeting the given time column (e.g. "started_at"). The keyword ("weekends", "mornings") is resolved through the years vocabulary by the when dialect; an unknown keyword is a client error, so it surfaces as a parse error rather than being ignored.

type ParamNames

type ParamNames struct {
	// Query is the parameter name for unified mode. Default: "query".
	Query string
	// Fields is the parameter name for the fields list. Default: "fields".
	Fields string
	// Filters is the parameter name for the filters JSON array. Default: "filters".
	Filters string
	// Sort is the parameter name for the sort specification. Default: "sort".
	Sort string
	// PageNum is the parameter name for the page number. Default: "page".
	PageNum string
	// PageSize is the parameter name for the page size. Default: "page_size".
	PageSize string
	// Offset is the parameter name for a raw 0-based row offset, an alternative
	// to PageNum (paired with PageSize as the limit). Default: "offset".
	Offset string

	// CursorAfter is the parameter name for forward cursor token. Default: "after".
	CursorAfter string
	// CursorBefore is the parameter name for backward cursor token. Default: "before".
	CursorBefore string
	// CursorLimit is the parameter name for cursor page size. Default: "limit".
	CursorLimit string

	// When is the parameter name for recurring time-pattern filters
	// (?when=weekends). Default: "when".
	When string
}

ParamNames allows customizing the URL parameter names used during parsing and formatting.

func DefaultParamNames

func DefaultParamNames() ParamNames

DefaultParamNames returns parameter names with sensible defaults.

type SortConfig

type SortConfig struct {
	// Format controls how sort is parsed/formatted. Default: SortFormatColonDir.
	Format SortFormat
}

SortConfig configures sort parsing and formatting.

type SortFormat

type SortFormat int

SortFormat controls how sort parameters are parsed and formatted.

const (
	// SortFormatColonDir uses comma-separated "field:direction" pairs, with an
	// optional nulls position: "name:asc,age:desc" or "name:asc:nulls_last".
	SortFormatColonDir SortFormat = iota

	// SortFormatSignPrefix uses a "-" prefix for descending ("name,-age"). No nulls position.
	SortFormatSignPrefix

	// SortFormatJSON parses a JSON array of sort objects, same schema as r3json.
	// Example: [{"field":"name","direction":"asc"}].
	SortFormatJSON
)

Jump to

Keyboard shortcuts

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