apiquery

package module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Sep 8, 2026 License: MIT Imports: 12 Imported by: 0

README

api-query

CI CodeQL Coverage Mutation Documentation Go Reference Release Go License

api-query compiles explicitly declared API query capabilities into an immutable, storage-neutral plan. It covers field projection, relationships, typed filters, deterministic sorting, cursor or offset pagination, conservative costs, and strict transport adapters without becoming an ORM or SQL language.

The minimum supported toolchain is Go 1.26.6.

go get github.com/faustbrian/go-api-query@v1.1.0

New integrations should use the target-oriented packages under adapters/. The complete package map and adapter migration guide describe the supported legacy paths and explicit named-type conversions.

Five-minute JSON-RPC quickstart

The example uses github.com/faustbrian/go-api-query/adapters/jsonrpc as apiqueryjsonrpc and github.com/faustbrian/go-api-query/adapters/validation as apiqueryvalidation.

schema, err := apiquery.NewSchema(apiquery.SchemaConfig{
    Resource: "orders",
    Revision: "orders-v1",
    Fields: []apiquery.FieldDefinition{
        {Name: "id", Type: apiquery.TypeString, Required: true},
        {Name: "status", Type: apiquery.TypeString, Default: true},
    },
    Filters: []apiquery.FilterDefinition{{
        Name: "status", Type: apiquery.TypeString,
        Operators: []apiquery.Operator{apiquery.OpEqual, apiquery.OpIn},
    }},
    Sorts: []apiquery.SortDefinition{{
        Name: "id", Type: apiquery.TypeString, TieBreaker: true,
    }},
    Pagination: apiquery.PaginationDefinition{
        Cursor: true, DefaultPageSize: 25,
    },
    Bounds: apiquery.Bounds{
        MaxFields: 10, MaxFilterDepth: 3, MaxFilterNodes: 20,
        MaxValues: 40, MaxSorts: 3, MaxPageSize: 100,
        MaxCursorBytes: 2048, MaxCost: 100,
    },
})
if err != nil {
    return err // invalid server declaration
}

params, err := apiqueryjsonrpc.Parse(rawParams, schema.Bounds().MaxRequestBytes)
if err != nil {
    return err // sanitized transport error
}

plan, err := apiquery.Compile(ctx, schema, params.Request(), apiquery.CompileOptions{
    Authorize: func(ctx context.Context, capability apiquery.Capability) bool {
        return policy.Allows(ctx, capability.Kind, capability.Name)
    },
    MandatoryConstraints: []apiquery.Constraint{{
        Name: "tenant_id", Value: apiquery.StringValue(tenantID), Protected: true,
    }},
    CursorDecoder: cursorCodec,
})
if err != nil {
    return apiqueryvalidation.Report(err, validation.DefaultLimits())
}

// Only a reviewed plan reaches an application-owned persistence adapter.
parts, err := pgCompiler.Compile(plan)

An explicitly empty JSON-RPC array such as "fields": [] remains different from an absent fields member. JSON objects reject unknown or duplicate members and parsing is byte-bounded before compilation.

Contract boundary

Servers own every field, filter, operator, relationship, sort, bound, cost, cursor version, authorization decision, and mandatory predicate. Clients never supply identifiers, SQL, regular expressions, functions, joins, repositories, or execution behavior. The core package imports no database or transport.

Start with the complete API reference, security model, and cursor guide. Transport and adoption guides cover HTTP, OpenRPC, JSON:API composition, SQLC, and Laravel/Cline RPC migration. Shared construction, ownership, lifecycle, and composition expectations are in the versioned Golib ecosystem index and its Service edge family.

Local quality gates

make inventory   # repository and package manifest consistency
make check       # the complete shared module contract
make ci          # repository contract plus the complete module contract

Verification is provided by the pinned go-library-tools release declared in .golib.yaml. PostgreSQL defaults to the shared task-owned fixture; set APIQUERY_TEST_DATABASE_URL to use an existing test database. No package executes queries or contacts a service at runtime.

Stability

The repository is on the stable v1 line and supports Go 1.26.6. Public compatibility rules are in docs/compatibility.md, current changes are in CHANGELOG.md, and the stable exported API is recorded in api/v1.txt.

