Major changes: - Migrate all handlers from Gin to Echo framework - Add new apperrors, echohelpers, and validator packages - Update middleware for Echo compatibility - Add ArchivedHandler to task categorization chain (archived tasks go to cancelled_tasks column) - Add 6 new integration tests: - RecurringTaskLifecycle: NextDueDate advancement for weekly/monthly tasks - MultiUserSharing: Complex sharing with user removal - TaskStateTransitions: All state transitions and kanban column changes - DateBoundaryEdgeCases: Threshold boundary testing - CascadeOperations: Residence deletion cascade effects - MultiUserOperations: Shared residence collaboration - Add single-purpose repository functions for kanban columns (GetOverdueTasks, GetDueSoonTasks, etc.) - Fix RemoveUser route param mismatch (userId -> user_id) - Fix determineExpectedColumn helper to correctly prioritize in_progress over overdue 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
171 lines
4.9 KiB
Markdown
171 lines
4.9 KiB
Markdown
# Phase 4: Gin to Echo Handler Migration Status
|
|
|
|
## Completed Files
|
|
|
|
### ✅ auth_handler.go
|
|
- **Status**: Fully migrated
|
|
- **Methods migrated**: 13 methods
|
|
- Login, Register, Logout, CurrentUser, UpdateProfile
|
|
- VerifyEmail, ResendVerification
|
|
- ForgotPassword, VerifyResetCode, ResetPassword
|
|
- AppleSignIn, GoogleSignIn
|
|
- **Key changes applied**:
|
|
- Import changed from gin to echo
|
|
- Added validator import
|
|
- All handlers return error
|
|
- c.Bind + c.Validate pattern implemented
|
|
- c.MustGet → c.Get
|
|
- gin.H → map[string]interface{}
|
|
- c.Request.Context() → c.Request().Context()
|
|
- All c.JSON calls use `return`
|
|
|
|
## Remaining Files to Migrate
|
|
|
|
### 🔧 residence_handler.go
|
|
- **Status**: Partially migrated (needs cleanup)
|
|
- **Methods**: 13 methods
|
|
- **Issue**: Sed-based automated migration created syntax errors
|
|
- **Next steps**: Manual cleanup needed
|
|
|
|
### ⏳ task_handler.go
|
|
- **Methods**: ~17 methods
|
|
- **Complexity**: High (multipart form handling for completions)
|
|
- **Special considerations**:
|
|
- Has multipart/form-data handling in CreateCompletion
|
|
- Multiple lookup endpoints (categories, priorities, frequencies)
|
|
|
|
### ⏳ contractor_handler.go
|
|
- **Methods**: 8 methods
|
|
- **Complexity**: Medium
|
|
|
|
### ⏳ document_handler.go
|
|
- **Methods**: 8 methods
|
|
- **Complexity**: High (multipart form handling)
|
|
- **Special considerations**: File upload in CreateDocument
|
|
|
|
### ⏳ notification_handler.go
|
|
- **Methods**: 9 methods
|
|
- **Complexity**: Medium
|
|
- **Special considerations**: Query parameters for pagination
|
|
|
|
### ⏳ subscription_handler.go
|
|
- **Status**: Unknown
|
|
- **Estimated complexity**: Medium
|
|
|
|
### ⏳ upload_handler.go
|
|
- **Methods**: 4 methods
|
|
- **Complexity**: Medium
|
|
- **Special considerations**: c.FormFile handling, c.DefaultQuery
|
|
|
|
### ⏳ user_handler.go
|
|
- **Methods**: 3 methods
|
|
- **Complexity**: Low
|
|
|
|
### ⏳ media_handler.go
|
|
- **Status**: Unknown
|
|
- **Estimated complexity**: Medium
|
|
|
|
### ⏳ static_data_handler.go
|
|
- **Methods**: Unknown
|
|
- **Complexity**: Low (likely just lookups)
|
|
|
|
### ⏳ task_template_handler.go
|
|
- **Status**: Unknown
|
|
- **Estimated complexity**: Medium
|
|
|
|
### ⏳ tracking_handler.go
|
|
- **Status**: Unknown
|
|
- **Estimated complexity**: Low
|
|
|
|
### ⏳ subscription_webhook_handler.go
|
|
- **Status**: Unknown
|
|
- **Estimated complexity**: Medium-High (webhook handling)
|
|
|
|
## Migration Pattern
|
|
|
|
All handlers must follow these transformations:
|
|
|
|
```go
|
|
// BEFORE (Gin)
|
|
func (h *Handler) Method(c *gin.Context) {
|
|
user := c.MustGet(middleware.AuthUserKey).(*models.User)
|
|
|
|
var req requests.SomeRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(400, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
result, err := h.service.DoSomething(&req)
|
|
if err != nil {
|
|
c.JSON(500, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(200, result)
|
|
}
|
|
|
|
// AFTER (Echo)
|
|
func (h *Handler) Method(c echo.Context) error {
|
|
user := c.Get(middleware.AuthUserKey).(*models.User)
|
|
|
|
var req requests.SomeRequest
|
|
if err := c.Bind(&req); err != nil {
|
|
return c.JSON(400, map[string]interface{}{"error": err.Error()})
|
|
}
|
|
if err := c.Validate(&req); err != nil {
|
|
return c.JSON(400, validator.FormatValidationErrors(err))
|
|
}
|
|
|
|
result, err := h.service.DoSomething(&req)
|
|
if err != nil {
|
|
return c.JSON(500, map[string]interface{}{"error": err.Error()})
|
|
}
|
|
|
|
return c.JSON(200, result)
|
|
}
|
|
```
|
|
|
|
## Critical Context Changes
|
|
|
|
| Gin | Echo |
|
|
|-----|------|
|
|
| `c.MustGet()` | `c.Get()` |
|
|
| `c.ShouldBindJSON()` | `c.Bind()` + `c.Validate()` |
|
|
| `c.JSON(status, data)` | `return c.JSON(status, data)` |
|
|
| `c.Query("key")` | `c.QueryParam("key")` |
|
|
| `c.DefaultQuery("k", "v")` | Manual: `if v := c.QueryParam("k"); v != "" { } else { v = "default" }` |
|
|
| `c.PostForm("field")` | `c.FormValue("field")` |
|
|
| `c.GetHeader("X-...")` | `c.Request().Header.Get("X-...")` |
|
|
| `c.Request.Context()` | `c.Request().Context()` |
|
|
| `c.Status(code)` | `return c.NoContent(code)` |
|
|
| `gin.H{...}` | `map[string]interface{}{...}` |
|
|
|
|
## Multipart Form Handling
|
|
|
|
For handlers with file uploads (document_handler, task_handler):
|
|
|
|
```go
|
|
// Request parsing
|
|
c.Request.ParseMultipartForm(32 << 20) // Same
|
|
c.PostForm("field") → c.FormValue("field")
|
|
c.FormFile("file") // Same
|
|
```
|
|
|
|
## Next Steps
|
|
|
|
1. Clean up residence_handler.go manually
|
|
2. Migrate contractor_handler.go (simpler, good template)
|
|
3. Migrate smaller files: user_handler.go, upload_handler.go, notification_handler.go
|
|
4. Migrate complex files: task_handler.go, document_handler.go
|
|
5. Migrate remaining files
|
|
6. Test compilation
|
|
7. Update route registration (if not already done in Phase 3)
|
|
|
|
## Automation Lessons Learned
|
|
|
|
- Sed-based bulk replacements are error-prone for complex Go code
|
|
- Better approach: Manual migration with copy-paste for repetitive patterns
|
|
- Python script provided in migrate_handlers.py (not yet tested)
|
|
- Best approach: Methodical manual migration with validation at each step
|