import files, add README & LICENSE

This commit is contained in:
2026-06-29 17:06:34 -07:00
commit aecd90eb84
17 changed files with 2552 additions and 0 deletions
+83
View File
@@ -0,0 +1,83 @@
package cursor
import (
"fmt"
"gitea.auvem.com/go-toolkit/dbx"
"github.com/go-jet/jet/v2/mysql"
)
// PageQuery runs a paginated SELECT and builds a Connection from the results.
type PageQuery[T any, IE mysql.Expression, IC mysql.Column] struct {
Sqlo dbx.Queryable
Stmt mysql.SelectStatement
Conds mysql.BoolExpression
Cursor *Cursor[IE, IC]
Default func() *Cursor[IE, IC]
Limit int
CountFn QueryCountFn
ToEdge func(active *Cursor[IE, IC], item *T) (GenericCursor, error)
// Scan runs the paginated query into dest. When nil, Run uses Stmt.Query.
Scan func(stmt mysql.SelectStatement, dest *[]*T) error
// AfterScan optionally transforms rows after the query and before building edges.
AfterScan func(items []*T) ([]*T, error)
}
// Run executes the paginated query and returns a Connection.
func (q PageQuery[T, IE, IC]) Run() (*Connection[T], error) {
active := q.Cursor
if active == nil {
active = q.Default()
}
stmt := q.Stmt
stmt.WHERE(q.Conds.AND(PaginateConds(q.Cursor)))
stmt.ORDER_BY(OrderByClauses(active)...)
if q.Limit > 0 {
stmt = stmt.LIMIT(int64(q.Limit))
}
var items []*T
scan := q.Scan
if scan == nil {
scan = func(s mysql.SelectStatement, dest *[]*T) error {
return s.Query(q.Sqlo, dest)
}
}
if err := scan(stmt, &items); err != nil {
return nil, fmt.Errorf("failed to run paginated query: %w", err)
}
if q.AfterScan != nil {
var err error
items, err = q.AfterScan(items)
if err != nil {
return nil, err
}
}
return BuildEdges(q.Sqlo, q.CountFn, items, func(item *T) (GenericCursor, error) {
return q.ToEdge(active, item)
})
}
// ConnectionFromRelayArgs parses Relay pagination args and calls list with the
// decoded cursor and limit. newZero supplies the cursor template for decoding
// (same as NewXCursor).
func ConnectionFromRelayArgs[T any, IE mysql.Expression, IC mysql.Column](
after *string,
first *int,
newZero func() *Cursor[IE, IC],
list func(cursor *Cursor[IE, IC], limit int) (*Connection[T], error),
) (*Connection[T], error) {
limit := 0
if first != nil {
limit = *first
}
c, err := NewCursorFromAfterPtr(newZero, after)
if err != nil {
return nil, err
}
return list(c, limit)
}