ezutil

package module
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Aug 20, 2025 License: MIT Imports: 31 Imported by: 4

README

EZUtil

CI Tests Go Report Card codecov Go Reference

A comprehensive, production-ready Go utility library that provides common functionality for web applications built with Gin, GORM, and other popular Go frameworks. EZUtil is designed to accelerate development by providing well-tested, reusable components for modern Go web applications.

🚀 Features

🌐 HTTP & Web Utilities
  • Gin Parameter Extraction: Type-safe parameter parsing with GetPathParam[T], GetQueryParam[T]
  • Request Binding: Simplified JSON/form data binding with validation
  • Response Helpers: Standardized JSON response utilities
  • Middleware Support: Common middleware implementations for web applications
  • Routing Utilities: Simplified routing helpers and patterns
🗄️ Database & ORM
  • GORM Integration: Seamless database connection management and configuration
  • Query Scopes: Reusable, composable query scopes for common database operations
  • Transaction Management: Robust transaction utilities with nested transaction support
  • Multi-Database Support: MySQL and PostgreSQL drivers with automatic configuration
  • Connection Pooling: Optimized database connection management
🔧 Configuration Management
  • Environment-Based Config: Automatic configuration loading from environment variables
  • Type-Safe Parsing: Built-in validation and type conversion for configuration values
  • Database Auto-Configuration: Automatic database connection setup with fallback defaults
  • Application Settings: Centralized management of app-level configuration
  • Flexible Loading: Support for loading configuration with or without database dependency
🔐 Authentication & Security
  • JWT Service: Complete JWT token creation, verification, and management
  • Secure Token Handling: Built-in token expiration and refresh capabilities
  • Authentication Middleware: Ready-to-use authentication middleware for Gin
  • Security Best Practices: Implements industry-standard security patterns
🛠️ General Utilities
  • Type-Safe Parsing: Generic Parse[T] function for string-to-type conversion
  • String Utilities: Random string generation, manipulation, and validation
  • Time Management: Date/time formatting, manipulation, and timezone handling
  • Slice Operations: Functional programming utilities (MapSlice, MapSliceWithError)
  • Error Handling: Structured error types with HTTP context and stack traces
  • Template Integration: Seamless integration with Templ template engine
  • UUID Support: UUID generation, parsing, and validation utilities

📦 Installation

go get github.com/itsLeonB/ezutil

Requirements:

  • Go 1.23 or higher
  • Compatible with Go 1.23, and 1.24

🏃 Quick Start

Basic Web Application
package main

import (
    "log"
    "time"
    
    "github.com/gin-gonic/gin"
    "github.com/itsLeonB/ezutil"
)

func main() {
    // Load configuration from environment
    defaults := ezutil.Config{
        App: &ezutil.App{
            Env:        "development",
            Port:       "8080",
            Timeout:    30 * time.Second,
            ClientUrls: []string{"http://localhost:8080"},
            Timezone:   "UTC",
        },
        Auth: &ezutil.Auth{
            SecretKey:      "your-secret-key",
            TokenDuration:  24 * time.Hour,
            CookieDuration: 7 * 24 * time.Hour,
            Issuer:         "your-app",
            URL:            "http://localhost:8080",
        },
    }
    
    config := ezutil.LoadConfig(defaults)
    
    // Create Gin router
    r := gin.Default()
    
    // Use EZUtil helpers for type-safe parameter extraction
    r.GET("/user/:id", func(c *gin.Context) {
        userID, exists, err := ezutil.GetPathParam[int](c, "id")
        if err != nil {
            c.JSON(400, gin.H{"error": "Invalid user ID format"})
            return
        }
        if !exists {
            c.JSON(400, gin.H{"error": "User ID is required"})
            return
        }
        
        c.JSON(200, gin.H{"user_id": userID, "message": "User found"})
    })
    
    // Start server
    log.Printf("Server starting on port %s", config.App.Port)
    r.Run(":" + config.App.Port)
}
Configuration Setup

Create a .env file or set environment variables:

# Application Configuration
APP_ENV=production
APP_PORT=8080
APP_TIMEOUT=30s
APP_TIMEZONE=UTC
APP_CLIENTURLS=http://localhost:8080,https://yourdomain.com

# Database Configuration
SQLDB_HOST=localhost
SQLDB_PORT=5432
SQLDB_NAME=myapp
SQLDB_USER=username
SQLDB_PASSWORD=password
SQLDB_DRIVER=postgres

