package db import ( "fmt" "os" "path/filepath" "server/internal/config" "strings" "github.com/gofiber/fiber/v3" "gorm.io/driver/postgres" "gorm.io/driver/sqlite" "gorm.io/gorm" ) var DB *gorm.DB // GetDB returns the global *gorm.DB instance. It panics if the database is not initialized. func GetDB() (*gorm.DB, error) { if DB == nil { cfg, err := config.GetConfig() if err != nil { return nil, err } DB, err = InitDB(cfg.Db) if err != nil { fmt.Printf("Failed to initialize database: %v\n", err) return nil, err } } return DB, nil } // Init opens the configured database connection and runs schema migrations. func InitDB(cfg config.DbConfig) (*gorm.DB, error) { switch cfg.Driver { case "sqlite": if err := ensureSQLiteDir(cfg.DSN); err != nil { return nil, fmt.Errorf("prepare sqlite path: %w", err) } DB, err := gorm.Open(sqlite.Open(cfg.DSN), &gorm.Config{}) if err != nil { return nil, fmt.Errorf("open sqlite: %w", err) } return DB, nil case "postgres": DB, err := gorm.Open(postgres.Open(cfg.DSN), &gorm.Config{}) if err != nil { return nil, fmt.Errorf("open postgres: %w", err) } return DB, nil default: return nil, fmt.Errorf("unsupported driver %q", cfg.Driver) } } func ensureSQLiteDir(dsn string) error { pathSpec := dsn if idx := strings.Index(pathSpec, "?"); idx >= 0 { pathSpec = pathSpec[:idx] } pathSpec = strings.TrimPrefix(pathSpec, "file:") if pathSpec == "" || strings.Contains(pathSpec, ":memory:") { return nil } dir := filepath.Dir(pathSpec) if dir == "." || dir == "" { return nil } return os.MkdirAll(dir, 0o755) } // dbFromCtx extracts *gorm.DB from Fiber context. func dbFromCtx(c fiber.Ctx) (*gorm.DB, error) { dbVal := c.Locals("db") db, ok := dbVal.(*gorm.DB) if !ok || db == nil { return nil, fiber.NewError(fiber.StatusInternalServerError, "database unavailable") } return db, nil } func DBFromCtx(c fiber.Ctx) (*gorm.DB, error) { return dbFromCtx(c) }