File size: 2,281 Bytes
fea99b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
{{/*
    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 }}