// Package database owns SQLite setup, migrations, and persistence repositories. package database import ( "context" "database/sql" "errors" "fmt" "os" "path/filepath" "strings" _ "modernc.org/sqlite" ) // Open creates the parent directory, opens SQLite, enables required pragmas, // runs embedded migrations, and verifies connectivity. func Open(ctx context.Context, path string) (*sql.DB, error) { if strings.TrimSpace(path) == "" { return nil, errors.New("database path must not be empty") } if path != ":memory:" { if err := os.MkdirAll(filepath.Dir(path), 0o750); err != nil { return nil, fmt.Errorf("create database directory: %w", err) } } dsn := path if path != ":memory:" { dsn = "file:" + filepath.ToSlash(path) } separator := "?" if strings.Contains(dsn, "?") { separator = "&" } dsn += separator + "_pragma=foreign_keys(1)&_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)" db, err := sql.Open("sqlite", dsn) if err != nil { return nil, fmt.Errorf("open SQLite: %w", err) } db.SetMaxOpenConns(1) db.SetMaxIdleConns(1) if err := db.PingContext(ctx); err != nil { db.Close() return nil, fmt.Errorf("ping SQLite: %w", err) } if err := Migrate(ctx, db); err != nil { db.Close() return nil, err } return db, nil }