Initialize base
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user