feat: init project

This commit is contained in:
yanghao05
2025-08-05 17:26:59 +08:00
parent c5d621ad03
commit e034a2e54e
30 changed files with 5159 additions and 0 deletions

View File

@@ -0,0 +1,161 @@
package handler
import (
"fmt"
"log/slog"
"net/http"
"strconv"
"github.com/gofiber/fiber/v3"
"github.com/rogeecn/database_render/internal/service"
)
// DataHandler handles HTTP requests for data operations
type DataHandler struct {
service *service.DataService
logger *slog.Logger
}
// NewDataHandler creates a new data handler
func NewDataHandler(service *service.DataService) *DataHandler {
return &DataHandler{
service: service,
logger: slog.With("component", "handler"),
}
}
// GetTables returns all configured tables
func (h *DataHandler) GetTables(c fiber.Ctx) error {
tables, err := h.service.GetTables()
if err != nil {
h.logger.Error("failed to get tables", "error", err)
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"error": "Failed to get tables",
})
}
h.logger.Debug("retrieved tables", "count", len(tables))
return c.JSON(fiber.Map{
"tables": tables,
})
}
// GetTableData returns paginated data for a table
func (h *DataHandler) GetTableData(c fiber.Ctx) error {
tableName := c.Params("table")
if tableName == "" {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"error": "Table name is required",
})
}
// Parse query parameters
page, err := strconv.Atoi(c.Query("page", "1"))
if err != nil || page <= 0 {
page = 1
}
pageSize, err := strconv.Atoi(c.Query("per_page", "10"))
if err != nil || pageSize <= 0 {
pageSize = 10
}
search := c.Query("search", "")
sortField := c.Query("sort", "")
sortOrder := c.Query("order", "asc")
// Validate sort order
if sortOrder != "asc" && sortOrder != "desc" {
sortOrder = "asc"
}
// Get table data
data, err := h.service.GetTableData(tableName, page, pageSize, search, sortField, sortOrder)
if err != nil {
h.logger.Error("failed to get table data",
"table", tableName,
"page", page,
"error", err)
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"error": fmt.Sprintf("Failed to get table data: %v", err),
})
}
return c.JSON(data)
}
// GetTableDetail returns a single record detail
func (h *DataHandler) GetTableDetail(c fiber.Ctx) error {
tableName := c.Params("table")
if tableName == "" {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"error": "Table name is required",
})
}
id := c.Params("id")
if id == "" {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"error": "ID is required",
})
}
// Get table detail
detail, err := h.service.GetTableDetail(tableName, id)
if err != nil {
h.logger.Error("failed to get table detail",
"table", tableName,
"id", id,
"error", err)
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"error": fmt.Sprintf("Failed to get table detail: %v", err),
})
}
return c.JSON(detail)
}
// GetTableConfig returns the configuration for a specific table
func (h *DataHandler) GetTableConfig(c fiber.Ctx) error {
tableName := c.Params("table")
if tableName == "" {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
"error": "Table name is required",
})
}
config, err := h.service.GetTableConfig(tableName)
if err != nil {
h.logger.Error("failed to get table config",
"table", tableName,
"error", err)
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
"error": fmt.Sprintf("Failed to get table config: %v", err),
})
}
return c.JSON(config)
}
// Health returns the health status
func (h *DataHandler) Health(c fiber.Ctx) error {
return c.JSON(fiber.Map{
"status": "ok",
"message": "Service is healthy",
})
}
// SetupRoutes sets up all the routes for the data handler
func (h *DataHandler) SetupRoutes(app *fiber.App) {
// API routes
api := app.Group("/api")
// Table routes
api.Get("/tables", h.GetTables)
api.Get("/data/:table", h.GetTableData)
api.Get("/data/:table/detail/:id", h.GetTableDetail)
api.Get("/config/:table", h.GetTableConfig)
// Health check
api.Get("/health", h.Health)
}