package config import ( "bufio" "fmt" "os" "strconv" "strings" "time" ) type Config struct { AppHost string AppPort string BearerToken string DBSettingsToken string DBMaxOpenConns int DBMaxIdleConns int DBConnMaxLifetime time.Duration ManagementDBHost string ManagementDBPort string ManagementDBDatabase string ManagementDBUsername string ManagementDBPassword string DBCredentialSecret string } 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"), BearerToken: env("CPONE_BEARER_TOKEN", ""), DBSettingsToken: env("CPONE_DATABASE_SETTINGS_TOKEN", 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, ManagementDBHost: env("CPONE_DB_HOST", "127.0.0.1"), ManagementDBPort: env("CPONE_DB_PORT", "3306"), ManagementDBDatabase: env("CPONE_DB_DATABASE", "cpone_middleware"), ManagementDBUsername: env("CPONE_DB_USERNAME", "root"), ManagementDBPassword: env("CPONE_DB_PASSWORD", ""), DBCredentialSecret: env("CPONE_DATABASE_CREDENTIAL_KEY", env("CPONE_DATABASE_SETTINGS_TOKEN", env("CPONE_BEARER_TOKEN", ""))), } if cfg.BearerToken == "" { return Config{}, fmt.Errorf("CPONE_BEARER_TOKEN wajib diisi") } if cfg.ManagementDBDatabase == "" { return Config{}, fmt.Errorf("CPONE_DB_DATABASE wajib diisi") } return cfg, nil } func (c Config) Addr() string { return c.AppHost + ":" + c.AppPort } 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 != "" { if _, alreadySet := os.LookupEnv(key); !alreadySet { _ = 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 }