package service import ( "database/sql" "fmt" "os" "path/filepath" "tinyauth/internal/assets" "github.com/glebarez/sqlite" "github.com/golang-migrate/migrate/v4" sqliteMigrate "github.com/golang-migrate/migrate/v4/database/sqlite3" "github.com/golang-migrate/migrate/v4/source/iofs" "gorm.io/gorm" ) type DatabaseServiceConfig struct { DatabasePath string } type DatabaseService struct { config DatabaseServiceConfig database *gorm.DB } func NewDatabaseService(config DatabaseServiceConfig) *DatabaseService { return &DatabaseService{ config: config, } } func (ds *DatabaseService) Init() error { dbPath := ds.config.DatabasePath if dbPath == "" { dbPath = "/data/tinyauth.db" } dir := filepath.Dir(dbPath) if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("failed to create database directory %s: %w", dir, err) } gormDB, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{}) if err != nil { return err } sqlDB, err := gormDB.DB() if err != nil { return err } sqlDB.SetMaxOpenConns(1) err = ds.migrateDatabase(sqlDB) if err != nil && err != migrate.ErrNoChange { return err } ds.database = gormDB return nil } func (ds *DatabaseService) migrateDatabase(sqlDB *sql.DB) error { data, err := iofs.New(assets.Migrations, "migrations") if err != nil { return err } target, err := sqliteMigrate.WithInstance(sqlDB, &sqliteMigrate.Config{}) if err != nil { return err } migrator, err := migrate.NewWithInstance("iofs", data, "tinyauth", target) if err != nil { return err } return migrator.Up() } func (ds *DatabaseService) GetDatabase() *gorm.DB { return ds.database }