package app import ( "fmt" "os" "path/filepath" "time" ) type Config struct { AppEnv string HTTPAddr string DatabaseURL string JWTIssuer string JWTAccessSecret string JWTAccessTTL time.Duration RefreshTTL time.Duration SMSCodeTTL time.Duration SMSCodeCooldown time.Duration SMSProvider string DevSMSCode string WechatMiniAppID string WechatMiniSecret string WechatMiniDevPrefix string LocalEventDir string AssetBaseURL string AssetPublicBaseURL string AssetBucketRoot string OSSUtilPath string OSSUtilConfigFile string } func LoadConfigFromEnv() (Config, error) { cfg := Config{ AppEnv: getEnv("APP_ENV", "development"), HTTPAddr: getEnv("HTTP_ADDR", ":8080"), DatabaseURL: os.Getenv("DATABASE_URL"), JWTIssuer: getEnv("JWT_ISSUER", "cmr-backend"), JWTAccessSecret: getEnv("JWT_ACCESS_SECRET", "change-me-in-production"), JWTAccessTTL: getDurationEnv("JWT_ACCESS_TTL", 2*time.Hour), RefreshTTL: getDurationEnv("AUTH_REFRESH_TTL", 30*24*time.Hour), SMSCodeTTL: getDurationEnv("AUTH_SMS_CODE_TTL", 10*time.Minute), SMSCodeCooldown: getDurationEnv("AUTH_SMS_COOLDOWN", 60*time.Second), SMSProvider: getEnv("AUTH_SMS_PROVIDER", "console"), DevSMSCode: os.Getenv("AUTH_DEV_SMS_CODE"), WechatMiniAppID: getEnv("WECHAT_MINI_APP_ID", ""), WechatMiniSecret: getEnv("WECHAT_MINI_APP_SECRET", ""), WechatMiniDevPrefix: getEnv("WECHAT_MINI_DEV_PREFIX", "dev-"), LocalEventDir: getEnv("LOCAL_EVENT_DIR", filepath.Clean("..\\event")), AssetBaseURL: getEnv("ASSET_BASE_URL", "https://oss-mbh5.colormaprun.com/gotomars"), AssetPublicBaseURL: getEnv("ASSET_PUBLIC_BASE_URL", "https://oss-mbh5.colormaprun.com"), AssetBucketRoot: getEnv("ASSET_BUCKET_ROOT", "oss://color-map-html"), OSSUtilPath: getEnv("OSSUTIL_PATH", filepath.Clean("..\\tools\\ossutil.exe")), OSSUtilConfigFile: getEnv("OSSUTIL_CONFIG_FILE", filepath.Join(mustUserHomeDir(), ".ossutilconfig")), } if cfg.DatabaseURL == "" { return Config{}, fmt.Errorf("DATABASE_URL is required") } if cfg.JWTAccessSecret == "" { return Config{}, fmt.Errorf("JWT_ACCESS_SECRET is required") } return cfg, nil } func getEnv(key, fallback string) string { if value := os.Getenv(key); value != "" { return value } return fallback } func getDurationEnv(key string, fallback time.Duration) time.Duration { if value := os.Getenv(key); value != "" { if parsed, err := time.ParseDuration(value); err == nil { return parsed } } return fallback } func mustUserHomeDir() string { home, err := os.UserHomeDir() if err != nil { return "." } return home }