package config import ( "bufio" "fmt" "os" "strconv" "strings" "time" ) type Config struct { AppHost string AppPort string DBHost string DBPort string DBDatabase string DBUsername string DBPassword string BearerToken string DBSettingsToken string DBMaxOpenConns int DBMaxIdleConns int DBConnMaxLifetime time.Duration DBDefaultRSCode string DBDefaultRSName string 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"), 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", ""), 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, DBDefaultRSCode: strings.ToUpper(strings.TrimSpace(env("DB_DEFAULT_RS_CODE", "AWALBROS_DEV"))), DBDefaultRSName: env("DB_DEFAULT_RS_NAME", "RS Dev Awalbros"), ManagementDBHost: env("CPONE_DB_HOST", env("DB_HOST", "127.0.0.1")), ManagementDBPort: env("CPONE_DB_PORT", env("DB_PORT", "3306")), ManagementDBDatabase: env("CPONE_DB_DATABASE", "cpone_middleware"), ManagementDBUsername: env("CPONE_DB_USERNAME", env("DB_USERNAME", "root")), ManagementDBPassword: env("CPONE_DB_PASSWORD", env("DB_PASSWORD", "")), DBCredentialSecret: env("CPONE_DATABASE_CREDENTIAL_KEY", env("CPONE_DATABASE_SETTINGS_TOKEN", env("CPONE_BEARER_TOKEN", ""))), } if cfg.DBDatabase == "" { return Config{}, fmt.Errorf("DB_DATABASE wajib diisi") } if cfg.BearerToken == "" { return Config{}, fmt.Errorf("CPONE_BEARER_TOKEN wajib diisi") } if cfg.DBDefaultRSCode == "" { return Config{}, fmt.Errorf("DB_DEFAULT_RS_CODE 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 != "" { _ = 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 }