diff --git a/appview/db/db.go b/appview/db/db.go
index 9f5d0f5a..ad0c957e 100644
--- a/appview/db/db.go
+++ b/appview/db/db.go
@@ -1,13 +1,25 @@
package db
import (
+ "context"
"database/sql"
_ "github.com/mattn/go-sqlite3"
)
type DB struct {
- db *sql.DB
+ *sql.DB
+}
+
+type Execer interface {
+ Query(query string, args ...any) (*sql.Rows, error)
+ QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
+ QueryRow(query string, args ...any) *sql.Row
+ QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
+ Exec(query string, args ...any) (sql.Result, error)
+ ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
+ Prepare(query string) (*sql.Stmt, error)
+ PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
}
func Make(dbPath string) (*DB, error) {
@@ -104,5 +116,5 @@ func Make(dbPath string) (*DB, error) {
if err != nil {
return nil, err
}
- return &DB{db: db}, nil
+ return &DB{db}, nil
}
diff --git a/appview/db/follow.go b/appview/db/follow.go
index 2a18bce3..795fc485 100644
--- a/appview/db/follow.go
+++ b/appview/db/follow.go
@@ -12,16 +12,16 @@ type Follow struct {
RKey string
}
-func (d *DB) AddFollow(userDid, subjectDid, rkey string) error {
+func AddFollow(e Execer, userDid, subjectDid, rkey string) error {
query := `insert or ignore into follows (user_did, subject_did, rkey) values (?, ?, ?)`
- _, err := d.db.Exec(query, userDid, subjectDid, rkey)
+ _, err := e.Exec(query, userDid, subjectDid, rkey)
return err
}
// Get a follow record
-func (d *DB) GetFollow(userDid, subjectDid string) (*Follow, error) {
+func GetFollow(e Execer, userDid, subjectDid string) (*Follow, error) {
query := `select user_did, subject_did, followed_at, rkey from follows where user_did = ? and subject_did = ?`
- row := d.db.QueryRow(query, userDid, subjectDid)
+ row := e.QueryRow(query, userDid, subjectDid)
var follow Follow
var followedAt string
@@ -42,14 +42,14 @@ func (d *DB) GetFollow(userDid, subjectDid string) (*Follow, error) {
}
// Get a follow record
-func (d *DB) DeleteFollow(userDid, subjectDid string) error {
- _, err := d.db.Exec(`delete from follows where user_did = ? and subject_did = ?`, userDid, subjectDid)
+func DeleteFollow(e Execer, userDid, subjectDid string) error {
+ _, err := e.Exec(`delete from follows where user_did = ? and subject_did = ?`, userDid, subjectDid)
return err
}
-func (d *DB) GetFollowerFollowing(did string) (int, int, error) {
+func GetFollowerFollowing(e Execer, did string) (int, int, error) {
followers, following := 0, 0
- err := d.db.QueryRow(
+ err := e.QueryRow(
`SELECT
COUNT(CASE WHEN subject_did = ? THEN 1 END) AS followers,
COUNT(CASE WHEN user_did = ? THEN 1 END) AS following
@@ -81,20 +81,20 @@ func (s FollowStatus) String() string {
}
}
-func (d *DB) GetFollowStatus(userDid, subjectDid string) FollowStatus {
+func GetFollowStatus(e Execer, userDid, subjectDid string) FollowStatus {
if userDid == subjectDid {
return IsSelf
- } else if _, err := d.GetFollow(userDid, subjectDid); err != nil {
+ } else if _, err := GetFollow(e, userDid, subjectDid); err != nil {
return IsNotFollowing
} else {
return IsFollowing
}
}
-func (d *DB) GetAllFollows() ([]Follow, error) {
+func GetAllFollows(e Execer) ([]Follow, error) {
var follows []Follow
- rows, err := d.db.Query(`select user_did, subject_did, followed_at, rkey from follows`)
+ rows, err := e.Query(`select user_did, subject_did, followed_at, rkey from follows`)
if err != nil {
return nil, err
}
diff --git a/appview/db/issues.go b/appview/db/issues.go
index 89c1c15f..122a9686 100644
--- a/appview/db/issues.go
+++ b/appview/db/issues.go
@@ -26,14 +26,10 @@ type Comment struct {
Created *time.Time
}
-func (d *DB) NewIssue(issue *Issue) error {
- tx, err := d.db.Begin()
- if err != nil {
- return err
- }
+func NewIssue(tx *sql.Tx, issue *Issue) error {
defer tx.Rollback()
- _, err = tx.Exec(`
+ _, err := tx.Exec(`
insert or ignore into repo_issue_seqs (repo_at, next_issue_id)
values (?, 1)
`, issue.RepoAt)
@@ -69,33 +65,33 @@ func (d *DB) NewIssue(issue *Issue) error {
return nil
}
-func (d *DB) SetIssueAt(repoAt string, issueId int, issueAt string) error {
- _, err := d.db.Exec(`update issues set issue_at = ? where repo_at = ? and issue_id = ?`, issueAt, repoAt, issueId)
+func SetIssueAt(e Execer, repoAt string, issueId int, issueAt string) error {
+ _, err := e.Exec(`update issues set issue_at = ? where repo_at = ? and issue_id = ?`, issueAt, repoAt, issueId)
return err
}
-func (d *DB) GetIssueAt(repoAt string, issueId int) (string, error) {
+func GetIssueAt(e Execer, repoAt string, issueId int) (string, error) {
var issueAt string
- err := d.db.QueryRow(`select issue_at from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&issueAt)
+ err := e.QueryRow(`select issue_at from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&issueAt)
return issueAt, err
}
-func (d *DB) GetIssueId(repoAt string) (int, error) {
+func GetIssueId(e Execer, repoAt string) (int, error) {
var issueId int
- err := d.db.QueryRow(`select next_issue_id from repo_issue_seqs where repo_at = ?`, repoAt).Scan(&issueId)
+ err := e.QueryRow(`select next_issue_id from repo_issue_seqs where repo_at = ?`, repoAt).Scan(&issueId)
return issueId - 1, err
}
-func (d *DB) GetIssueOwnerDid(repoAt string, issueId int) (string, error) {
+func GetIssueOwnerDid(e Execer, repoAt string, issueId int) (string, error) {
var ownerDid string
- err := d.db.QueryRow(`select owner_did from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&ownerDid)
+ err := e.QueryRow(`select owner_did from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&ownerDid)
return ownerDid, err
}
-func (d *DB) GetIssues(repoAt string) ([]Issue, error) {
+func GetIssues(e Execer, repoAt string) ([]Issue, error) {
var issues []Issue
- rows, err := d.db.Query(`select owner_did, issue_id, created, title, body, open from issues where repo_at = ? order by created desc`, repoAt)
+ rows, err := e.Query(`select owner_did, issue_id, created, title, body, open from issues where repo_at = ? order by created desc`, repoAt)
if err != nil {
return nil, err
}
@@ -125,9 +121,9 @@ func (d *DB) GetIssues(repoAt string) ([]Issue, error) {
return issues, nil
}
-func (d *DB) GetIssue(repoAt string, issueId int) (*Issue, error) {
+func GetIssue(e Execer, repoAt string, issueId int) (*Issue, error) {
query := `select owner_did, created, title, body, open from issues where repo_at = ? and issue_id = ?`
- row := d.db.QueryRow(query, repoAt, issueId)
+ row := e.QueryRow(query, repoAt, issueId)
var issue Issue
var createdAt string
@@ -145,9 +141,9 @@ func (d *DB) GetIssue(repoAt string, issueId int) (*Issue, error) {
return &issue, nil
}
-func (d *DB) GetIssueWithComments(repoAt string, issueId int) (*Issue, []Comment, error) {
+func GetIssueWithComments(e Execer, repoAt string, issueId int) (*Issue, []Comment, error) {
query := `select owner_did, issue_id, created, title, body, open from issues where repo_at = ? and issue_id = ?`
- row := d.db.QueryRow(query, repoAt, issueId)
+ row := e.QueryRow(query, repoAt, issueId)
var issue Issue
var createdAt string
@@ -162,7 +158,7 @@ func (d *DB) GetIssueWithComments(repoAt string, issueId int) (*Issue, []Comment
}
issue.Created = &createdTime
- comments, err := d.GetComments(repoAt, issueId)
+ comments, err := GetComments(e, repoAt, issueId)
if err != nil {
return nil, nil, err
}
@@ -170,9 +166,9 @@ func (d *DB) GetIssueWithComments(repoAt string, issueId int) (*Issue, []Comment
return &issue, comments, nil
}
-func (d *DB) NewComment(comment *Comment) error {
+func NewComment(e Execer, comment *Comment) error {
query := `insert into comments (owner_did, repo_at, comment_at, issue_id, comment_id, body) values (?, ?, ?, ?, ?, ?)`
- _, err := d.db.Exec(
+ _, err := e.Exec(
query,
comment.OwnerDid,
comment.RepoAt,
@@ -184,10 +180,10 @@ func (d *DB) NewComment(comment *Comment) error {
return err
}
-func (d *DB) GetComments(repoAt string, issueId int) ([]Comment, error) {
+func GetComments(e Execer, repoAt string, issueId int) ([]Comment, error) {
var comments []Comment
- rows, err := d.db.Query(`select owner_did, issue_id, comment_id, comment_at, body, created from comments where repo_at = ? and issue_id = ? order by created asc`, repoAt, issueId)
+ rows, err := e.Query(`select owner_did, issue_id, comment_id, comment_at, body, created from comments where repo_at = ? and issue_id = ? order by created asc`, repoAt, issueId)
if err == sql.ErrNoRows {
return []Comment{}, nil
}
@@ -220,12 +216,12 @@ func (d *DB) GetComments(repoAt string, issueId int) ([]Comment, error) {
return comments, nil
}
-func (d *DB) CloseIssue(repoAt string, issueId int) error {
- _, err := d.db.Exec(`update issues set open = 0 where repo_at = ? and issue_id = ?`, repoAt, issueId)
+func CloseIssue(e Execer, repoAt string, issueId int) error {
+ _, err := e.Exec(`update issues set open = 0 where repo_at = ? and issue_id = ?`, repoAt, issueId)
return err
}
-func (d *DB) ReopenIssue(repoAt string, issueId int) error {
- _, err := d.db.Exec(`update issues set open = 1 where repo_at = ? and issue_id = ?`, repoAt, issueId)
+func ReopenIssue(e Execer, repoAt string, issueId int) error {
+ _, err := e.Exec(`update issues set open = 1 where repo_at = ? and issue_id = ?`, repoAt, issueId)
return err
}
diff --git a/appview/db/jetstream.go b/appview/db/jetstream.go
index f2c4c9d6..f4196387 100644
--- a/appview/db/jetstream.go
+++ b/appview/db/jetstream.go
@@ -1,21 +1,25 @@
package db
-func (d *DB) SaveLastTimeUs(lastTimeUs int64) error {
- _, err := d.db.Exec(`insert into _jetstream (last_time_us) values (?)`, lastTimeUs)
+type DbWrapper struct {
+ Execer
+}
+
+func (db DbWrapper) SaveLastTimeUs(lastTimeUs int64) error {
+ _, err := db.Exec(`insert into _jetstream (last_time_us) values (?)`, lastTimeUs)
return err
}
-func (d *DB) UpdateLastTimeUs(lastTimeUs int64) error {
- _, err := d.db.Exec(`update _jetstream set last_time_us = ? where rowid = 1`, lastTimeUs)
+func (db DbWrapper) UpdateLastTimeUs(lastTimeUs int64) error {
+ _, err := db.Exec(`update _jetstream set last_time_us = ? where rowid = 1`, lastTimeUs)
if err != nil {
return err
}
return nil
}
-func (d *DB) GetLastTimeUs() (int64, error) {
+func (db DbWrapper) GetLastTimeUs() (int64, error) {
var lastTimeUs int64
- row := d.db.QueryRow(`select last_time_us from _jetstream`)
+ row := db.QueryRow(`select last_time_us from _jetstream`)
err := row.Scan(&lastTimeUs)
return lastTimeUs, err
}
diff --git a/appview/db/pubkeys.go b/appview/db/pubkeys.go
index 408c2c40..552745cc 100644
--- a/appview/db/pubkeys.go
+++ b/appview/db/pubkeys.go
@@ -5,15 +5,15 @@ import (
"time"
)
-func (d *DB) AddPublicKey(did, name, key string) error {
+func AddPublicKey(e Execer, did, name, key string) error {
query := `insert or ignore into public_keys (did, name, key) values (?, ?, ?)`
- _, err := d.db.Exec(query, did, name, key)
+ _, err := e.Exec(query, did, name, key)
return err
}
-func (d *DB) RemovePublicKey(did string) error {
+func RemovePublicKey(e Execer, did string) error {
query := `delete from public_keys where did = ?`
- _, err := d.db.Exec(query, did)
+ _, err := e.Exec(query, did)
return err
}
@@ -35,10 +35,10 @@ func (p PublicKey) MarshalJSON() ([]byte, error) {
})
}
-func (d *DB) GetAllPublicKeys() ([]PublicKey, error) {
+func GetAllPublicKeys(e Execer) ([]PublicKey, error) {
var keys []PublicKey
- rows, err := d.db.Query(`select key, name, did, created from public_keys`)
+ rows, err := e.Query(`select key, name, did, created from public_keys`)
if err != nil {
return nil, err
}
@@ -62,10 +62,10 @@ func (d *DB) GetAllPublicKeys() ([]PublicKey, error) {
return keys, nil
}
-func (d *DB) GetPublicKeys(did string) ([]PublicKey, error) {
+func GetPublicKeys(e Execer, did string) ([]PublicKey, error) {
var keys []PublicKey
- rows, err := d.db.Query(`select did, key, name, created from public_keys where did = ?`, did)
+ rows, err := e.Query(`select did, key, name, created from public_keys where did = ?`, did)
if err != nil {
return nil, err
}
diff --git a/appview/db/registration.go b/appview/db/registration.go
index c82e100c..b354f59d 100644
--- a/appview/db/registration.go
+++ b/appview/db/registration.go
@@ -32,10 +32,10 @@ const (
)
// returns registered status, did of owner, error
-func (d *DB) RegistrationsByDid(did string) ([]Registration, error) {
+func RegistrationsByDid(e Execer, did string) ([]Registration, error) {
var registrations []Registration
- rows, err := d.db.Query(`
+ rows, err := e.Query(`
select domain, did, created, registered from registrations
where did = ?
`, did)
@@ -69,12 +69,12 @@ func (d *DB) RegistrationsByDid(did string) ([]Registration, error) {
}
// returns registered status, did of owner, error
-func (d *DB) RegistrationByDomain(domain string) (*Registration, error) {
+func RegistrationByDomain(e Execer, domain string) (*Registration, error) {
var createdAt *string
var registeredAt *string
var registration Registration
- err := d.db.QueryRow(`
+ err := e.QueryRow(`
select domain, did, created, registered from registrations
where domain = ?
`, domain).Scan(®istration.Domain, ®istration.ByDid, &createdAt, ®isteredAt)
@@ -106,9 +106,9 @@ func genSecret() string {
return hex.EncodeToString(key)
}
-func (d *DB) GenerateRegistrationKey(domain, did string) (string, error) {
+func GenerateRegistrationKey(e Execer, domain, did string) (string, error) {
// sanity check: does this domain already have a registration?
- reg, err := d.RegistrationByDomain(domain)
+ reg, err := RegistrationByDomain(e, domain)
if err != nil {
return "", err
}
@@ -127,7 +127,7 @@ func (d *DB) GenerateRegistrationKey(domain, did string) (string, error) {
secret := genSecret()
- _, err = d.db.Exec(`
+ _, err = e.Exec(`
insert into registrations (domain, did, secret)
values (?, ?, ?)
on conflict(domain) do update set did = excluded.did, secret = excluded.secret
@@ -140,8 +140,8 @@ func (d *DB) GenerateRegistrationKey(domain, did string) (string, error) {
return secret, nil
}
-func (d *DB) GetRegistrationKey(domain string) (string, error) {
- res := d.db.QueryRow(`select secret from registrations where domain = ?`, domain)
+func GetRegistrationKey(e Execer, domain string) (string, error) {
+ res := e.QueryRow(`select secret from registrations where domain = ?`, domain)
var secret string
err := res.Scan(&secret)
@@ -152,8 +152,8 @@ func (d *DB) GetRegistrationKey(domain string) (string, error) {
return secret, nil
}
-func (d *DB) Register(domain string) error {
- _, err := d.db.Exec(`
+func Register(e Execer, domain string) error {
+ _, err := e.Exec(`
update registrations
set registered = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
where domain = ?;
diff --git a/appview/db/repos.go b/appview/db/repos.go
index 90cdc7e6..6927614b 100644
--- a/appview/db/repos.go
+++ b/appview/db/repos.go
@@ -14,10 +14,10 @@ type Repo struct {
AtUri string
}
-func (d *DB) GetAllRepos() ([]Repo, error) {
+func GetAllRepos(e Execer) ([]Repo, error) {
var repos []Repo
- rows, err := d.db.Query(`select did, name, knot, rkey, created from repos`)
+ rows, err := e.Query(`select did, name, knot, rkey, created from repos`)
if err != nil {
return nil, err
}
@@ -39,10 +39,10 @@ func (d *DB) GetAllRepos() ([]Repo, error) {
return repos, nil
}
-func (d *DB) GetAllReposByDid(did string) ([]Repo, error) {
+func GetAllReposByDid(e Execer, did string) ([]Repo, error) {
var repos []Repo
- rows, err := d.db.Query(`select did, name, knot, rkey, created from repos where did = ?`, did)
+ rows, err := e.Query(`select did, name, knot, rkey, created from repos where did = ?`, did)
if err != nil {
return nil, err
}
@@ -64,10 +64,10 @@ func (d *DB) GetAllReposByDid(did string) ([]Repo, error) {
return repos, nil
}
-func (d *DB) GetRepo(did, name string) (*Repo, error) {
+func GetRepo(e Execer, did, name string) (*Repo, error) {
var repo Repo
- row := d.db.QueryRow(`select did, name, knot, created, at_uri from repos where did = ? and name = ?`, did, name)
+ row := e.QueryRow(`select did, name, knot, created, at_uri from repos where did = ? and name = ?`, did, name)
var createdAt string
if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri); err != nil {
@@ -79,28 +79,28 @@ func (d *DB) GetRepo(did, name string) (*Repo, error) {
return &repo, nil
}
-func (d *DB) AddRepo(repo *Repo) error {
- _, err := d.db.Exec(`insert into repos (did, name, knot, rkey, at_uri) values (?, ?, ?, ?, ?)`, repo.Did, repo.Name, repo.Knot, repo.Rkey, repo.AtUri)
+func AddRepo(e Execer, repo *Repo) error {
+ _, err := e.Exec(`insert into repos (did, name, knot, rkey, at_uri) values (?, ?, ?, ?, ?)`, repo.Did, repo.Name, repo.Knot, repo.Rkey, repo.AtUri)
return err
}
-func (d *DB) RemoveRepo(did, name, rkey string) error {
- _, err := d.db.Exec(`delete from repos where did = ? and name = ? and rkey = ?`, did, name, rkey)
+func RemoveRepo(e Execer, did, name, rkey string) error {
+ _, err := e.Exec(`delete from repos where did = ? and name = ? and rkey = ?`, did, name, rkey)
return err
}
-func (d *DB) AddCollaborator(collaborator, repoOwnerDid, repoName, repoKnot string) error {
- _, err := d.db.Exec(
+func AddCollaborator(e Execer, collaborator, repoOwnerDid, repoName, repoKnot string) error {
+ _, err := e.Exec(
`insert into collaborators (did, repo)
values (?, (select id from repos where did = ? and name = ? and knot = ?));`,
collaborator, repoOwnerDid, repoName, repoKnot)
return err
}
-func (d *DB) CollaboratingIn(collaborator string) ([]Repo, error) {
+func CollaboratingIn(e Execer, collaborator string) ([]Repo, error) {
var repos []Repo
- rows, err := d.db.Query(`select r.did, r.name, r.knot, r.rkey, r.created from repos r join collaborators c on r.id = c.repo where c.did = ?;`, collaborator)
+ rows, err := e.Query(`select r.did, r.name, r.knot, r.rkey, r.created from repos r join collaborators c on r.id = c.repo where c.did = ?;`, collaborator)
if err != nil {
return nil, err
}
diff --git a/appview/db/timeline.go b/appview/db/timeline.go
index e06322ff..d857b409 100644
--- a/appview/db/timeline.go
+++ b/appview/db/timeline.go
@@ -11,15 +11,15 @@ type TimelineEvent struct {
EventAt time.Time
}
-func (d *DB) MakeTimeline() ([]TimelineEvent, error) {
+func MakeTimeline(e Execer) ([]TimelineEvent, error) {
var events []TimelineEvent
- repos, err := d.GetAllRepos()
+ repos, err := GetAllRepos(e)
if err != nil {
return nil, err
}
- follows, err := d.GetAllFollows()
+ follows, err := GetAllFollows(e)
if err != nil {
return nil, err
}
diff --git a/appview/pages/templates/repo/new.html b/appview/pages/templates/repo/new.html
index e71ee250..045043ac 100644
--- a/appview/pages/templates/repo/new.html
+++ b/appview/pages/templates/repo/new.html
@@ -22,10 +22,10 @@
type="text"
id="branch"
name="branch"
+ value="main"
required
class="w-full max-w-md"
/>
-
The default branch is main