Files
honeyDueAPI/MIGRATION_STATUS.md
Trey t 6dac34e373 Migrate from Gin to Echo framework and add comprehensive integration tests
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>
2025-12-16 13:52:08 -06:00

4.9 KiB

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:

// 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):

// 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