M api/database/sq.go => api/database/sq.go +0 -1
@@ 8,7 8,6 @@ import (
)
type Selectable interface {
- As(alias string) Selectable
Select(ctx context.Context) []string
Fields(ctx context.Context) []interface{}
}
M api/graph/model/cursor.go => api/graph/model/cursor.go +11 -0
@@ 8,6 8,7 @@ import (
"git.sr.ht/~sircmpwn/git.sr.ht/api/crypto"
)
+// TODO: Add a field for the resource this is intended to be used with
type Cursor struct {
Count int `json:"count"`
Next string `json:"next"`
@@ 41,3 42,13 @@ func (cur Cursor) MarshalGQL(w io.Writer) {
w.Write(crypto.Encrypt(data))
w.Write([]byte("\""))
}
+
+func NewCursor(filter *Filter) *Cursor {
+ // TODO: Apply filter
+ return &Cursor{
+ Count: 25,
+ Next: "",
+ OrderBy: "",
+ Search: "",
+ }
+}
M api/graph/model/repository.go => api/graph/model/repository.go +15 -1
@@ 3,6 3,7 @@ package model
import (
"context"
"time"
+ "strconv"
"github.com/go-git/go-git/v5"
sq "github.com/Masterminds/squirrel"
@@ 66,7 67,7 @@ func (r *Repository) Select(ctx context.Context) []string {
database.WithAlias(r.alias, "owner_id"))
}
-func (r *Repository) As(alias string) database.Selectable {
+func (r *Repository) As(alias string) *Repository {
r.alias = alias
return r
}
@@ 84,6 85,19 @@ func (r *Repository) Fields(ctx context.Context) []interface{} {
return append(fields, &r.Path, &r.OwnerID)
}
+func (r *Repository) ApplyCursor(q sq.SelectBuilder, c *Cursor) sq.SelectBuilder {
+ if c.Next != "" {
+ id, _ := strconv.Atoi(c.Next)
+ q = q.Where(r.alias + `.id <= ?`, id)
+ }
+ if c.OrderBy != "" {
+ q = q.OrderBy(c.OrderBy)
+ } else {
+ q = q.OrderBy(r.alias + `.id DESC`)
+ }
+ return q.Limit(uint64(c.Count + 1))
+}
+
func (r *Repository) DefaultSearch(query sq.SelectBuilder,
term string) (sq.SelectBuilder, error) {
name := database.WithAlias(r.alias, "name")
M api/graph/schema.resolvers.go => api/graph/schema.resolvers.go +12 -3
@@ 160,17 160,22 @@ func (r *userResolver) Repositories(ctx context.Context, obj *model.User, cursor
err error
rows *sql.Rows
)
+
repo := (&model.Repository{}).As(`repo`)
query := database.
Select(ctx, repo).
From(`repository repo`).
- Where(`repo.owner_id = ?`, obj.ID).
- OrderBy(`id DESC`).
- Limit(26)
+ Where(`repo.owner_id = ?`, obj.ID)
+ if cursor == nil {
+ cursor = model.NewCursor(filter)
+ }
+ query = repo.ApplyCursor(query, cursor)
+
if rows, err = query.RunWith(r.DB).QueryContext(ctx); err != nil {
panic(err)
}
defer rows.Close()
+
var repos []*model.Repository
for rows.Next() {
var repo model.Repository
@@ 179,6 184,7 @@ func (r *userResolver) Repositories(ctx context.Context, obj *model.User, cursor
}
repos = append(repos, &repo)
}
+
if len(repos) > 25 {
cursor = &model.Cursor{
Count: 25,
@@ 187,7 193,10 @@ func (r *userResolver) Repositories(ctx context.Context, obj *model.User, cursor
Search: "",
}
repos = repos[:25]
+ } else {
+ cursor = nil
}
+
return &model.RepositoryCursor{repos, cursor}, nil
}