package main import ( "fmt" "log" "net/http" "time" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/go-chi/httprate" "github.com/jmoiron/sqlx" "github.com/joho/godotenv" "emly-api-go/internal/config" "emly-api-go/internal/database" "emly-api-go/internal/database/schema" "emly-api-go/internal/routes" ) func main() { // Load .env (ignored if not present in production) _ = godotenv.Load() cfg := config.Load() db, err := database.Connect(cfg) if err != nil { log.Fatalf("database connection failed: %v", err) } defer func(db *sqlx.DB) { err := db.Close() if err != nil { log.Fatalf("closing database failed: %v", err) } }(db) // Run conditional schema migrations if err := schema.Migrate(db, cfg.Database); err != nil { log.Fatalf("schema migration failed: %v", err) } r := chi.NewRouter() // Global middlewares r.Use(middleware.RequestID) r.Use(middleware.RealIP) r.Use(middleware.Logger) r.Use(middleware.Recoverer) r.Use(middleware.Timeout(30 * time.Second)) // Global rate limit to 100 requests per minute r.Use(httprate.LimitByIP(100, time.Minute)) routes.RegisterAll(r, db) addr := fmt.Sprintf(":%s", cfg.Port) log.Printf("server listening on %s", addr) if err := http.ListenAndServe(addr, r); err != nil { log.Fatalf("server error: %v", err) } }