package config import ( "bufio" "fmt" "net/url" "os" "strconv" "strings" "time" ) type Config struct { AppHost string AppPort string DBHost string DBPort string DBDatabase string DBUsername string DBPassword string BearerToken string DBMaxOpenConns int DBMaxIdleConns int DBConnMaxLifetime time.Duration } func Load(path string) (Config, error) { if err := loadDotEnv(path); err != nil { return Config{}, err } cfg := Config{ AppHost: env("APP_HOST", "0.0.0.0"), AppPort: env("APP_PORT", "8080"), DBHost: env("DB_HOST", "127.0.0.1"), DBPort: env("DB_PORT", "3306"), DBDatabase: env("DB_DATABASE", ""), DBUsername: env("DB_USERNAME", "root"), DBPassword: env("DB_PASSWORD", ""), BearerToken: env("CPONE_BEARER_TOKEN", ""), DBMaxOpenConns: envInt("DB_MAX_OPEN_CONNS", 25), DBMaxIdleConns: envInt("DB_MAX_IDLE_CONNS", 25), DBConnMaxLifetime: time.Duration(envInt("DB_CONN_MAX_LIFETIME_MINUTES", 5)) * time.Minute, } if cfg.DBDatabase == "" { return Config{}, fmt.Errorf("DB_DATABASE wajib diisi") } if cfg.BearerToken == "" { return Config{}, fmt.Errorf("CPONE_BEARER_TOKEN wajib diisi") } return cfg, nil } func (c Config) Addr() string { return c.AppHost + ":" + c.AppPort } func (c Config) MySQLDSN() string { values := url.Values{} values.Set("charset", "utf8mb4") values.Set("parseTime", "true") values.Set("loc", "Local") return fmt.Sprintf( "%s:%s@tcp(%s:%s)/%s?%s", c.DBUsername, c.DBPassword, c.DBHost, c.DBPort, c.DBDatabase, values.Encode(), ) } func loadDotEnv(path string) error { file, err := os.Open(path) if err != nil { if os.IsNotExist(err) { return nil } return err } defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) if line == "" || strings.HasPrefix(line, "#") { continue } key, value, ok := strings.Cut(line, "=") if !ok { continue } key = strings.TrimSpace(key) value = strings.TrimSpace(value) value = strings.Trim(value, `"'`) if key != "" { _ = os.Setenv(key, value) } } return scanner.Err() } func env(key string, fallback string) string { value := os.Getenv(key) if value == "" { return fallback } return value } func envInt(key string, fallback int) int { value := os.Getenv(key) if value == "" { return fallback } parsed, err := strconv.Atoi(value) if err != nil { return fallback } return parsed }