restheadspec

package
v1.0.3 Latest Latest
Warning

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

Go to latest
Published: Dec 30, 2025 License: MIT Imports: 25 Imported by: 0

README

RestHeadSpec - Header-Based REST API

RestHeadSpec provides a REST API where all query options are passed via HTTP headers instead of the request body. This provides cleaner separation between data and metadata, making it ideal for GET requests and RESTful architectures.

Features

  • Header-Based Querying: All query options via HTTP headers
  • Lifecycle Hooks: Before/after hooks for create, read, update, delete operations
  • Cursor Pagination: Efficient cursor-based pagination with complex sorting
  • Advanced Filtering: Field filters, search operators, AND/OR logic
  • Multiple Response Formats: Simple, detailed, and Syncfusion-compatible responses
  • Single Record as Object: Automatically return single-element arrays as objects (default)
  • Base64 Support: Base64-encoded header values for complex queries
  • Type-Aware Filtering: Automatic type detection and conversion
  • CORS Support: Comprehensive CORS headers for cross-origin requests
  • OPTIONS Method: Full OPTIONS support for CORS preflight

Quick Start

Setup with GORM
import "github.com/bitechdev/ResolveSpec/pkg/restheadspec"
import "github.com/gorilla/mux"

// Create handler
handler := restheadspec.NewHandlerWithGORM(db)

// IMPORTANT: Register models BEFORE setting up routes
handler.Registry.RegisterModel("public.users", &User{})
handler.Registry.RegisterModel("public.posts", &Post{})

// Setup routes
router := mux.NewRouter()
restheadspec.SetupMuxRoutes(router, handler, nil)

// Start server
http.ListenAndServe(":8080", router)
Setup with Bun ORM
import "github.com/bitechdev/ResolveSpec/pkg/restheadspec"
import "github.com/uptrace/bun"

// Create handler with Bun
handler := restheadspec.NewHandlerWithBun(bunDB)

// Register models
handler.Registry.RegisterModel("public.users", &User{})

// Setup routes (same as GORM)
router := mux.NewRouter()
restheadspec.SetupMuxRoutes(router, handler, nil)

Basic Usage

Simple GET Request
GET /public/users HTTP/1.1
Host: api.example.com
X-Select-Fields: id,name,email
X-FieldFilter-Status: active
X-Sort: -created_at
X-Limit: 50
With Preloading
GET /public/users HTTP/1.1
X-Select-Fields: id,name,email,department_id
X-Preload: department:id,name
X-FieldFilter-Status: active
X-Limit: 50

Common Headers

Header Description Example
X-Select-Fields Columns to include id,name,email
X-Not-Select-Fields Columns to exclude password,internal_notes
X-FieldFilter-{col} Exact match filter X-FieldFilter-Status: active
X-SearchFilter-{col} Fuzzy search (ILIKE) X-SearchFilter-Name: john
X-SearchOp-{op}-{col} Filter with operator X-SearchOp-Gte-Age: 18
X-Preload Preload relations posts:id,title
X-Sort Sort columns -created_at,+name
X-Limit Limit results 50
X-Offset Offset for pagination 100
X-Clean-JSON Remove null/empty fields true
X-Single-Record-As-Object Return single records as objects false

Available Operators: eq, neq, gt, gte, lt, lte, contains, startswith, endswith, between, betweeninclusive, in, empty, notempty

For complete header documentation, see HEADERS.md.

Lifecycle Hooks

RestHeadSpec supports lifecycle hooks for all CRUD operations:

import "github.com/bitechdev/ResolveSpec/pkg/restheadspec"

// Create handler
handler := restheadspec.NewHandlerWithGORM(db)

// Register a before-read hook (e.g., for authorization)
handler.Hooks.Register(restheadspec.BeforeRead, func(ctx *restheadspec.HookContext) error {
    // Check permissions
    if !userHasPermission(ctx.Context, ctx.Entity) {
        return fmt.Errorf("unauthorized access to %s", ctx.Entity)
    }

    // Modify query options
    ctx.Options.Limit = ptr(100) // Enforce max limit

    return nil
})

