From 7eb25718dbea908ca8409c209d22e74a7b3ada88 Mon Sep 17 00:00:00 2001 From: bagas Date: Sun, 22 Feb 2026 02:23:48 +0700 Subject: [PATCH] feat: add config loader --- internal/config/config.go | 74 +++++++++++++++++++++++++++++++++++++++ internal/server/server.go | 6 ++-- main.go | 23 ++++-------- 3 files changed, 84 insertions(+), 19 deletions(-) create mode 100644 internal/config/config.go diff --git a/internal/config/config.go b/internal/config/config.go new file mode 100644 index 0000000..1fc9999 --- /dev/null +++ b/internal/config/config.go @@ -0,0 +1,74 @@ +package config + +import ( + "fmt" + "os" + + "github.com/joho/godotenv" +) + +type Config interface { + Addr() string + Port() string + DatabaseURL() string +} +type config struct { + addr string + port string + databaseURL string +} + +func (c *config) Addr() string { + return c.addr +} + +func (c *config) Port() string { + return c.port +} + +func (c *config) DatabaseURL() string { + return c.databaseURL +} + +func parse() (*config, error) { + domain := getenv("ADDRESS", "0.0.0.0") + sshPort := getenv("PORT", "8080") + databaseURL := getenv("DATABASE_URL", "") + + if databaseURL == "" { + return nil, fmt.Errorf("DATABASE_URL environment variable not set") + } + + return &config{ + addr: domain, + port: sshPort, + databaseURL: databaseURL, + }, nil +} + +func loadEnvFile() error { + if _, err := os.Stat(".env"); err == nil { + return godotenv.Load(".env") + } + return nil +} + +func getenv(key, def string) string { + if v := os.Getenv(key); v != "" { + return v + } + return def +} + +func MustLoad() (Config, error) { + if err := loadEnvFile(); err != nil { + return nil, err + } + + cfg, err := parse() + if err != nil { + return nil, err + } + + return cfg, nil +} diff --git a/internal/server/server.go b/internal/server/server.go index 2755f84..f5c379a 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -11,12 +11,12 @@ import ( type Server struct { addr string - port uint16 + port string repository *repository.Queries jwt *jwt.JWT } -func New(addr string, port uint16, repository *repository.Queries, jwt *jwt.JWT) *Server { +func New(addr string, port string, repository *repository.Queries, jwt *jwt.JWT) *Server { return &Server{ addr: addr, port: port, @@ -55,7 +55,7 @@ func router(repository *repository.Queries, jwt *jwt.JWT) *http.ServeMux { func (s *Server) Start() error { r := router(s.repository, s.jwt) hs := &http.Server{ - Addr: fmt.Sprintf("%s:%d", s.addr, s.port), + Addr: fmt.Sprintf("%s:%s", s.addr, s.port), Handler: middleware.Handler(middleware.CORS(r)), } diff --git a/main.go b/main.go index e61924e..f7d6a83 100644 --- a/main.go +++ b/main.go @@ -5,23 +5,22 @@ import ( "log" "os" "os/signal" + "ristek-task-be/internal/config" "ristek-task-be/internal/db/sqlc/repository" "ristek-task-be/internal/jwt" "ristek-task-be/internal/server" "syscall" "github.com/jackc/pgx/v5/pgxpool" - "github.com/joho/godotenv" ) func main() { log.SetOutput(os.Stdout) log.SetFlags(log.LstdFlags | log.Lshortfile) - if _, err := os.Stat(".env"); err == nil { - if err = godotenv.Load(".env"); err != nil { - log.Printf("Warning: Failed to load .env file: %s", err) - } + conf, err := config.MustLoad() + if err != nil { + log.Fatalf("failed to load config: %s", err) } errChan := make(chan error, 1) @@ -29,18 +28,10 @@ func main() { signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM) - addr := "localhost" - port := uint16(8080) - - dbURL := os.Getenv("DATABASE_URL") - if dbURL == "" { - log.Fatal("DATABASE_URL is required") - } - ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer cancel() - connect, err := pgxpool.New(ctx, dbURL) + connect, err := pgxpool.New(ctx, conf.DatabaseURL()) if err != nil { panic(err) } @@ -48,12 +39,12 @@ func main() { repo := repository.New(connect) j := jwt.New("yomama") go func() { - s := server.New(addr, port, repo, j) + s := server.New(conf.Addr(), conf.Port(), repo, j) err = s.Start() errChan <- err }() - log.Printf("Server is running on %s:%d", addr, port) + log.Printf("Server is running on %s:%s", conf.Addr(), conf.Port()) select { case err = <-errChan: