Initialize base

This commit is contained in:
hdbar
2025-07-27 16:20:21 +03:30
commit ad9db7bcce
31 changed files with 8268 additions and 0 deletions
+717
View File
@@ -0,0 +1,717 @@
---
alwaysApply: true
---
# Cursor Rules for Tender Management Go Backend
## Project Context
This is a Go backend API for a tender management system following Clean Architecture principles with minimal complexity, designed to be AI-friendly and easy to maintain.
## 🏗️ Architecture Guidelines
### Clean Architecture Layers
- **Domain Layer** (`internal/domain/`): Business entities, interfaces, and core business rules
- **Service Layer** (`internal/service/`): Business logic and use cases
- **Handler Layer** (`internal/handler/`): HTTP controllers and request/response handling
- **Repository Layer** (`internal/repository/`): Data access implementations
- **Infrastructure Layer** (`internal/infrastructure/`): External dependencies (DB, cache, queues)
### Dependency Rules
- Always depend on interfaces, not concrete implementations
- Use dependency injection through constructors
- Inner layers should never depend on outer layers
- All dependencies flow inward toward the domain
## 💻 Go Best Practices
### Code Structure
- Use standard Go project layout with `internal/` for private code
- Group related functionality in packages
- Keep packages focused on single responsibility
- Use meaningful package names (not generic like `utils` or `helpers`)
### Naming Conventions
- Use Go naming conventions: camelCase for private, PascalCase for public
- Interface names should describe what they do (e.g., `UserRepository`, `AuthService`)
- Use descriptive variable names, avoid abbreviations
- Constants should be in ALL_CAPS with underscores
### Error Handling
- Always handle errors explicitly, never ignore them
- Use structured error messages with context
- Wrap errors with additional context using `fmt.Errorf("context: %w", err)`
- Log errors at the point they occur with relevant fields
- Return domain-specific error types when appropriate
### Function Design
- Keep functions small and focused (max 20-30 lines)
- Use early returns to reduce nesting
- Validate inputs at function entry points
- Use descriptive parameter names
- Limit function parameters (max 3-4, use structs for more)
## 🔌 Interface Design
### Repository Interfaces
- Always create interfaces in the domain layer
- Use context.Context as first parameter for all methods
- Return domain entities, not database models
- Include common operations: Create, GetByID, Update, Delete, List
- Use specific query methods (e.g., `GetByEmail`, `GetActiveUsers`)
### Service Interfaces
- Define business operations clearly
- Use request/response DTOs for complex operations
- Include validation in service methods
- Handle business logic, not infrastructure concerns
## 📝 Logging Standards
### Using Zap Logger
- Always use structured logging with fields
- Include relevant context (user_id, request_id, etc.)
- Use appropriate log levels:
- `Debug`: Detailed debugging information
- `Info`: General operational messages
- `Warn`: Warning conditions that should be addressed
- `Error`: Error conditions that need attention
- `Fatal`: Critical errors that cause program termination
### Logging Examples
```go
// Good
log.Info("User authenticated successfully", map[string]interface{}{
"user_id": user.ID.String(),
"email": user.Email,
"ip": clientIP,
})
// Bad
log.Info("User login")
```
### Error Logging
- Log errors with full context
- Include error details and relevant fields
- Don't log the same error multiple times in the call stack
## 🗄️ Database & Repository Patterns
### Repository Implementation
- Implement repository interfaces in `internal/repository/`
- Use proper database transactions for related operations
- Handle database errors gracefully
- Use prepared statements or ORM query builders
- Implement proper pagination
### Data Models
- Separate database models from domain entities
- Convert between database models and domain entities in repositories
- Use proper database field tags (bson, json)
- Include audit fields (created_at, updated_at)
## 🌐 HTTP Handler Guidelines
### Request Handling
- Validate all incoming requests using struct tags
- Use proper HTTP status codes
- Return consistent API response format using `pkg/response`
- Handle CORS appropriately
- Include request timeout handling
### Response Format
- Always use standardized response structure from `pkg/response`
- Include appropriate metadata for paginated responses
- Provide meaningful error messages
- Never expose internal errors to clients
### Security
- Validate and sanitize all inputs
- Use proper authentication middleware
- Implement rate limiting
- Never log sensitive information (passwords, tokens)
- Use HTTPS in production
## 🧪 Testing Guidelines
### Test Structure
- Write unit tests for all business logic
- Use table-driven tests for multiple scenarios
- Mock external dependencies using interfaces
- Test error cases, not just happy paths
- Use meaningful test names that describe the scenario
### Test Organization
- Place tests in same package as code being tested
- Use `_test.go` suffix for test files
- Create test utilities in `testutil` package if needed
- Use setup/teardown functions for common test data
## 📋 Configuration Management
### Configuration Files
- Use YAML for configuration files
- Support environment variable overrides
- Validate configuration on startup
- Use default values for optional settings
- Document all configuration options
### Environment Variables
- Use consistent naming convention (e.g., `TM_DATABASE_URI`)
- Never commit secrets in configuration files
- Use different configs for different environments
## 🚀 Performance Guidelines
### Optimization
- Use database indexes appropriately
- Implement caching for frequently accessed data
- Use connection pooling for databases
- Avoid N+1 queries
- Profile performance bottlenecks
### Memory Management
- Close resources properly (database connections, files)
- Use context for cancellation and timeouts
- Avoid memory leaks in goroutines
- Use sync.Pool for frequently allocated objects
## 📚 Documentation Standards
### Code Documentation
- Write clear comments for complex business logic
- Document all public interfaces and types
- Use Go doc comments format
- Include examples for complex functions
- Keep comments up to date with code changes
### API Documentation
- Use OpenAPI/Swagger annotations
- Document all endpoints with examples
- Include error response examples
- Document authentication requirements
## 🔐 Security Best Practices
### Authentication & Authorization
- Use JWT tokens with proper expiration
- Implement refresh token rotation
- Use bcrypt for password hashing
- Validate token claims properly
- Implement proper RBAC
### Input Validation
- Validate all inputs at API boundaries
- Use whitelist validation, not blacklist
- Sanitize inputs to prevent injection attacks
- Validate file uploads properly
## 📦 Dependency Management
### Go Modules
- Keep go.mod clean and organized
- Pin major versions for stability
- Regular dependency updates with testing
- Remove unused dependencies
- Use vendor directory for critical dependencies
### External Libraries
- Prefer standard library when possible
- Choose well-maintained libraries
- Avoid dependencies with security issues
- Keep dependencies minimal
## 🔄 Code Review Guidelines
### Before Committing
- Run `go fmt`, `go vet`, and linting tools
- Ensure all tests pass
- Check for proper error handling
- Verify logging is appropriate
- Confirm no sensitive data is exposed
### Code Quality
- Follow single responsibility principle
- Avoid code duplication
- Use meaningful variable names
- Keep functions and files reasonably sized
- Maintain consistent code style
## 🚨 Error Patterns to Avoid
### Anti-patterns
- Don't use panic for regular error handling
- Avoid global variables for application state
- Don't ignore context cancellation
- Avoid deeply nested if statements
- Don't use reflection unless absolutely necessary
### Common Mistakes
- Not handling database connection errors
- Forgetting to close resources
- Not validating user inputs
- Exposing internal errors to clients
- Not using proper HTTP status codes
## 📋 Checklist for New Features
### Before Implementation
- [ ] Define interfaces in domain layer
- [ ] Create proper request/response DTOs
- [ ] Plan error handling strategy
- [ ] Design database schema if needed
- [ ] Consider caching requirements
### During Implementation
- [ ] Follow clean architecture layers
- [ ] Use dependency injection
- [ ] Implement proper logging
- [ ] Add input validation
- [ ] Handle errors gracefully
### After Implementation
- [ ] Write unit tests
- [ ] Update API documentation
- [ ] Test error scenarios
- [ ] Verify security implications
- [ ] Check performance impact
## 🎯 Code Examples
### Service Implementation Template
```go
type UserServiceImpl struct {
userRepo domain.UserRepository
logger logger.Logger
}
func NewUserService(userRepo domain.UserRepository, logger logger.Logger) domain.UserService {
return &UserServiceImpl{
userRepo: userRepo,
logger: logger,
}
}
func (s *UserServiceImpl) CreateUser(ctx context.Context, req domain.CreateUserRequest) (*domain.User, error) {
// Validate input
if err := validateCreateUserRequest(req); err != nil {
return nil, fmt.Errorf("invalid request: %w", err)
}
// Business logic
user := &domain.User{
ID: uuid.New(),
Email: req.Email,
// ... other fields
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
// Repository call
if err := s.userRepo.Create(ctx, user); err != nil {
s.logger.Error("Failed to create user", map[string]interface{}{
"error": err.Error(),
"email": req.Email,
})
return nil, fmt.Errorf("failed to create user: %w", err)
}
s.logger.Info("User created successfully", map[string]interface{}{
"user_id": user.ID.String(),
"email": user.Email,
})
return user, nil
}
```
### Handler Implementation Template
```go
func (h *UserHandler) CreateUser(c echo.Context) error {
var req domain.CreateUserRequest
// Bind and validate request
if err := c.Bind(&req); err != nil {
return response.BadRequest(c, "Invalid request format", err.Error())
}
if err := h.validator.Struct(&req); err != nil {
return response.ValidationError(c, "Validation failed", err.Error())
}
// Call service
user, err := h.userService.CreateUser(c.Request().Context(), req)
if err != nil {
h.logger.Error("Create user failed", map[string]interface{}{
"error": err.Error(),
"email": req.Email,
})
return response.InternalServerError(c, "Failed to create user")
}
return response.Created(c, user, "User created successfully")
}
```
## 🚀 Remember
- Prioritize simplicity and readability over cleverness
- Make code self-documenting through clear naming
- Always consider the person who will maintain this code
- Test your code thoroughly
- Security and performance are not optional # Cursor Rules for Tender Management Go Backend
## Project Context
This is a Go backend API for a tender management system following Clean Architecture principles with minimal complexity, designed to be AI-friendly and easy to maintain.
## 🏗️ Architecture Guidelines
### Clean Architecture Layers
- **Domain Layer** (`internal/domain/`): Business entities, interfaces, and core business rules
- **Service Layer** (`internal/service/`): Business logic and use cases
- **Handler Layer** (`internal/handler/`): HTTP controllers and request/response handling
- **Repository Layer** (`internal/repository/`): Data access implementations
- **Infrastructure Layer** (`internal/infrastructure/`): External dependencies (DB, cache, queues)
### Dependency Rules
- Always depend on interfaces, not concrete implementations
- Use dependency injection through constructors
- Inner layers should never depend on outer layers
- All dependencies flow inward toward the domain
## 💻 Go Best Practices
### Code Structure
- Use standard Go project layout with `internal/` for private code
- Group related functionality in packages
- Keep packages focused on single responsibility
- Use meaningful package names (not generic like `utils` or `helpers`)
### Naming Conventions
- Use Go naming conventions: camelCase for private, PascalCase for public
- Interface names should describe what they do (e.g., `UserRepository`, `AuthService`)
- Use descriptive variable names, avoid abbreviations
- Constants should be in ALL_CAPS with underscores
### Error Handling
- Always handle errors explicitly, never ignore them
- Use structured error messages with context
- Wrap errors with additional context using `fmt.Errorf("context: %w", err)`
- Log errors at the point they occur with relevant fields
- Return domain-specific error types when appropriate
### Function Design
- Keep functions small and focused (max 20-30 lines)
- Use early returns to reduce nesting
- Validate inputs at function entry points
- Use descriptive parameter names
- Limit function parameters (max 3-4, use structs for more)
## 🔌 Interface Design
### Repository Interfaces
- Always create interfaces in the domain layer
- Use context.Context as first parameter for all methods
- Return domain entities, not database models
- Include common operations: Create, GetByID, Update, Delete, List
- Use specific query methods (e.g., `GetByEmail`, `GetActiveUsers`)
### Service Interfaces
- Define business operations clearly
- Use request/response DTOs for complex operations
- Include validation in service methods
- Handle business logic, not infrastructure concerns
## 📝 Logging Standards
### Using Zap Logger
- Always use structured logging with fields
- Include relevant context (user_id, request_id, etc.)
- Use appropriate log levels:
- `Debug`: Detailed debugging information
- `Info`: General operational messages
- `Warn`: Warning conditions that should be addressed
- `Error`: Error conditions that need attention
- `Fatal`: Critical errors that cause program termination
### Logging Examples
```go
// Good
log.Info("User authenticated successfully", map[string]interface{}{
"user_id": user.ID.String(),
"email": user.Email,
"ip": clientIP,
})
// Bad
log.Info("User login")
```
### Error Logging
- Log errors with full context
- Include error details and relevant fields
- Don't log the same error multiple times in the call stack
## 🗄️ Database & Repository Patterns
### Repository Implementation
- Implement repository interfaces in `internal/repository/`
- Use proper database transactions for related operations
- Handle database errors gracefully
- Use prepared statements or ORM query builders
- Implement proper pagination
### Data Models
- Separate database models from domain entities
- Convert between database models and domain entities in repositories
- Use proper database field tags (bson, json)
- Include audit fields (created_at, updated_at)
## 🌐 HTTP Handler Guidelines
### Request Handling
- Validate all incoming requests using struct tags
- Use proper HTTP status codes
- Return consistent API response format using `pkg/response`
- Handle CORS appropriately
- Include request timeout handling
### Response Format
- Always use standardized response structure from `pkg/response`
- Include appropriate metadata for paginated responses
- Provide meaningful error messages
- Never expose internal errors to clients
### Security
- Validate and sanitize all inputs
- Use proper authentication middleware
- Implement rate limiting
- Never log sensitive information (passwords, tokens)
- Use HTTPS in production
## 🧪 Testing Guidelines
### Test Structure
- Write unit tests for all business logic
- Use table-driven tests for multiple scenarios
- Mock external dependencies using interfaces
- Test error cases, not just happy paths
- Use meaningful test names that describe the scenario
### Test Organization
- Place tests in same package as code being tested
- Use `_test.go` suffix for test files
- Create test utilities in `testutil` package if needed
- Use setup/teardown functions for common test data
## 📋 Configuration Management
### Configuration Files
- Use YAML for configuration files
- Support environment variable overrides
- Validate configuration on startup
- Use default values for optional settings
- Document all configuration options
### Environment Variables
- Use consistent naming convention (e.g., `TM_DATABASE_URI`)
- Never commit secrets in configuration files
- Use different configs for different environments
## 🚀 Performance Guidelines
### Optimization
- Use database indexes appropriately
- Implement caching for frequently accessed data
- Use connection pooling for databases
- Avoid N+1 queries
- Profile performance bottlenecks
### Memory Management
- Close resources properly (database connections, files)
- Use context for cancellation and timeouts
- Avoid memory leaks in goroutines
- Use sync.Pool for frequently allocated objects
## 📚 Documentation Standards
### Code Documentation
- Write clear comments for complex business logic
- Document all public interfaces and types
- Use Go doc comments format
- Include examples for complex functions
- Keep comments up to date with code changes
### API Documentation
- Use OpenAPI/Swagger annotations
- Document all endpoints with examples
- Include error response examples
- Document authentication requirements
## 🔐 Security Best Practices
### Authentication & Authorization
- Use JWT tokens with proper expiration
- Implement refresh token rotation
- Use bcrypt for password hashing
- Validate token claims properly
- Implement proper RBAC
### Input Validation
- Validate all inputs at API boundaries
- Use whitelist validation, not blacklist
- Sanitize inputs to prevent injection attacks
- Validate file uploads properly
## 📦 Dependency Management
### Go Modules
- Keep go.mod clean and organized
- Pin major versions for stability
- Regular dependency updates with testing
- Remove unused dependencies
- Use vendor directory for critical dependencies
### External Libraries
- Prefer standard library when possible
- Choose well-maintained libraries
- Avoid dependencies with security issues
- Keep dependencies minimal
## 🔄 Code Review Guidelines
### Before Committing
- Run `go fmt`, `go vet`, and linting tools
- Ensure all tests pass
- Check for proper error handling
- Verify logging is appropriate
- Confirm no sensitive data is exposed
### Code Quality
- Follow single responsibility principle
- Avoid code duplication
- Use meaningful variable names
- Keep functions and files reasonably sized
- Maintain consistent code style
## 🚨 Error Patterns to Avoid
### Anti-patterns
- Don't use panic for regular error handling
- Avoid global variables for application state
- Don't ignore context cancellation
- Avoid deeply nested if statements
- Don't use reflection unless absolutely necessary
### Common Mistakes
- Not handling database connection errors
- Forgetting to close resources
- Not validating user inputs
- Exposing internal errors to clients
- Not using proper HTTP status codes
## 📋 Checklist for New Features
### Before Implementation
- [ ] Define interfaces in domain layer
- [ ] Create proper request/response DTOs
- [ ] Plan error handling strategy
- [ ] Design database schema if needed
- [ ] Consider caching requirements
### During Implementation
- [ ] Follow clean architecture layers
- [ ] Use dependency injection
- [ ] Implement proper logging
- [ ] Add input validation
- [ ] Handle errors gracefully
### After Implementation
- [ ] Write unit tests
- [ ] Update API documentation
- [ ] Test error scenarios
- [ ] Verify security implications
- [ ] Check performance impact
## 🎯 Code Examples
### Service Implementation Template
```go
type UserServiceImpl struct {
userRepo domain.UserRepository
logger logger.Logger
}
func NewUserService(userRepo domain.UserRepository, logger logger.Logger) domain.UserService {
return &UserServiceImpl{
userRepo: userRepo,
logger: logger,
}
}
func (s *UserServiceImpl) CreateUser(ctx context.Context, req domain.CreateUserRequest) (*domain.User, error) {
// Validate input
if err := validateCreateUserRequest(req); err != nil {
return nil, fmt.Errorf("invalid request: %w", err)
}
// Business logic
user := &domain.User{
ID: uuid.New(),
Email: req.Email,
// ... other fields
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
// Repository call
if err := s.userRepo.Create(ctx, user); err != nil {
s.logger.Error("Failed to create user", map[string]interface{}{
"error": err.Error(),
"email": req.Email,
})
return nil, fmt.Errorf("failed to create user: %w", err)
}
s.logger.Info("User created successfully", map[string]interface{}{
"user_id": user.ID.String(),
"email": user.Email,
})
return user, nil
}
```
### Handler Implementation Template
```go
func (h *UserHandler) CreateUser(c echo.Context) error {
var req domain.CreateUserRequest
// Bind and validate request
if err := c.Bind(&req); err != nil {
return response.BadRequest(c, "Invalid request format", err.Error())
}
if err := h.validator.Struct(&req); err != nil {
return response.ValidationError(c, "Validation failed", err.Error())
}
// Call service
user, err := h.userService.CreateUser(c.Request().Context(), req)
if err != nil {
h.logger.Error("Create user failed", map[string]interface{}{
"error": err.Error(),
"email": req.Email,
})
return response.InternalServerError(c, "Failed to create user")
}
return response.Created(c, user, "User created successfully")
}
```
## 🚀 Remember
- Prioritize simplicity and readability over cleverness
- Make code self-documenting through clear naming
- Always consider the person who will maintain this code
- Test your code thoroughly
- Security and performance are not optional