// Register an after-read hook (e.g., for data transformation)
handler.Hooks.Register(restheadspec.AfterRead, func(ctx *restheadspec.HookContext) error {
    // Transform or filter results
    if users, ok := ctx.Result.([]User); ok {
        for i := range users {
            users[i].Email = maskEmail(users[i].Email)
        }
    }
    return nil
})

// Register a before-create hook (e.g., for validation)
handler.Hooks.Register(restheadspec.BeforeCreate, func(ctx *restheadspec.HookContext) error {
    // Validate data
    if user, ok := ctx.Data.(*User); ok {
        if user.Email == "" {
            return fmt.Errorf("email is required")
        }
        // Add timestamps
        user.CreatedAt = time.Now()
    }
    return nil
})

Available Hook Types:

  • BeforeRead, AfterRead
  • BeforeCreate, AfterCreate
  • BeforeUpdate, AfterUpdate
  • BeforeDelete, AfterDelete

HookContext provides:

  • Context: Request context
  • Handler: Access to handler, database, and registry
  • Schema, Entity, TableName: Request info
  • Model: The registered model type
  • Options: Parsed request options (filters, sorting, etc.)
  • ID: Record ID (for single-record operations)
  • Data: Request data (for create/update)
  • Result: Operation result (for after hooks)
  • Writer: Response writer (allows hooks to modify response)

Cursor Pagination

RestHeadSpec supports efficient cursor-based pagination for large datasets:

GET /public/posts HTTP/1.1
X-Sort: -created_at,+id
X-Limit: 50
X-Cursor-Forward: <cursor_token>

How it works:

  1. First request returns results + cursor token in response
  2. Subsequent requests use X-Cursor-Forward or X-Cursor-Backward
  3. Cursor maintains consistent ordering even with data changes
  4. Supports complex multi-column sorting

Benefits over offset pagination:

  • Consistent results when data changes
  • Better performance for large offsets
  • Prevents "skipped" or duplicate records
  • Works with complex sort expressions

Example with hooks:

// Enable cursor pagination in a hook
handler.Hooks.Register(restheadspec.BeforeRead, func(ctx *restheadspec.HookContext) error {
    // For large tables, enforce cursor pagination
    if ctx.Entity == "posts" && ctx.Options.Offset != nil && *ctx.Options.Offset > 1000 {
        return fmt.Errorf("use cursor pagination for large offsets")
    }
    return nil
})

Response Formats

RestHeadSpec supports multiple response formats:

1. Simple Format (X-SimpleApi: true):

[
  { "id": 1, "name": "John" },
  { "id": 2, "name": "Jane" }
]

2. Detail Format (X-DetailApi: true, default):

{
  "success": true,
  "data": [...],
  "metadata": {
    "total": 100,
    "filtered": 100,
    "limit": 50,
    "offset": 0
  }
}

3. Syncfusion Format (X-Syncfusion: true):

{
  "result": [...],
  "count": 100
}

Single Record as Object (Default Behavior)

By default, RestHeadSpec automatically converts single-element arrays into objects for cleaner API responses.

Default behavior (enabled):

GET /public/users/123
{
  "success": true,
  "data": { "id": 123, "name": "John", "email": "john@example.com" }
}

To disable (force arrays):

GET /public/users/123
X-Single-Record-As-Object: false
{
  "success": true,
  "data": [{ "id": 123, "name": "John", "email": "john@example.com" }]
}

How it works:

  • When a query returns exactly one record, it's returned as an object
  • When a query returns multiple records, they're returned as an array
  • Set X-Single-Record-As-Object: false to always receive arrays
  • Works with all response formats (simple, detail, syncfusion)
  • Applies to both read operations and create/update returning clauses

CORS & OPTIONS Support

RestHeadSpec includes comprehensive CORS support for cross-origin requests:

OPTIONS Method:

OPTIONS /public/users HTTP/1.1

Returns metadata with appropriate CORS headers:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, X-Select-Fields, X-FieldFilter-*, ...
Access-Control-Max-Age: 86400
Access-Control-Allow-Credentials: true

