package main import ( "errors" "flag" "fmt" "log/slog" "os" "github.com/gofiber/fiber/v2" fiblogger "github.com/gofiber/fiber/v2/middleware/logger" "github.com/gofiber/fiber/v2/middleware/recover" "xiangj-adapter/internal/apperror" "xiangj-adapter/internal/config" "xiangj-adapter/internal/controller" "xiangj-adapter/internal/db" "xiangj-adapter/internal/logger" "xiangj-adapter/internal/model" "xiangj-adapter/internal/router" "xiangj-adapter/internal/service" ) func main() { configPath := flag.String("config", "config.yaml", "config file path") flag.Parse() cfg, err := config.Load(*configPath) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } log, err := logger.New(logger.Options{ Level: cfg.Log.Level, Output: cfg.Log.Output, FilePath: cfg.Log.FilePath, }) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } pg, err := db.NewPostgres(db.PostgresConfig{ Address: cfg.Database.Address, Username: cfg.Database.Username, Password: cfg.Database.Password, Database: cfg.Database.Database, SSLMode: cfg.Database.SSLMode, MaxOpenConns: cfg.Database.MaxOpenConns, MaxIdleConns: cfg.Database.MaxIdleConns, ConnMaxLifetime: cfg.Database.ConnMaxLifetime, ConnMaxIdleTime: cfg.Database.ConnMaxIdleTime, }) if err != nil { log.Error("database init failed", "err", err) os.Exit(1) } defer pg.Close() app := fiber.New(fiber.Config{ ErrorHandler: func(c *fiber.Ctx, err error) error { return handleError(c, err, log) }, }) app.Use(recover.New()) app.Use(fiblogger.New()) dataService := service.NewDataService(pg, cfg.Database.Schema) dataController := controller.NewDataController(dataService, log) router.Register(app, dataController) log.Info("server starting", "address", cfg.Server.Address) if err := app.Listen(cfg.Server.Address); err != nil { log.Error("server stopped", "err", err) os.Exit(1) } } func handleError(c *fiber.Ctx, err error, log *slog.Logger) error { status := fiber.StatusInternalServerError message := "internal error" var appErr *apperror.AppError if errors.As(err, &appErr) { status = appErr.Status message = appErr.Message } else if fiberErr, ok := err.(*fiber.Error); ok { status = fiberErr.Code message = fiberErr.Message } log.Error("request failed", "status", status, "path", c.Path(), "err", err) return c.Status(status).JSON(model.APIResponse{Data: nil, Error: message}) }