# Authentication Configuration
AUTH_SECRETKEY=your-super-secret-jwt-key
AUTH_TOKENDURATION=24h
AUTH_COOKIEDURATION=168h
AUTH_ISSUER=myapp
AUTH_URL=https://yourdomain.com
Advanced Usage Examples
Database Operations with Transactions
// Initialize transactor
transactor := ezutil.NewTransactor(db)

// Use transactions with automatic rollback on error
err := transactor.WithinTransaction(ctx, func(ctx context.Context) error {
    tx, err := ezutil.GetTxFromContext(ctx)
    if err != nil {
        return err
    }
    
    // Perform database operations within transaction
    user := User{Name: "John Doe", Email: "john@example.com"}
    if err := tx.Create(&user).Error; err != nil {
        return err // Transaction will be rolled back automatically
    }
    
    // Nested transactions are supported
    return transactor.WithinTransaction(ctx, func(ctx context.Context) error {
        innerTx, err := ezutil.GetTxFromContext(ctx)
        if err != nil {
            return err
        }
        
        profile := Profile{UserID: user.ID, Bio: "Software Developer"}
        return innerTx.Create(&profile).Error
    })
})

if err != nil {
    log.Printf("Transaction failed: %v", err)
}
Type-Safe String Parsing
// Parse various types from strings
userID, err := ezutil.Parse[int]("123")
if err != nil {
    log.Printf("Invalid user ID: %v", err)
}

isActive, err := ezutil.Parse[bool]("true")
price, err := ezutil.Parse[float64]("29.99")
uuid, err := ezutil.Parse[uuid.UUID]("550e8400-e29b-41d4-a716-446655440000")

// Generate secure random strings
apiKey, err := ezutil.GenerateRandomString(32)
if err != nil {
    log.Printf("Failed to generate API key: %v", err)
}
Functional Slice Operations
// Transform slices with type safety
numbers := []int{1, 2, 3, 4, 5}
doubled := ezutil.MapSlice(numbers, func(n int) int {
    return n * 2
})
// Result: [2, 4, 6, 8, 10]

// Handle errors during transformation
strings := []string{"1", "2", "invalid", "4"}
numbers, err := ezutil.MapSliceWithError(strings, func(s string) (int, error) {
    return ezutil.Parse[int](s)
})
if err != nil {
    log.Printf("Conversion failed: %v", err)
}
Advanced Error Handling
// Create structured application errors
appErr := ezutil.NewAppError(
    "VALIDATION_ERROR",
    "Invalid input provided",
    http.StatusBadRequest,
    map[string]string{
        "field": "email",
        "issue": "invalid format",
    },
)

// Use in Gin handlers with automatic error response
r.POST("/users", func(c *gin.Context) {
    var user User
    if err := c.ShouldBindJSON(&user); err != nil {
        ezutil.HandleError(c, ezutil.NewAppError(
            "BIND_ERROR",
            "Invalid JSON payload",
            http.StatusBadRequest,
            nil,
        ))
        return
    }
    
    // Process user...
})
JWT Authentication
// Create JWT service
jwtService := ezutil.NewJWTService(config.Auth.SecretKey, config.Auth.Issuer)

// Generate tokens
claims := map[string]interface{}{
    "user_id": 123,
    "role":    "admin",
}

token, err := jwtService.GenerateToken(claims, config.Auth.TokenDuration)
if err != nil {
    log.Printf("Token generation failed: %v", err)
}

// Verify tokens
parsedClaims, err := jwtService.VerifyToken(token)
if err != nil {
    log.Printf("Token verification failed: %v", err)
}

🏗️ Project Structure

ezutil/
├── .github/
│   └── workflows/           # CI/CD workflows
│       ├── ci.yml          # Main CI pipeline
│       ├── test.yml        # Extended testing with security scans
│       └── lint.yml        # Code linting
├── test/                   # Comprehensive test suite
│   ├── *_test.go          # Test files for each module
│   ├── go.mod             # Test module dependencies
│   └── go.sum             # Test dependency checksums
├── config/                 # Configuration structures
├── internal/              # Internal utilities
├── config_loader.go       # Environment configuration loading
├── errors.go              # Error handling utilities
├── gin_*.go              # Gin framework utilities
├── gorm_*.go             # GORM database utilities
├── http_utils.go         # HTTP utilities
├── services.go           # Service layer utilities (JWT, etc.)
├── slice_utils.go        # Slice manipulation utilities
├── sql_utils.go          # SQL utilities
├── string_utils.go       # String manipulation utilities
├── templ_utils.go        # Template utilities
├── time_utils.go         # Time/date utilities
├── uuid_utils.go         # UUID utilities
├── Makefile              # Build and test automation
├── go.mod                # Go module definition
└── README.md             # This file