Key Features:

  • OPTIONS returns model metadata (same as GET metadata endpoint)
  • All HTTP methods include CORS headers automatically
  • OPTIONS requests don't require authentication (CORS preflight)
  • Supports all HeadSpec custom headers (X-Select-Fields, X-FieldFilter-*, etc.)
  • 24-hour max age to reduce preflight requests

Configuration:

import "github.com/bitechdev/ResolveSpec/pkg/common"

// Get default CORS config
corsConfig := common.DefaultCORSConfig()

// Customize if needed
corsConfig.AllowedOrigins = []string{"https://example.com"}
corsConfig.AllowedMethods = []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}

Advanced Features

Base64 Encoding

For complex header values, use base64 encoding:

GET /public/users HTTP/1.1
X-Select-Fields-Base64: aWQsbmFtZSxlbWFpbA==
AND/OR Logic

Combine multiple filters with AND/OR logic:

GET /public/users HTTP/1.1
X-FieldFilter-Status: active
X-SearchOp-Gte-Age: 18
X-Filter-Logic: AND
Complex Preloading

Load nested relationships:

GET /public/users HTTP/1.1
X-Preload: posts:id,title,comments:id,text,author:name

Model Registration

type User struct {
    ID    uint   `json:"id" gorm:"primaryKey"`
    Name  string `json:"name"`
    Email string `json:"email"`
    Posts []Post `json:"posts,omitempty" gorm:"foreignKey:UserID"`
}

// Schema.Table format
handler.Registry.RegisterModel("public.users", &User{})

Complete Example

package main

import (
    "log"
    "net/http"

    "github.com/bitechdev/ResolveSpec/pkg/restheadspec"
    "github.com/gorilla/mux"
    "gorm.io/driver/postgres"
    "gorm.io/gorm"
)

type User struct {
    ID     uint   `json:"id" gorm:"primaryKey"`
    Name   string `json:"name"`
    Email  string `json:"email"`
    Status string `json:"status"`
}

func main() {
    // Connect to database
    db, err := gorm.Open(postgres.Open("your-connection-string"), &gorm.Config{})
    if err != nil {
        log.Fatal(err)
    }

    // Create handler
    handler := restheadspec.NewHandlerWithGORM(db)

    // Register models
    handler.Registry.RegisterModel("public.users", &User{})

    // Add hooks
    handler.Hooks.Register(restheadspec.BeforeRead, func(ctx *restheadspec.HookContext) error {
        log.Printf("Reading %s", ctx.Entity)
        return nil
    })

    // Setup routes
    router := mux.NewRouter()
    restheadspec.SetupMuxRoutes(router, handler, nil)

    // Start server
    log.Println("Server starting on :8080")
    log.Fatal(http.ListenAndServe(":8080", router))
}

Testing

RestHeadSpec is designed for testability:

import (
    "net/http/httptest"
    "testing"
)

func TestUserRead(t *testing.T) {
    handler := restheadspec.NewHandlerWithGORM(testDB)
    handler.Registry.RegisterModel("public.users", &User{})

    req := httptest.NewRequest("GET", "/public/users", nil)
    req.Header.Set("X-Select-Fields", "id,name")
    req.Header.Set("X-Limit", "10")

    rec := httptest.NewRecorder()
    // Test your handler...
}

See Also

License

This package is part of ResolveSpec and is licensed under the MIT License.

Documentation

Overview

Package restheadspec provides the Rest Header Spec API framework.

Rest Header Spec (restheadspec) is a RESTful API framework that reads query options, filters, sorting, pagination, and other parameters from HTTP headers instead of request bodies or query parameters. This approach provides a clean separation between data and metadata in API requests.

Key Features

  • Header-based API configuration: All query options are passed via HTTP headers
  • Database-agnostic: Works with both GORM and Bun ORM through adapters
  • Router-agnostic: Supports multiple HTTP routers (Mux, BunRouter, etc.)
  • Advanced filtering: Supports complex filter operations (eq, gt, lt, like, between, etc.)
  • Pagination and sorting: Built-in support for limit, offset, and multi-column sorting
  • Preloading and expansion: Support for eager loading relationships
  • Multiple response formats: Default, simple, and Syncfusion formats

HTTP Headers