Documentation

Start with the documentation index for transport, cursor, authorization, SQL, compatibility, and operations guidance.

Documentation

Overview

Package apiquery compiles declared API query capabilities into immutable, transport-neutral plans.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AuthorizeFunc

type AuthorizeFunc func(context.Context, Capability) bool

AuthorizeFunc decides whether a declared capability is available to the current principal. It runs only after the schema declaration is found.

type Bounds

type Bounds struct {
	MaxRequestBytes   int
	MaxFields         int
	MaxIncludes       int
	MaxIncludeDepth   int
	MaxFilterDepth    int
	MaxFilterNodes    int
	MaxValues         int
	MaxMembership     int
	MaxStringBytes    int
	MaxSorts          int
	MaxPageSize       int
	MaxCursorBytes    int
	MaxCanonicalBytes int
	MaxErrors         int
	MaxCost           int
}

Bounds contains hard compilation and resource limits. Zero values receive conservative defaults rather than disabling a bound.

type Capability

type Capability struct {
	Kind CapabilityKind
	Name string
}

Capability describes a declared element to an application authorizer.

type CapabilityKind

type CapabilityKind string

CapabilityKind identifies an authorization decision without exposing schema internals through failures.

const (
	CapabilityField        CapabilityKind = "field"
	CapabilityFilter       CapabilityKind = "filter"
	CapabilitySort         CapabilityKind = "sort"
	CapabilityRelationship CapabilityKind = "relationship"
)

type CompileOptions

type CompileOptions struct {
	Authorize            AuthorizeFunc
	MandatoryConstraints []Constraint
	CursorDecoder        CursorDecoder
}

CompileOptions supplies request-scoped policy without mutating the schema.

type Constraint

type Constraint struct {
	Name      string `json:"name"`
	Value     Value  `json:"value"`
	Protected bool   `json:"protected"`
}

Constraint is a server-owned mandatory equality predicate. Transport input cannot create, remove, or replace constraints.

type CursorDecoder

type CursorDecoder interface {
	DecodeCursor(context.Context, string, string, []SortTerm) (CursorState, error)
}

CursorDecoder authenticates and decodes one opaque cursor for an exact schema revision and ordered sort contract.

type CursorDirection

type CursorDirection string

CursorDirection identifies the seek direction authenticated by a cursor.

const (
	CursorForward  CursorDirection = "forward"
	CursorBackward CursorDirection = "backward"
)

type CursorState

type CursorState struct {
	Direction CursorDirection `json:"direction"`
	Positions []Value         `json:"positions"`
	Policy    string          `json:"policy,omitempty"`
}

CursorState is the authenticated, typed cursor state retained by a plan. Positions are sensitive application data and must not be logged.

type Direction

type Direction string

Direction controls ordered sorting.

const (
	Ascending  Direction = "asc"
	Descending Direction = "desc"
)

type ErrorCode

type ErrorCode string

ErrorCode is a stable machine-readable query failure category.

const (
	CodeInvalidElement  ErrorCode = "invalid_element"
	CodeUnsupported     ErrorCode = "unsupported_operation"
	CodeConflict        ErrorCode = "conflict"
	CodeAuthorization   ErrorCode = "authorization_rejected"
	CodeCostLimit       ErrorCode = "cost_limit"
	CodeCursorFailure   ErrorCode = "cursor_failure"
	CodeVersionMismatch ErrorCode = "version_mismatch"
	CodeLimitExceeded   ErrorCode = "limit_exceeded"
)

type FieldDefinition

type FieldDefinition struct {
	Name       string
	Type       ValueType
	Default    bool
	Required   bool
	Deprecated bool
	Cost       int
}

FieldDefinition declares one selectable field.

type FilterDefinition

type FilterDefinition struct {
	Name       string
	Type       ValueType
	Operators  []Operator
	Protected  bool
	Deprecated bool
	Nullable   bool
	AllowEmpty bool
	Cost       int
}

FilterDefinition declares the only operations accepted for one filter.

type FilterExpr

type FilterExpr struct {
	Predicate *Predicate   `json:"predicate,omitempty"`
	Logic     Logic        `json:"logic,omitempty"`
	Children  []FilterExpr `json:"children,omitempty"`
}

