// Package config loads runtime settings from the environment. package config import ( "os" "strconv" "time" ) type Config struct { // Storage: "postgres" (default) or "memory" (no infra, for dev/tests). Store string DatabaseURL string RedisAddr string RedisPassword string RedisDB int RedisKeyPrefix string // PublicURL is the externally reachable base (used to build OAuth callback // URLs). PostLoginRedirect is where users land after a successful login. PublicURL string PostLoginRedirect string // FrontendDist is the directory of the built SPA served by the frontend cmd. FrontendDist string // ShortDomain is the display host for short links (e.g. snip.to). ShortDomain string SessionSecret string CookieSecure bool // Identity providers (each optional; absent => that login button is hidden). GoogleClientID string GoogleClientSecret string OIDCIssuer string OIDCClientID string OIDCClientSecret string ClickFlushInterval time.Duration } func env(key, def string) string { if v := os.Getenv(key); v != "" { return v } return def } func envBool(key string, def bool) bool { if v := os.Getenv(key); v != "" { b, err := strconv.ParseBool(v) if err == nil { return b } } return def } func envInt(key string, def int) int { if v := os.Getenv(key); v != "" { n, err := strconv.Atoi(v) if err == nil { return n } } return def } // Load reads configuration from the environment with sensible local defaults. func Load() Config { flush := time.Duration(envInt("CLICK_FLUSH_SECONDS", 10)) * time.Second return Config{ Store: env("STORE", "postgres"), DatabaseURL: env("DATABASE_URL", "postgres://snip:snip@localhost:5432/snip?sslmode=disable"), RedisAddr: env("REDIS_ADDR", "localhost:6379"), RedisPassword: env("REDIS_PASSWORD", ""), RedisDB: envInt("REDIS_DB", 0), RedisKeyPrefix: env("REDIS_KEY_PREFIX", ""), PublicURL: env("PUBLIC_URL", "http://localhost:8080"), PostLoginRedirect: env("POST_LOGIN_REDIRECT", "/dashboard"), FrontendDist: env("FRONTEND_DIST", "./web"), ShortDomain: env("SHORT_DOMAIN", "snip.to"), SessionSecret: env("SESSION_SECRET", "dev-insecure-secret-change-me"), CookieSecure: envBool("COOKIE_SECURE", false), GoogleClientID: env("GOOGLE_CLIENT_ID", ""), GoogleClientSecret: env("GOOGLE_CLIENT_SECRET", ""), OIDCIssuer: env("OIDC_ISSUER", ""), OIDCClientID: env("OIDC_CLIENT_ID", ""), OIDCClientSecret: env("OIDC_CLIENT_SECRET", ""), ClickFlushInterval: flush, } }