The following headers are supported for configuring API requests:

  • X-Filters: JSON array of filter conditions
  • X-Columns: Comma-separated list of columns to select
  • X-Sort: JSON array of sort specifications
  • X-Limit: Maximum number of records to return
  • X-Offset: Number of records to skip
  • X-Preload: Comma-separated list of relations to preload
  • X-Expand: Comma-separated list of relations to expand (LEFT JOIN)
  • X-Distinct: Boolean to enable DISTINCT queries
  • X-Skip-Count: Boolean to skip total count query
  • X-Response-Format: Response format (detail, simple, syncfusion)
  • X-Clean-JSON: Boolean to remove null/empty fields
  • X-Custom-SQL-Where: Custom SQL WHERE clause (AND)
  • X-Custom-SQL-Or: Custom SQL WHERE clause (OR)

Usage Example

// Create a handler with GORM
handler := restheadspec.NewHandlerWithGORM(db)

// Register models
handler.Registry.RegisterModel("users", User{})

// Setup routes with Mux
muxRouter := mux.NewRouter()
restheadspec.SetupMuxRoutes(muxRouter, handler)

// Make a request with headers
// GET /public/users
// X-Filters: [{"column":"age","operator":"gt","value":18}]
// X-Sort: [{"column":"name","direction":"asc"}]
// X-Limit: 10

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DecodeParam

func DecodeParam(pStr string) (string, error)

DecodeParam - Decodes parameter string and returns unencoded string

func ExampleAuthorizationHook

func ExampleAuthorizationHook(ctx *HookContext) error

ExampleAuthorizationHook checks if the user has permission to perform the operation

func ExampleBunRouterWithBunDB

func ExampleBunRouterWithBunDB(bunDB *bun.DB)

ExampleBunRouterWithBunDB shows usage with both BunRouter and Bun DB

func ExampleCacheInvalidationHook

func ExampleCacheInvalidationHook(ctx *HookContext) error

ExampleCacheInvalidationHook invalidates cache after create/update/delete

func ExampleDataTransformHook

func ExampleDataTransformHook(ctx *HookContext) error

ExampleDataTransformHook modifies data before create/update

func ExampleFilterSensitiveDataHook

func ExampleFilterSensitiveDataHook(ctx *HookContext) error

ExampleFilterSensitiveDataHook removes sensitive data from responses

func ExampleRelatedDataHook

func ExampleRelatedDataHook(ctx *HookContext) error

ExampleRelatedDataHook fetches related data using the handler's database

func ExampleTxHook added in v0.0.107

func ExampleTxHook(ctx *HookContext) error

ExampleTxHook demonstrates using the Tx field to execute additional SQL queries The Tx field provides access to the database/transaction for custom queries

func ExampleValidationHook

func ExampleValidationHook(ctx *HookContext) error

ExampleValidationHook validates data before create/update operations

func ExampleWithBun

func ExampleWithBun(bunDB *bun.DB)

ExampleWithBun shows how to switch to Bun ORM

func ExampleWithGORM

func ExampleWithGORM(db *gorm.DB)

ExampleWithGORM shows how to use RestHeadSpec with GORM

func GetEntity

func GetEntity(ctx context.Context) string

GetEntity retrieves entity from context

func GetModel

func GetModel(ctx context.Context) interface{}

GetModel retrieves model from context

func GetModelPtr

func GetModelPtr(ctx context.Context) interface{}

GetModelPtr retrieves model pointer from context

func GetSchema

func GetSchema(ctx context.Context) string

GetSchema retrieves schema from context

func GetTableName

func GetTableName(ctx context.Context) string

GetTableName retrieves table name from context

func NewStandardBunRouter

func NewStandardBunRouter() *router.StandardBunRouterAdapter

NewStandardBunRouter creates a router with standard BunRouter handlers

func NewStandardMuxRouter

func NewStandardMuxRouter() *router.StandardMuxAdapter

NewStandardMuxRouter creates a router with standard Mux HTTP handlers

func RegisterSecurityHooks added in v0.0.67

func RegisterSecurityHooks(handler *Handler, securityList *security.SecurityList)

RegisterSecurityHooks registers all security-related hooks with the handler

func SetupBunRouterRoutes

func SetupBunRouterRoutes(bunRouter *router.StandardBunRouterAdapter, handler *Handler)