FilterExpr is either one Predicate or one logical group.

type Logic

type Logic string

Logic identifies a bounded logical composition.

const (
	LogicAnd Logic = "and"
	LogicOr  Logic = "or"
	LogicNot Logic = "not"
)

type NullOrder

type NullOrder string

NullOrder declares deterministic null placement.

const (
	NullsFirst NullOrder = "first"
	NullsLast  NullOrder = "last"
)

type Operator

type Operator string

Operator is a declared, typed predicate operation.

const (
	OpEqual          Operator = "eq"
	OpNotEqual       Operator = "neq"
	OpLess           Operator = "lt"
	OpLessOrEqual    Operator = "lte"
	OpGreater        Operator = "gt"
	OpGreaterOrEqual Operator = "gte"
	OpIn             Operator = "in"
	OpNotIn          Operator = "not_in"
	OpBetween        Operator = "between"
	OpIsNull         Operator = "is_null"
	OpContains       Operator = "contains"
	OpStartsWith     Operator = "starts_with"
	OpEndsWith       Operator = "ends_with"
)

type Optional

type Optional[T any] struct {
	// contains filtered or unexported fields
}

Optional distinguishes an absent request component from an explicitly supplied zero or empty value.

func Present

func Present[T any](value T) Optional[T]

Present constructs an explicitly supplied request component.

func (Optional[T]) IsPresent

func (o Optional[T]) IsPresent() bool

IsPresent reports whether the component was supplied.

func (Optional[T]) Value

func (o Optional[T]) Value() (T, bool)

Value returns the supplied value and whether it was present.

type PageMode

type PageMode string

PageMode selects a declared pagination capability.

const (
	PageNone   PageMode = "none"
	PageCursor PageMode = "cursor"
	PageOffset PageMode = "offset"
)

type PageRequest

type PageRequest struct {
	Mode   PageMode `json:"mode"`
	Size   int      `json:"size,omitempty"`
	After  string   `json:"after,omitempty"`
	Before string   `json:"before,omitempty"`
	Offset int      `json:"offset,omitempty"`
}

PageRequest describes bounded pagination without decoding a cursor.

type PaginationDefinition

type PaginationDefinition struct {
	Cursor          bool
	Offset          bool
	DefaultPageSize int
	MaxOffset       int
}

PaginationDefinition explicitly enables bounded page modes.

type Plan

type Plan struct {
	// contains filtered or unexported fields
}

Plan is an immutable, reviewed query description. Accessors return copies so adapters cannot mutate a plan after compilation.

func Compile

func Compile(ctx context.Context, schema *Schema, request Request, options CompileOptions) (*Plan, error)

Compile validates and snapshots a request into an immutable plan.

Example
package main

import (
	"context"
	"fmt"

	apiquery "github.com/faustbrian/go-api-query"
)

func main() {
	schema, err := apiquery.NewSchema(apiquery.SchemaConfig{
		Resource: "orders", Revision: "orders-v1",
		Fields: []apiquery.FieldDefinition{
			{Name: "id", Type: apiquery.TypeString, Required: true},
			{Name: "status", Type: apiquery.TypeString, Default: true},
		},
	})
	if err != nil {
		fmt.Println("schema error")
		return
	}
	plan, err := apiquery.Compile(context.Background(), schema, apiquery.Request{},
		apiquery.CompileOptions{})
	if err != nil {
		fmt.Println("compile error")
		return
	}
	fmt.Println(plan.Resource(), plan.SchemaRevision(), plan.ResponseFields(), plan.ExecutionFields())
}
Output:
orders orders-v1 [status] [id status]

func (*Plan) Canonical

func (p *Plan) Canonical() ([]byte, error)

Canonical returns deterministic JSON suitable for cache keys, signing, and equality tests. It contains no maps and preserves semantically ordered lists.

func (*Plan) Cost

func (p *Plan) Cost() int

Cost returns the conservative schema-defined projected cost.

func (*Plan) Cursor

func (p *Plan) Cursor() *CursorState

Cursor returns a defensive copy of authenticated cursor state, or nil for a first cursor page and non-cursor plans.

