- Go backend: auth (JWT), points earn/spend, QR token generation, partners, admin grant/stats endpoints with chi router - Next.js 14 frontend: login, student dashboard, transaction history, QR display, partners list - PostgreSQL migrations (4 tables), Redis cache, Docker Compose - CORS middleware, role-based route protection, Zustand auth store Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
62 lines
1.6 KiB
Go
62 lines
1.6 KiB
Go
// Package config loads all runtime configuration from environment variables.
|
|
// All other packages must read settings through this package — no magic strings elsewhere.
|
|
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
// Config holds all application settings read from environment variables.
|
|
type Config struct {
|
|
DatabaseURL string
|
|
RedisURL string
|
|
JWTSecret string
|
|
JWTAccessTTL time.Duration
|
|
JWTRefreshTTL time.Duration
|
|
Port string
|
|
Env string
|
|
}
|
|
|
|
// Load reads environment variables and returns a populated Config.
|
|
// Returns an error if any required variable is missing or cannot be parsed.
|
|
func Load() (*Config, error) {
|
|
cfg := &Config{
|
|
DatabaseURL: os.Getenv("DATABASE_URL"),
|
|
RedisURL: os.Getenv("REDIS_URL"),
|
|
JWTSecret: os.Getenv("JWT_SECRET"),
|
|
Port: envOrDefault("PORT", "8080"),
|
|
Env: envOrDefault("ENV", "development"),
|
|
}
|
|
|
|
for _, req := range []struct{ name, val string }{
|
|
{"DATABASE_URL", cfg.DatabaseURL},
|
|
{"REDIS_URL", cfg.RedisURL},
|
|
{"JWT_SECRET", cfg.JWTSecret},
|
|
} {
|
|
if req.val == "" {
|
|
return nil, fmt.Errorf("config.Load: required env var %s is not set", req.name)
|
|
}
|
|
}
|
|
|
|
var err error
|
|
cfg.JWTAccessTTL, err = time.ParseDuration(envOrDefault("JWT_ACCESS_TTL", "15m"))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("config.Load: invalid JWT_ACCESS_TTL: %w", err)
|
|
}
|
|
cfg.JWTRefreshTTL, err = time.ParseDuration(envOrDefault("JWT_REFRESH_TTL", "168h"))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("config.Load: invalid JWT_REFRESH_TTL: %w", err)
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
func envOrDefault(key, fallback string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|