SetupBunRouterRoutes sets up bunrouter routes for the RestHeadSpec API

func SetupExampleHooks

func SetupExampleHooks(handler *Handler)

SetupExampleHooks demonstrates how to register hooks on a handler

func SetupMuxRoutes

func SetupMuxRoutes(muxRouter *mux.Router, handler *Handler, authMiddleware MiddlewareFunc)

SetupMuxRoutes sets up routes for the RestHeadSpec API with Mux authMiddleware is optional - if provided, routes will be protected with the middleware Example: SetupMuxRoutes(router, handler, func(h http.Handler) http.Handler { return security.NewAuthHandler(securityList, h) })

func WithEntity

func WithEntity(ctx context.Context, entity string) context.Context

WithEntity adds entity to context

func WithModel

func WithModel(ctx context.Context, model interface{}) context.Context

WithModel adds model to context

func WithModelPtr

func WithModelPtr(ctx context.Context, modelPtr interface{}) context.Context

WithModelPtr adds model pointer to context

func WithOptions added in v0.0.47

func WithOptions(ctx context.Context, options ExtendedRequestOptions) context.Context

WithOptions adds request options to context

func WithRequestData

func WithRequestData(ctx context.Context, schema, entity, tableName string, model, modelPtr interface{}, options ExtendedRequestOptions) context.Context

WithRequestData adds all request-scoped data to context at once

func WithSchema

func WithSchema(ctx context.Context, schema string) context.Context

WithSchema adds schema to context

func WithTableName

func WithTableName(ctx context.Context, tableName string) context.Context

WithTableName adds table name to context

Types

type ColumnCastInfo

type ColumnCastInfo struct {
	NeedsCast     bool
	IsNumericType bool
}

ColumnCastInfo holds information about whether a column needs casting

type CursorDirection

type CursorDirection int

CursorDirection defines pagination direction

const (
	CursorForward  CursorDirection = 1
	CursorBackward CursorDirection = -1
)

type ExpandOption

type ExpandOption struct {
	Relation string
	Columns  []string
	Where    string
	Sort     string
}

ExpandOption represents a relation expansion configuration

type ExtendedRequestOptions

type ExtendedRequestOptions struct {
	common.RequestOptions

	// Field selection
	CleanJSON bool

	// Advanced filtering
	SearchColumns  []string
	CustomSQLWhere string
	CustomSQLOr    string

	// Joins
	Expand []ExpandOption

	// Advanced features
	AdvancedSQL map[string]string // Column -> SQL expression
	ComputedQL  map[string]string // Column -> CQL expression
	Distinct    bool
	SkipCount   bool
	SkipCache   bool
	PKRow       *string

	// Response format
	ResponseFormat string // "simple", "detail", "syncfusion"

	// Single record normalization - convert single-element arrays to objects
	SingleRecordAsObject bool

	// Transaction
	AtomicTransaction bool

	// X-Files configuration - comprehensive query options as a single JSON object
	XFiles *XFiles
}

ExtendedRequestOptions extends common.RequestOptions with additional features

func GetOptions added in v0.0.47

func GetOptions(ctx context.Context) *ExtendedRequestOptions

GetOptions retrieves request options from context

func (*ExtendedRequestOptions) GetCursorFilter

func (opts *ExtendedRequestOptions) GetCursorFilter(
	tableName string,
	pkName string,
	modelColumns []string,
	expandJoins map[string]string,
) (string, error)

GetCursorFilter generates a SQL `EXISTS` subquery for cursor-based pagination. It uses the current request's sort, cursor, joins (via Expand), and CQL (via ComputedQL).

Parameters:

  • tableName: name of the main table (e.g. "post")
  • pkName: primary key column (e.g. "id")
  • modelColumns: optional list of valid main-table columns (for validation). Pass nil to skip.
  • expandJoins: optional map[alias]string of JOIN clauses (e.g. "user": "LEFT JOIN user ON ...")

Returns SQL snippet to embed in WHERE clause.

type FallbackHandler added in v0.0.69

type FallbackHandler func(w common.ResponseWriter, r common.Request, params map[string]string)

