package lite import ( "context" "database/sql" "fmt" "os" "github.com/jmoiron/sqlx" _ "github.com/ncruces/go-sqlite3/driver" _ "github.com/ncruces/go-sqlite3/embed" ) type database struct { file string path string sqlite *sqlx.DB } type Database interface { Connect() error Close() error Exec(ctx context.Context, query string, args ...any) (sql.Result, error) Query(ctx context.Context, query string, args ...any) (*sqlx.Rows, error) QueryRow(ctx context.Context, query string, args ...any) *sqlx.Row QueryIn(ctx context.Context, query string, args ...any) (*sqlx.Rows, error) } func New(opts ...Option) (Database, error) { home, err := os.UserHomeDir() if err != nil { return nil, err } defaultFile := "lite-db" db := &database{ file: defaultFile, path: home, } for _, opt := range opts { opt(db) } return db, nil } // connects to database file func (d *database) Connect() error { db, err := sqlx.Open("sqlite3", fmt.Sprintf("file:%s/%s", d.path, d.file)) if err != nil { return err } d.sqlite = db return nil } // closes database file connection func (d *database) Close() error { return d.sqlite.Close() } // runs any updates, inserts, or any other queries that do not return rows func (d *database) Exec(ctx context.Context, query string, args ...any) (sql.Result, error) { return d.sqlite.ExecContext(ctx, query, args...) } // runs basic data queries func (d *database) Query(ctx context.Context, query string, args ...any) (*sqlx.Rows, error) { return d.sqlite.QueryxContext(ctx, query, args...) } // retrieves a single row from database func (d *database) QueryRow(ctx context.Context, query string, args ...any) *sqlx.Row { return d.sqlite.QueryRowxContext(ctx, query, args...) } // runs queries that require parameters in an IN clause func (d *database) QueryIn(ctx context.Context, query string, args ...any) (*sqlx.Rows, error) { q, ar, err := sqlx.In(query, args...) if err != nil { return nil, err } return d.sqlite.QueryxContext(ctx, q, ar...) }