🧪 Testing

EZUtil includes a comprehensive test suite with over 200 individual test cases covering all exported functions and methods. The tests are organized in a separate test/ directory using the ezutil_test package for proper isolation.

Test Coverage

The test suite provides comprehensive coverage including:

  • All exported functions and methods - 100% coverage of public API
  • Happy path scenarios - Normal operation testing
  • Error conditions - Comprehensive error handling validation
  • Edge cases - Boundary condition testing
  • Database operations - Using in-memory SQLite for isolation
  • HTTP request/response handling - Complete web layer testing
  • JWT token operations - Authentication flow testing
  • Configuration loading - Environment variable processing
  • Transaction management - Database transaction testing
  • Type safety - Generic function validation
Running Tests

Use the provided Makefile commands for various testing scenarios:

# Show all available commands
make help

# Run all tests (quick)
make test

# Run tests with verbose output
make test-verbose

# Run tests with coverage report
make test-coverage

# Generate HTML coverage report
make test-coverage-html

# Clean test cache and run fresh tests
make test-clean
Continuous Integration

The project uses GitHub Actions for comprehensive CI/CD:

Main CI Pipeline (ci.yml)
  • Multi-version testing: Go 1.23, 1.24
  • Automated testing: Full test suite execution
  • Coverage reporting: Automatic upload to Codecov
  • Build verification: Cross-version compatibility
Extended Testing (test.yml)
  • Comprehensive testing: All test scenarios
  • Security scanning: Gosec static analysis
  • Dependency verification: Module integrity checks
  • SARIF reporting: Security findings integration
Code Quality (lint.yml)
  • Static analysis: golangci-lint integration
  • Code formatting: Automated style checking
  • Best practices: Go idiom enforcement
Test Organization
test/
├── config_loader_test.go    # Configuration loading tests
├── errors_test.go           # Error handling tests
├── gin_utils_test.go        # Gin utilities tests
├── gorm_scopes_test.go      # Database scope tests
├── gorm_transactor_test.go  # Transaction management tests
├── http_utils_test.go       # HTTP utility tests
├── services_test.go         # Service layer tests (JWT, etc.)
├── slice_utils_test.go      # Slice operation tests
├── sql_utils_test.go        # SQL utility tests
├── string_utils_test.go     # String manipulation tests
├── templ_utils_test.go      # Template utility tests
├── time_utils_test.go       # Time/date utility tests
└── uuid_utils_test.go       # UUID utility tests

📚 Dependencies

EZUtil builds upon several excellent Go packages:

Core Dependencies
  • Gin v1.9.1 - HTTP web framework
  • GORM v1.25.5 - ORM library for database operations
  • Eris v0.8.1 - Error handling and stack traces
  • JWT v5.2.0 - JSON Web Token implementation
Database Drivers
Utility Libraries
  • Templ v0.2.543 - Template engine integration
  • Envconfig v1.4.0 - Environment variable configuration
  • UUID v1.4.0 - UUID generation and parsing
Development Dependencies

🔧 Configuration Reference

Application Configuration (APP_*)
Variable Type Default Description
APP_ENV string development Application environment
APP_PORT string 3000 Server port number
APP_TIMEOUT duration 10s Request timeout
APP_CLIENTURLS []string ["http://localhost:3000"] Allowed client URLs
APP_TIMEZONE string America/New_York Application timezone
Database Configuration (SQLDB_*)
Variable Type Required Description
SQLDB_HOST string Database host
SQLDB_PORT string Database port
SQLDB_NAME string Database name
SQLDB_USER string Database username
SQLDB_PASSWORD string Database password
SQLDB_DRIVER string Database driver (mysql or postgres)
Authentication Configuration (AUTH_*)
Variable Type Default Description
AUTH_SECRETKEY string default-secret JWT signing key
AUTH_TOKENDURATION duration 30m JWT token lifetime
AUTH_COOKIEDURATION duration 12h Cookie lifetime
AUTH_ISSUER string default-issuer JWT issuer
AUTH_URL string http://localhost:3000 Authentication service URL

🚀 Performance & Best Practices

Database Optimization
  • Connection Pooling: Automatic connection pool management
  • Transaction Efficiency: Nested transaction support with proper rollback
  • Query Optimization: Reusable scopes for common query patterns
  • Type Safety: Compile-time type checking for database operations
Security Features
  • JWT Security: Secure token generation with configurable expiration
  • Input Validation: Built-in parameter validation and sanitization
  • Error Handling: Structured errors without sensitive information leakage
  • HTTPS Support: Ready for production HTTPS deployment