FallbackHandler is a function that handles requests when no model is found It receives the same parameters as the Handle method

type Handler

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

Handler handles API requests using database and model abstractions This handler reads filters, columns, and options from HTTP headers

func NewHandler

func NewHandler(db common.Database, registry common.ModelRegistry) *Handler

NewHandler creates a new API handler with database and registry abstractions

func NewHandlerWithBun

func NewHandlerWithBun(db *bun.DB) *Handler

NewHandlerWithBun creates a new Handler with Bun adapter

func NewHandlerWithGORM

func NewHandlerWithGORM(db *gorm.DB) *Handler

NewHandlerWithGORM creates a new Handler with GORM adapter

func (*Handler) FetchRowNumber added in v0.0.19

func (h *Handler) FetchRowNumber(ctx context.Context, tableName string, pkName string, pkValue string, options ExtendedRequestOptions, model any) (int64, error)

FetchRowNumber calculates the row number of a specific record based on sorting and filtering Returns the 1-based row number of the record with the given primary key value

func (*Handler) GetDatabase added in v0.0.65

func (h *Handler) GetDatabase() common.Database

GetDatabase returns the underlying database connection Implements common.SpecHandler interface

func (*Handler) GetRelationshipInfo added in v0.0.20

func (h *Handler) GetRelationshipInfo(modelType reflect.Type, relationName string) *common.RelationshipInfo

GetRelationshipInfo implements common.RelationshipInfoProvider interface

func (*Handler) Handle

func (h *Handler) Handle(w common.ResponseWriter, r common.Request, params map[string]string)

Handle processes API requests through router-agnostic interface Options are read from HTTP headers instead of request body

func (*Handler) HandleGet

func (h *Handler) HandleGet(w common.ResponseWriter, r common.Request, params map[string]string)

HandleGet processes GET requests for metadata

func (*Handler) HandleOpenAPI added in v0.0.87

func (h *Handler) HandleOpenAPI(w common.ResponseWriter, r common.Request)

HandleOpenAPI generates and returns the OpenAPI specification

func (*Handler) Hooks

func (h *Handler) Hooks() *HookRegistry

Hooks returns the hook registry for this handler Use this to register custom hooks for operations

func (*Handler) SetFallbackHandler added in v0.0.69

func (h *Handler) SetFallbackHandler(fallback FallbackHandler)

SetFallbackHandler sets a fallback handler to be called when no model is found If not set, the handler will simply return (pass through to next route)

func (*Handler) SetOpenAPIGenerator added in v0.0.87

func (h *Handler) SetOpenAPIGenerator(generator func() (string, error))

SetOpenAPIGenerator sets the OpenAPI generator function This allows avoiding circular dependencies

func (*Handler) ValidateAndAdjustFilterForColumnType

func (h *Handler) ValidateAndAdjustFilterForColumnType(filter *common.FilterOption, model interface{}) ColumnCastInfo

ValidateAndAdjustFilterForColumnType validates and adjusts a filter based on column type Returns ColumnCastInfo indicating whether the column should be cast to text in SQL

type HookContext

type HookContext struct {
	Context   context.Context
	Handler   *Handler // Reference to the handler for accessing database, registry, etc.
	Schema    string
	Entity    string
	TableName string
	Model     interface{}
	Options   ExtendedRequestOptions

	// Operation-specific fields
	ID          string
	Data        interface{} // For create/update operations
	Result      interface{} // For after hooks
	Error       error       // For after hooks
	QueryFilter string      // For read operations

	// Query chain - allows hooks to modify the query before execution
	// Can be SelectQuery, InsertQuery, UpdateQuery, or DeleteQuery
	Query interface{}

	// Response writer - allows hooks to modify response
	Writer common.ResponseWriter

	// Tx provides access to the database/transaction for executing additional SQL
	// This allows hooks to run custom queries in addition to the main Query chain
	Tx common.Database
}

HookContext contains all the data available to a hook

type HookFunc

type HookFunc func(*HookContext) error

HookFunc is the signature for hook functions It receives a HookContext and can modify it or return an error If an error is returned, the operation will be aborted

func ExampleAuditLogHook

func ExampleAuditLogHook(hookType HookType) HookFunc

