package database import ( "context" "database/sql" "fmt" "os" "path/filepath" "time" libsql "github.com/tursodatabase/go-libsql" "github.com/tim/md-hub-secure/apps/server/internal/config" ) type DB interface { SQL() *sql.DB Close() error } type dbHandle struct { sql *sql.DB } func Open(ctx context.Context, cfg config.DatabaseConfig) (DB, error) { if err := os.MkdirAll(filepath.Dir(cfg.Path), 0o755); err != nil { return nil, fmt.Errorf("create database directory: %w", err) } var ( db *sql.DB err error ) if cfg.PrimaryURL == "" { db, err = sql.Open("libsql", "file:"+cfg.Path) if err != nil { return nil, fmt.Errorf("open local libsql database: %w", err) } } else { var opts []libsql.Option if cfg.AuthToken != "" { opts = append(opts, libsql.WithAuthToken(cfg.AuthToken)) } connector, err := libsql.NewEmbeddedReplicaConnector(cfg.Path, cfg.PrimaryURL, opts...) if err != nil { return nil, fmt.Errorf("create libsql connector: %w", err) } db = sql.OpenDB(connector) } db.SetConnMaxLifetime(5 * time.Minute) db.SetMaxOpenConns(1) db.SetMaxIdleConns(1) if err := db.PingContext(ctx); err != nil { return nil, fmt.Errorf("ping database: %w", err) } var journalMode string if err := db.QueryRowContext(ctx, "PRAGMA journal_mode=WAL").Scan(&journalMode); err != nil { return nil, fmt.Errorf("enable wal mode: %w", err) } if _, err := db.ExecContext(ctx, "PRAGMA foreign_keys=ON"); err != nil { return nil, fmt.Errorf("enable foreign keys: %w", err) } return &dbHandle{sql: db}, nil } func (d *dbHandle) SQL() *sql.DB { return d.sql } func (d *dbHandle) Close() error { return d.sql.Close() }