package db import ( "fmt" "os" "path/filepath" "strings" "server/internal/models" "gorm.io/driver/postgres" "gorm.io/driver/sqlite" "gorm.io/gorm" ) type Config struct { Driver string DSN string } // Init opens the configured database connection and runs schema migrations. func Init(cfg Config) (*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) } if err := db.AutoMigrate(&models.User{}, &models.UserDetails{}, &models.UserPreferences{}, &models.Session{}, &models.PasswordResetToken{}); err != nil { return nil, fmt.Errorf("migrate user: %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) } if err := db.AutoMigrate(&models.User{}, &models.UserDetails{}, &models.UserPreferences{}, &models.Session{}, &models.PasswordResetToken{}); err != nil { return nil, fmt.Errorf("migrate user: %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) }