ExampleAuditLogHook creates audit log entries for operations

func ExampleLoggingHook

func ExampleLoggingHook(hookType HookType) HookFunc

ExampleLoggingHook logs before and after operations

type HookRegistry

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

HookRegistry manages all registered hooks

func NewHookRegistry

func NewHookRegistry() *HookRegistry

NewHookRegistry creates a new hook registry

func (*HookRegistry) Clear

func (r *HookRegistry) Clear(hookType HookType)

Clear removes all hooks for the specified type

func (*HookRegistry) ClearAll

func (r *HookRegistry) ClearAll()

ClearAll removes all registered hooks

func (*HookRegistry) Count

func (r *HookRegistry) Count(hookType HookType) int

Count returns the number of hooks registered for a specific type

func (*HookRegistry) Execute

func (r *HookRegistry) Execute(hookType HookType, ctx *HookContext) error

Execute runs all hooks for the specified type in order If any hook returns an error, execution stops and the error is returned

func (*HookRegistry) GetAllHookTypes

func (r *HookRegistry) GetAllHookTypes() []HookType

GetAllHookTypes returns all hook types that have registered hooks

func (*HookRegistry) HasHooks

func (r *HookRegistry) HasHooks(hookType HookType) bool

HasHooks returns true if there are any hooks registered for the specified type

func (*HookRegistry) Register

func (r *HookRegistry) Register(hookType HookType, hook HookFunc)

Register adds a new hook for the specified hook type

func (*HookRegistry) RegisterMultiple

func (r *HookRegistry) RegisterMultiple(hookTypes []HookType, hook HookFunc)

RegisterMultiple registers a hook for multiple hook types

type HookType

type HookType string

HookType defines the type of hook to execute

const (
	// Read operation hooks
	BeforeRead HookType = "before_read"
	AfterRead  HookType = "after_read"

	// Create operation hooks
	BeforeCreate HookType = "before_create"
	AfterCreate  HookType = "after_create"

	// Update operation hooks
	BeforeUpdate HookType = "before_update"
	AfterUpdate  HookType = "after_update"

	// Delete operation hooks
	BeforeDelete HookType = "before_delete"
	AfterDelete  HookType = "after_delete"

	// Scan/Execute operation hooks
	BeforeScan HookType = "before_scan"
)

type MiddlewareFunc added in v0.0.65

type MiddlewareFunc func(http.Handler) http.Handler

MiddlewareFunc is a function that wraps an http.Handler with additional functionality

type XFiles added in v0.0.46

type XFiles struct {
	TableName   string      `json:"tablename"`
	Schema      string      `json:"schema"`
	PrimaryKey  string      `json:"primarykey"`
	ForeignKey  string      `json:"foreignkey"`
	RelatedKey  string      `json:"relatedkey"`
	Sort        []string    `json:"sort"`
	Prefix      string      `json:"prefix"`
	Editable    bool        `json:"editable"`
	Recursive   bool        `json:"recursive"`
	Expand      bool        `json:"expand"`
	Rownumber   bool        `json:"rownumber"`
	Skipcount   bool        `json:"skipcount"`
	Offset      json.Number `json:"offset"`
	Limit       json.Number `json:"limit"`
	Columns     []string    `json:"columns"`
	OmitColumns []string    `json:"omit_columns"`
	CQLColumns  []string    `json:"cql_columns"`

	SqlJoins     []string     `json:"sql_joins"`
	SqlOr        []string     `json:"sql_or"`
	SqlAnd       []string     `json:"sql_and"`
	ParentTables []*XFiles    `json:"parenttables"`
	ChildTables  []*XFiles    `json:"childtables"`
	ModelType    reflect.Type `json:"-"`
	ParentEntity *XFiles      `json:"-"`
	Level        uint         `json:"-"`
	Errors       []error      `json:"-"`
	FilterFields []struct {
		Field    string `json:"field"`
		Value    string `json:"value"`
		Operator string `json:"operator"`
	} `json:"filter_fields"`
	CursorForward  string `json:"cursor_forward"`
	CursorBackward string `json:"cursor_backward"`
}

Jump to

Keyboard shortcuts

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