func (*Plan) ExecutionFields

func (p *Plan) ExecutionFields() []string

ExecutionFields returns response fields plus required server-only fields.

func (*Plan) Filter

func (p *Plan) Filter() *FilterExpr

Filter returns a deep copy of the reviewed filter expression.

func (*Plan) Includes

func (p *Plan) Includes() []string

Includes returns a defensive copy of reviewed relationship paths.

func (*Plan) MandatoryConstraints

func (p *Plan) MandatoryConstraints() []Constraint

MandatoryConstraints returns server-owned predicates that persistence adapters must always compose with client filters.

func (*Plan) Page

func (p *Plan) Page() PageRequest

Page returns the bounded page request.

func (*Plan) Resource

func (p *Plan) Resource() string

Resource reports the schema resource identity.

func (*Plan) ResponseFields

func (p *Plan) ResponseFields() []string

ResponseFields returns only fields authorized for response projection.

func (*Plan) SchemaRevision

func (p *Plan) SchemaRevision() string

SchemaRevision reports the exact schema revision used to compile the plan.

func (*Plan) Sorts

func (p *Plan) Sorts() []SortTerm

Sorts returns a defensive copy of the deterministic ordered sort terms.

type Predicate

type Predicate struct {
	Name     string   `json:"name"`
	Operator Operator `json:"operator"`
	Values   []Value  `json:"values"`
}

Predicate is a typed filter leaf.

type RelationshipDefinition

type RelationshipDefinition struct {
	Name          string
	Resource      string
	Cost          int
	Relationships []RelationshipDefinition
}

RelationshipDefinition declares one includable edge.

type Request

type Request struct {
	SchemaRevision Optional[string]
	Fields         Optional[[]string]
	Includes       Optional[[]string]
	Filter         *FilterExpr
	Sorts          Optional[[]SortTerm]
	Page           PageRequest
}

Request is the transport-neutral query input.

type Schema

type Schema struct {
	// contains filtered or unexported fields
}

Schema is an immutable server-declared query capability set.

func NewSchema

func NewSchema(config SchemaConfig) (*Schema, error)

NewSchema validates and defensively copies a declared schema.

func (*Schema) Bounds

func (s *Schema) Bounds() Bounds

Bounds returns the normalized immutable limits used by the schema. Transport adapters should use MaxRequestBytes as their decode limit.

type SchemaConfig

type SchemaConfig struct {
	Resource      string
	Revision      string
	Fields        []FieldDefinition
	Filters       []FilterDefinition
	Sorts         []SortDefinition
	Relationships []RelationshipDefinition
	DefaultSort   []SortTerm
	AllowedLogic  []Logic
	Pagination    PaginationDefinition
	Bounds        Bounds
}

SchemaConfig is mutable caller input used only while constructing a Schema.

type SortDefinition

type SortDefinition struct {
	Name       string
	Type       ValueType
	TieBreaker bool
	Nulls      NullOrder
	Cost       int
}

SortDefinition declares one sortable field and its ordering role.

type SortTerm

type SortTerm struct {
	Name      string    `json:"name"`
	Direction Direction `json:"direction"`
	Nulls     NullOrder `json:"nulls,omitempty"`
}

SortTerm is one ordered sort component.

type Value

type Value struct {
	// contains filtered or unexported fields
}

Value is a closed, typed query value. It deliberately cannot hold arbitrary Go values or persistence expressions.

func BoolValue

func BoolValue(value bool) Value

BoolValue constructs a boolean value.

func BytesValue

func BytesValue(value []byte) Value

BytesValue constructs a value from a defensive copy represented as base64.

func FloatValue

func FloatValue(value float64) Value

FloatValue constructs a finite floating-point value.

func IntValue

func IntValue(value int64) Value

IntValue constructs a signed integer value.

func NullValue

func NullValue() Value

NullValue constructs an explicit null cursor position. Null is not a valid declared field type, filter value, or equality constraint.

func StringValue

func StringValue(value string) Value

StringValue constructs a string value.

func TimeValue

func TimeValue(value time.Time) Value

TimeValue constructs a UTC RFC 3339 timestamp value.

func UintValue

func UintValue(value uint64) Value