Development Experience
  • Type Safety: Generic functions for compile-time type checking
  • Error Context: Rich error information with stack traces
  • Testing Support: Comprehensive test utilities and mocks
  • Documentation: Extensive inline documentation and examples

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Development Setup
  1. Fork and Clone

    git clone https://github.com/yourusername/ezutil.git
    cd ezutil
    
  2. Install Dependencies

    go mod download
    cd test && go mod download
    
  3. Run Tests

    make test-verbose
    
  4. Run Linting

    make lint
    
Contribution Guidelines
  1. Code Quality: Ensure all tests pass and maintain test coverage
  2. Documentation: Update documentation for new features
  3. Commit Messages: Use clear, descriptive commit messages
  4. Pull Requests: Include description of changes and test results
Development Workflow
  1. Create your feature branch (git checkout -b feature/amazing-feature)
  2. Make your changes and add tests
  3. Ensure all tests pass (make test)
  4. Run linting (make lint)
  5. Commit your changes (git commit -m 'Add some amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

👨‍💻 Author

Ellion Blessan - itsLeonB

🙏 Acknowledgments

  • The Go community for excellent libraries and tools
  • Contributors who help improve this project
  • Users who provide feedback and bug reports

EZUtil - Making Go web development easier, one utility at a time. 🚀

Built with ❤️ for the Go community

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BetweenTime added in v0.10.0

func BetweenTime(col string, start, end time.Time) func(db *gorm.DB) *gorm.DB

BetweenTime returns a GORM scope that filters records between two time values. It uses GetTimeRangeClause to generate the appropriate SQL WHERE clause. Handles open-ended ranges when either start or end time is zero.

func BindRequest

func BindRequest[T any](ctx *gin.Context, bindType binding.Binding) (T, error)

BindRequest binds the incoming HTTP request to a struct of type T using the specified binding type. It supports various Gin binding types such as JSON, XML, Query, etc. Returns the bound struct or an error if binding fails.

func Capitalize added in v1.0.0

func Capitalize(word string) string

Capitalize converts the first character of a word to uppercase and the rest to lowercase. Returns an empty string if the input is empty. Useful for formatting names and titles consistently.

func CompareUUID added in v1.0.0

func CompareUUID(a, b uuid.UUID) int

CompareUUID compares two UUID values byte by byte. Returns -1 if a < b, 0 if a == b, and 1 if a > b. Useful for sorting UUIDs or implementing custom comparison logic.

func DefaultOrder added in v1.0.0

func DefaultOrder() func(*gorm.DB) *gorm.DB

DefaultOrder returns a GORM scope that applies default ordering by created_at DESC. This provides consistent ordering for queries that don't specify explicit ordering. Assumes the model has a created_at field.

func ForUpdate added in v1.0.0

func ForUpdate(enable bool) func(*gorm.DB) *gorm.DB

ForUpdate returns a GORM scope that conditionally adds FOR UPDATE locking to queries. When enable is true, it adds SELECT ... FOR UPDATE to prevent concurrent modifications. Used for pessimistic locking in transaction-critical operations.

func FormatTimeNullable added in v0.10.0

func FormatTimeNullable(t time.Time, layout string) string

FormatTimeNullable formats a time.Time using the specified layout, handling zero values gracefully. Returns an empty string if the time is zero (uninitialized), otherwise returns the formatted time. Useful for optional time fields in JSON responses and templates.

func GenerateRandomString

func GenerateRandomString(length int) (string, error)

GenerateRandomString creates a cryptographically secure random string of the specified length. The string is base64-encoded using URL-safe encoding without padding. Returns an error if length is non-positive or random generation fails.

func GetAndParseFromContext added in v0.10.0

func GetAndParseFromContext[T any](ctx *gin.Context, key string) (T, error)

GetAndParseFromContext retrieves a string value from the Gin context and parses it to type T. It combines GetFromContext and Parse operations in a single function call. Returns the parsed value or an error if the key doesn't exist or parsing fails.

func GetEndOfDay

func GetEndOfDay(year int, month int, day int) (time.Time, error)

GetEndOfDay creates a time.Time representing the end of the specified date (23:59:59.999999999 UTC). It validates the date parameters and returns an error for invalid dates. The returned time is in UTC timezone with maximum precision.

func GetFromContext

func GetFromContext[T any](ctx *gin.Context, key string) (T, error)

GetFromContext retrieves a value from the Gin context and type-asserts it to type T. Returns the typed value or an error if the key does not exist or type assertion fails. Useful for retrieving typed data stored in context by middleware.

func GetPathParam

func GetPathParam[T any](ctx *gin.Context, key string) (T, bool, error)

GetPathParam extracts and parses a path parameter from the Gin context. It returns the parsed value of type T, a boolean indicating if the parameter exists, and an error if parsing fails. If the parameter does not exist, it returns the zero value with false. Supports parsing to string, int, bool, and UUID types.

func GetRequiredPathParam added in v0.10.0

func GetRequiredPathParam[T any](ctx *gin.Context, key string) (T, error)

GetRequiredPathParam extracts and parses a required path parameter from the Gin context. It returns the parsed value of type T or an error if the parameter is missing or parsing fails. Unlike GetPathParam, this function treats missing parameters as an error condition.

func GetStartOfDay

func GetStartOfDay(year int, month int, day int) (time.Time, error)

GetStartOfDay creates a time.Time representing the start of the specified date (00:00:00 UTC). It validates the date parameters and returns an error for invalid dates. The returned time is in UTC timezone.

func GetTemplSafeUrl added in v0.10.0

func GetTemplSafeUrl(format string, args ...any) templ.SafeURL

GetTemplSafeUrl creates a templ.SafeURL from a format string and arguments. It uses fmt.Sprintf to format the URL and wraps it in templ.URL for safe template rendering. This prevents XSS attacks by ensuring URLs are properly escaped in templates.

func GetTimeRangeClause added in v0.10.0

func GetTimeRangeClause(timeCol string, start, end time.Time) (string, []any)

GetTimeRangeClause generates a SQL WHERE clause for time range filtering. It handles various combinations of start and end times, including open-ended ranges. Returns the SQL clause string and corresponding parameter values for prepared statements.

func GetTxFromContext

func GetTxFromContext(ctx context.Context) (*gorm.DB, error)

GetTxFromContext retrieves the current GORM transaction from the context. Returns an error if no transaction is found or if the stored value is not a *gorm.DB.

func MapSlice

func MapSlice[T any, U any](input []T, mapperFunc func(T) U) []U

MapSlice applies a mapping function to each element of an input slice and returns a new slice. The function transforms elements of type T to type U using the provided mapperFunc. This is a generic utility for functional-style slice transformations.

func MapSliceWithError added in v0.10.0

func MapSliceWithError[T any, U any](input []T, mapperFunc func(T) (U, error)) ([]U, error)

MapSliceWithError applies a mapping function to each element of an input slice with error handling. The function transforms elements of type T to type U using the provided mapperFunc. Returns an error immediately if any transformation fails, providing fail-fast behavior.

func NewAuthMiddleware

func NewAuthMiddleware(
	authStrategy string,
	tokenCheckFunc func(ctx *gin.Context, token string) (bool, map[string]any, error),
) gin.HandlerFunc

NewAuthMiddleware creates an authentication middleware for Gin. It extracts a token using the given strategy (e.g., "header" or "cookie") via internal.ExtractToken, calls tokenCheckFunc to validate the token and retrieve user data, stores user data in the Gin context, and aborts the request on errors. Returns a Gin HandlerFunc for authentication handling.

func NewCorsMiddleware

func NewCorsMiddleware(corsConfig *cors.Config) gin.HandlerFunc

NewCorsMiddleware creates a CORS middleware for Gin with the provided configuration. If corsConfig is nil, default settings are used (via cors.Default()). The middleware validates the configuration and logs a fatal error if invalid. Returns a Gin HandlerFunc to handle CORS according to the specified config.

func NewErrorMiddleware

func NewErrorMiddleware() gin.HandlerFunc

NewErrorMiddleware creates an error handling middleware for Gin. It should be registered last and captures errors from previous handlers, converts them into AppError or validation errors, and sends a structured JSON response with the appropriate HTTP status code. Returns a Gin HandlerFunc.

func NewPermissionMiddleware

func NewPermissionMiddleware(
	roleContextKey string,
	requiredPermission string,
	permissionMap map[string][]string,
) gin.HandlerFunc

NewPermissionMiddleware creates a permission-checking middleware for Gin. It retrieves the user role from context using the provided roleContextKey, checks if the role exists in permissionMap and includes the requiredPermission, and aborts the request with a ForbiddenError if permission is missing. Returns a Gin HandlerFunc for permission enforcement.

func OrderBy

func OrderBy(field string, ascending bool) func(db *gorm.DB) *gorm.DB

OrderBy returns a GORM scope that orders query results by the specified field. It uses internal.IsValidFieldName to validate the field name and prevent SQL injection. Set ascending to true for ascending order, false for descending.

func Paginate

func Paginate(page, limit int) func(db *gorm.DB) *gorm.DB

Paginate returns a GORM scope that applies pagination to a query. It calculates the appropriate offset based on the page number and limit. The page parameter is 1-indexed (minimum value of 1).

func Parse

func Parse[T any](value string) (T, error)

Parse converts a string value to the specified type T. Supported types include string, int, bool, and uuid.UUID. Returns an error if parsing fails or the type is unsupported.

func PreloadRelations

func PreloadRelations(relations []string) func(db *gorm.DB) *gorm.DB

PreloadRelations returns a GORM scope that preloads the specified relations. It eager loads related data to avoid N+1 query problems.

func RunServer

func RunServer(defaultConfigs Config, serverSetupFunc func(*Config) *http.Server)

RunServer initializes and runs an HTTP server with graceful shutdown support. It loads configuration using the provided defaults, invokes serverSetupFunc, and handles shutdown.

func SetupRoutes

func SetupRoutes(router *gin.Engine, routeConfigs []RouteConfig)

SetupRoutes configures Gin routes based on the provided RouteConfig slice. It creates a hierarchical route structure with groups, versions, and endpoints. The function applies middleware handlers at each level of the hierarchy. Panics if router is nil.

func WhereBySpec

func WhereBySpec[T any](spec T) func(db *gorm.DB) *gorm.DB

WhereBySpec returns a GORM scope that applies a WHERE clause based on the provided struct spec. Non-zero fields in spec will be used as AND conditions in the query.

Types

type App

type App struct {
	Env        string
	Port       string
	Timeout    time.Duration
	ClientUrls []string
	Timezone   string
}

App holds application-level settings such as environment name, server port, request timeout, allowed client URLs, and timezone. These values are populated from environment variables.

type AppError

type AppError struct {
	Type           string `json:"type"`
	Message        string `json:"message"`
	HttpStatusCode int    `json:"-"`
	Details        any    `json:"details,omitempty"`
}

AppError represents an application-specific error with HTTP context. It includes Type, Message, HttpStatusCode, and optional Details. AppError implements the error interface by returning a formatted error string.

func BadRequestError

func BadRequestError(details any) AppError

BadRequestError returns an AppError with HTTP 400 status. Use this when the client sends a malformed or invalid request.

func ConflictError

func ConflictError(details any) AppError

ConflictError returns an AppError with HTTP 409 status. Use this when a request conflicts with the current state of the server, such as attempting to create a duplicate resource.

func ForbiddenError

func ForbiddenError(details any) AppError

ForbiddenError returns an AppError with HTTP 403 status. Use this when an authenticated user lacks permission for the requested action.

func InternalServerError

func InternalServerError() AppError

InternalServerError returns an AppError with HTTP 500 status. Use this for unexpected server-side errors that should be logged and investigated.

func NotFoundError

func NotFoundError(details any) AppError

NotFoundError returns an AppError with HTTP 404 status. Use this when a requested resource cannot be found.

func UnauthorizedError

func UnauthorizedError(details any) AppError

UnauthorizedError returns an AppError with HTTP 401 status. Use this when authentication is required but missing or invalid.

func UnprocessableEntityError

func UnprocessableEntityError(details any) AppError

UnprocessableEntityError returns an AppError with HTTP 422 status. Use this when a well-formed request cannot be processed due to semantic errors.

func ValidationError

func ValidationError(details any) AppError

ValidationError returns an AppError with HTTP 422 status. Use this for input validation failures, providing details about the invalid fields.

func (AppError) Error

func (ae AppError) Error() string

Error returns a formatted string representation of the AppError. It implements the error interface by formatting Type, Message, and Details.

type Auth

type Auth struct {
	SecretKey      string
	TokenDuration  time.Duration
	CookieDuration time.Duration
	Issuer         string
	URL            string
}

Auth holds authentication configuration including JWT secret key, token and cookie durations, issuer identifier, and authentication service URL. Values are sourced from environment variables.

type CRUDRepository added in v1.0.0

type CRUDRepository[T any] interface {
	// Insert creates a new record in the database.
	Insert(ctx context.Context, model T) (T, error)
	// FindAll retrieves multiple records based on the specification.
	FindAll(ctx context.Context, spec Specification[T]) ([]T, error)
	// FindFirst retrieves the first record matching the specification.
	FindFirst(ctx context.Context, spec Specification[T]) (T, error)
	// Update modifies an existing record in the database.
	Update(ctx context.Context, model T) (T, error)
	// Delete removes a record from the database (hard delete).
	Delete(ctx context.Context, model T) error
	// BatchInsert creates multiple records in a single database operation.
	BatchInsert(ctx context.Context, models []T) ([]T, error)
	// GetGormInstance returns the appropriate GORM DB instance (transaction-aware).
	GetGormInstance(ctx context.Context) (*gorm.DB, error)
}

CRUDRepository defines a generic interface for basic CRUD operations on entities of type T. It provides standard database operations with context support and transaction awareness. The interface abstracts the underlying database implementation for easier testing and flexibility.

func NewCRUDRepository added in v1.0.0

func NewCRUDRepository[T any](db *gorm.DB) CRUDRepository[T]

NewCRUDRepository creates a new CRUD repository implementation using GORM. The repository provides transaction-aware database operations for the specified entity type T.

type Config

type Config struct {
	App     *App
	Auth    *Auth
	SQLDB   *SQLDB
	GORM    *gorm.DB
	Generic GenericConfig
}

Config represents the complete application configuration loaded from environment variables. It aggregates all configuration sections including app settings, authentication, database parameters, and the initialized GORM DB instance.

func LoadConfig

func LoadConfig(defaults Config) *Config

LoadConfig reads environment variables into the default Config, loads sub-configuration for App, Auth, and SQLDB, establishes a GORM connection, and returns the fully initialized Config.

func LoadConfigWithDB added in v1.0.0

func LoadConfigWithDB(defaults Config, connectDB bool) *Config

LoadConfigWithDB reads environment variables into the default Config with optional database connection. If connectDB is false, the GORM field will be nil, allowing for testing without database dependency.

func LoadConfigWithoutDB added in v1.0.0

func LoadConfigWithoutDB(defaults Config) *Config

LoadConfigWithoutDB loads configuration without establishing database connection. This is useful for testing or when database connection is not needed.

type EndpointConfig

type EndpointConfig struct {
	Method   string
	Endpoint string
	Handlers []gin.HandlerFunc
}

EndpointConfig represents an individual HTTP endpoint. It specifies the HTTP method, endpoint path, and handlers for a specific route. This is the leaf level of the routing hierarchy.

type GenericConfig added in v1.1.1

type GenericConfig interface {
	Prefix() string
}

type HashService added in v0.10.0

type HashService interface {
	// Hash generates a secure hash of the input value.
	Hash(val string) (string, error)
	// CheckHash verifies if a value matches the provided hash.
	CheckHash(hash, val string) (bool, error)
}

HashService provides an interface for password hashing and verification. It abstracts different hashing algorithms for secure password storage.

func NewHashService added in v0.10.0

func NewHashService(cost int) HashService

NewHashService creates a new hash service implementation using bcrypt. The cost parameter determines the computational cost of hashing (defaults to 10 if negative). Higher cost values provide better security but slower performance.

type JSONResponse

type JSONResponse struct {
	Message    string     `json:"message"`
	Data       any        `json:"data,omitzero"`
	Errors     error      `json:"errors,omitempty"`
	Pagination Pagination `json:"pagination,omitzero"`
}

JSONResponse represents a standardized HTTP JSON response structure. It can include a message, data payload, error information, and pagination metadata.

func NewErrorResponse

func NewErrorResponse(err error) JSONResponse

NewErrorResponse creates a JSONResponse for error cases. It sets the message to the error text and populates the Errors field.

func NewResponse

func NewResponse(message string) JSONResponse

NewResponse creates a basic JSONResponse with the specified message. Additional data, errors, or pagination can be added using the With* methods.

func (JSONResponse) WithData

func (jr JSONResponse) WithData(data any) JSONResponse

WithData adds a data payload to the JSONResponse. Returns a new JSONResponse with the Data field populated.

func (JSONResponse) WithError

func (jr JSONResponse) WithError(err error) JSONResponse

WithError adds error information to the JSONResponse. Returns a new JSONResponse with the Errors field populated.

func (JSONResponse) WithPagination

func (jr JSONResponse) WithPagination(queryOptions QueryOptions, totalData int) JSONResponse

WithPagination calculates and adds pagination metadata to the JSONResponse. It computes total pages and next/previous flags based on query options and total data count. Returns a new JSONResponse with pagination metadata included.

type JWTClaims added in v0.10.0

type JWTClaims struct {
	jwt.RegisteredClaims
	Data map[string]any `json:"data"` // Custom application data
}

JWTClaims represents the claims structure for JWT tokens. It extends jwt.RegisteredClaims with custom data payload for application-specific information.

type JWTService added in v0.10.0

type JWTService interface {
	// CreateToken generates a new JWT token with the provided data payload.
	CreateToken(data map[string]any) (string, error)
	// VerifyToken validates a JWT token string and returns the claims.
	VerifyToken(tokenstr string) (JWTClaims, error)
}

JWTService provides an interface for JWT token operations. It abstracts token creation and verification for different signing algorithms.

func NewJwtService added in v0.10.0

func NewJwtService(configs *Auth) JWTService

NewJwtService creates a new JWT service implementation using HMAC SHA256 signing. It uses the provided Auth configuration for token settings and validation.

type Logger added in v1.2.0

type Logger interface {
	Debug(args ...any)
	Info(args ...any)
	Warn(args ...any)
	Error(args ...any)
	Fatal(args ...any)
	Debugf(format string, args ...any)
	Infof(format string, args ...any)
	Warnf(format string, args ...any)
	Errorf(format string, args ...any)
	Fatalf(format string, args ...any)
}

func NewSimpleLogger added in v1.2.0

func NewSimpleLogger(namespace string, useColor bool, minLevel int) Logger

type Pagination

type Pagination struct {
	TotalData   int  `json:"totalData"`
	CurrentPage int  `json:"currentPage"`
	TotalPages  int  `json:"totalPages"`
	HasNextPage bool `json:"hasNextPage"`
	HasPrevPage bool `json:"hasPrevPage"`
}

Pagination contains metadata about paginated results. It provides information about the current page, total pages, and navigation flags.

func (*Pagination) IsZero

func (p *Pagination) IsZero() bool

IsZero checks if all pagination fields are at their zero values. Returns true if the pagination data is uninitialized or empty.

type QueryOptions

type QueryOptions struct {
	Page  int `query:"page" binding:"required,min=1"`
	Limit int `query:"limit" binding:"required,min=1"`
}

QueryOptions represents common pagination query parameters for HTTP requests. It includes validation tags to ensure proper values for page and limit parameters.

type RouteConfig

type RouteConfig struct {
	Group    string
	Versions []RouteVersionConfig
	Handlers []gin.HandlerFunc
}

RouteConfig represents a top-level route group configuration. It defines a route group with optional versioned subgroups and middleware handlers. Used by SetupRoutes to create hierarchical route structures.

type RouteGroupConfig

type RouteGroupConfig struct {
	Group     string
	Endpoints []EndpointConfig
	Handlers  []gin.HandlerFunc
}

RouteGroupConfig represents a route group within a versioned section. It contains individual endpoints and middleware handlers specific to this group. Groups help organize related endpoints under a common path prefix.

type RouteVersionConfig

type RouteVersionConfig struct {
	Version  int
	Groups   []RouteGroupConfig
	Handlers []gin.HandlerFunc
}

RouteVersionConfig represents a versioned route group within a RouteConfig. It contains version-specific route groups and middleware handlers. Versions are typically represented as integers (e.g., 1 for "/v1").

type SQLDB

type SQLDB struct {
	Host     string `required:"true"`
	User     string `required:"true"`
	Password string `required:"true"`
	Name     string `required:"true"`
	Port     string `required:"true"`
	Driver   string `required:"true"`
}

SQLDB holds SQL database connection parameters loaded from environment variables, including host, user credentials, database name, port, and driver type for GORM.

type Specification added in v1.0.0

type Specification[T any] struct {
	Model            T        // Model with fields set for WHERE conditions
	PreloadRelations []string // Relations to eager load
	ForUpdate        bool     // Whether to use SELECT ... FOR UPDATE
}

Specification defines query parameters for database operations. It includes the model for WHERE conditions, relations to preload, and locking options.

type Transactor

type Transactor interface {
	// Begin starts a new database transaction and returns a context containing the transaction.
	Begin(ctx context.Context) (context.Context, error)
	// Commit commits the current transaction in the context.
	Commit(ctx context.Context) error
	// Rollback rolls back the current transaction in the context without returning an error.
	Rollback(ctx context.Context)
	// WithinTransaction executes a service function within a database transaction.
	WithinTransaction(ctx context.Context, serviceFn func(ctx context.Context) error) error
}

Transactor provides an interface for managing database transactions with context. It abstracts transaction operations to allow for easier testing and different implementations.

func NewTransactor

func NewTransactor(db *gorm.DB) Transactor

NewTransactor creates a new Transactor implementation using GORM. The returned Transactor can be used to manage database transactions with context propagation.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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