{{/* This template attaches cursor-based pagination methods to Ent queries. */}} {{ define "cursor" }} {{ $pkg := base $.Config.Package }} {{ template "header" $ }} {{ range $n := $.Nodes }} {{ $hasCreatedAt := false }} {{ range $f := $n.Fields }} {{ if eq $f.Name "created_at" }} {{ $hasCreatedAt = true }} {{ end }} {{ end }} {{ if $hasCreatedAt }} {{ $receiver := $n.Receiver }} // Cursor runs the query and returns a cursor-paginated response. // Ordering is always by created_at asc, id asc. func ({{ $receiver }} *{{ $n.QueryName }}) Cursor(ctx context.Context, cursor *pagination.Cursor) (pagination.Result[*{{ $n.Name }}], error) { if cursor != nil { if err := cursor.Validate(); err != nil { return pagination.Result[*{{ $n.Name }}]{}, fmt.Errorf("invalid cursor: %w", err) } {{ $receiver }}.Where(func(s *sql.Selector) { s.Where( sql.Or( sql.GT(s.C("created_at"), cursor.Time), sql.And( sql.EQ(s.C("created_at"), cursor.Time), sql.P(func(b *sql.Builder) { b.WriteString("CAST(") b.WriteString(s.C("id")) b.WriteString(" AS TEXT) > ") b.Args(cursor.ID) }), ), ), ) }) } {{ $receiver }}.Order(func(s *sql.Selector) { s.OrderBy(sql.Asc(s.C("created_at")), sql.Asc(s.C("id"))) }) items, err := {{ $receiver }}.All(ctx) if err != nil { return pagination.Result[*{{ $n.Name }}]{}, err } if items == nil { items = make([]*{{ $n.Name }}, 0) } result := pagination.Result[*{{ $n.Name }}]{ Items: items, } if len(items) > 0 { last := items[len(items)-1] result.NextCursor = lo.ToPtr(pagination.NewCursor(last.CreatedAt, fmt.Sprint(last.ID))) } return result, nil } {{ end }} {{ end }} {{ end }}