UintValue constructs an unsigned integer value.

func (Value) MarshalJSON

func (v Value) MarshalJSON() ([]byte, error)

MarshalJSON emits a deterministic typed representation.

func (Value) String

func (v Value) String() string

String reports the canonical textual value. Protected values should not be placed in diagnostics by callers.

func (Value) Type

func (v Value) Type() ValueType

Type reports the value's closed type.

func (*Value) UnmarshalJSON

func (v *Value) UnmarshalJSON(data []byte) error

UnmarshalJSON accepts only the canonical closed representation emitted by MarshalJSON.

type ValueType

type ValueType string

ValueType identifies the wire and comparison semantics of a typed value.

const (
	TypeString ValueType = "string"
	TypeInt    ValueType = "int"
	TypeUint   ValueType = "uint"
	TypeFloat  ValueType = "float"
	TypeBool   ValueType = "bool"
	TypeTime   ValueType = "time"
	TypeBytes  ValueType = "bytes"
	TypeNull   ValueType = "null"
)

type Violation

type Violation struct {
	Code    ErrorCode `json:"code"`
	Path    string    `json:"path"`
	Message string    `json:"message"`
}

Violation is one sanitized failure at a stable request path.

type Violations

type Violations struct {
	// contains filtered or unexported fields
}

Violations aggregates a bounded set of query failures.

func (*Violations) Error

func (v *Violations) Error() string

Error returns a stable, sanitized summary.

func (*Violations) Items

func (v *Violations) Items() []Violation

Items returns a defensive copy of the structured failures.

Directories

Path Synopsis
adapters
http
Package apiqueryhttp parses the repository's bounded conventional HTTP query representation.
Package apiqueryhttp parses the repository's bounded conventional HTTP query representation.
jsonapi
Package apiqueryjsonapi maps authoritative go-jsonapi query values into the transport-neutral request model.
Package apiqueryjsonapi maps authoritative go-jsonapi query values into the transport-neutral request model.
jsonrpc
Package apiqueryjsonrpc parses bounded JSON-RPC query parameters and exposes a caller-owned OpenRPC descriptor.
Package apiqueryjsonrpc parses bounded JSON-RPC query parameters and exposes a caller-owned OpenRPC descriptor.
postgres
Package apiquerypostgres compiles reviewed plans into allowlisted PostgreSQL statement fragments.
Package apiquerypostgres compiles reviewed plans into allowlisted PostgreSQL statement fragments.
validation
Package apiqueryvalidation projects API Query failures into immutable go-validation reports.
Package apiqueryvalidation projects API Query failures into immutable go-validation reports.
Package apiqueryhttp strictly parses conventional HTTP query strings into transport-neutral API query requests.
Package apiqueryhttp strictly parses conventional HTTP query strings into transport-neutral API query requests.
Package apiqueryjsonapi composes parsed jsonapi queries with apiquery.
Package apiqueryjsonapi composes parsed jsonapi queries with apiquery.
Package apiquerypgx translates reviewed plans into bounded PostgreSQL query primitives.
Package apiquerypgx translates reviewed plans into bounded PostgreSQL query primitives.
Package apiqueryrpc parses bounded JSON-RPC query parameters and describes their OpenRPC content without compiling or executing a query.
Package apiqueryrpc parses bounded JSON-RPC query parameters and describes their OpenRPC content without compiling or executing a query.
Package apiquerytest provides builders, fixtures, assertions, and conformance suites for API query consumers and adapters.
Package apiquerytest provides builders, fixtures, assertions, and conformance suites for API query consumers and adapters.
Package apiqueryvalidation projects query failures into validation reports without exposing rejected values or unsafe causes.
Package apiqueryvalidation projects query failures into validation reports without exposing rejected values or unsafe causes.
Package cursor encrypts, authenticates, versions, and bounds typed cursor positions without coupling them to a transport or database.
Package cursor encrypts, authenticates, versions, and bounds typed cursor positions without coupling them to a transport or database.
internal
strictjson
Package strictjson provides bounded JSON decoding with duplicate and unknown object member rejection.
Package strictjson provides bounded JSON decoding with duplicate and unknown object member rejection.

Jump to

Keyboard shortcuts

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