1package resolvers
2
3import (
4 "context"
5
6 "github.com/git-bug/git-bug/api/auth"
7 "github.com/git-bug/git-bug/api/graphql/connections"
8 "github.com/git-bug/git-bug/api/graphql/graph"
9 "github.com/git-bug/git-bug/api/graphql/models"
10 "github.com/git-bug/git-bug/entities/common"
11 "github.com/git-bug/git-bug/entity"
12 "github.com/git-bug/git-bug/query"
13)
14
15var _ graph.RepositoryResolver = &repoResolver{}
16
17type repoResolver struct{}
18
19func (repoResolver) Name(_ context.Context, obj *models.Repository) (*string, error) {
20 name := obj.Repo.Name()
21 return &name, nil
22}
23
24// Slug returns the URL-friendly identifier for the repo, used as the /:repo
25// path segment in the frontend.
26func (repoResolver) Slug(_ context.Context, obj *models.Repository) (string, error) {
27 return obj.Repo.Slug(), nil
28}
29
30func (repoResolver) AllBugs(_ context.Context, obj *models.Repository, after *string, before *string, first *int, last *int, queryStr *string) (*models.BugConnection, error) {
31 input := models.ConnectionInput{
32 Before: before,
33 After: after,
34 First: first,
35 Last: last,
36 }
37
38 var q *query.Query
39 if queryStr != nil {
40 query2, err := query.Parse(*queryStr)
41 if err != nil {
42 return nil, err
43 }
44 q = query2
45 } else {
46 q = query.NewQuery()
47 }
48
49 // Simply pass a []string with the ids to the pagination algorithm
50 source, err := obj.Repo.Bugs().Query(q)
51 if err != nil {
52 return nil, err
53 }
54
55 // The edger create a custom edge holding just the id
56 edger := func(id entity.Id, offset int) connections.Edge {
57 return connections.LazyBugEdge{
58 Id: id,
59 Cursor: connections.OffsetToCursor(offset),
60 }
61 }
62
63 // The conMaker will finally load and compile bugs from git to replace the selected edges
64 conMaker := func(lazyBugEdges []*connections.LazyBugEdge, lazyNode []entity.Id, info *models.PageInfo, totalCount int) (*models.BugConnection, error) {
65 edges := make([]*models.BugEdge, len(lazyBugEdges))
66 nodes := make([]models.BugWrapper, len(lazyBugEdges))
67
68 for i, lazyBugEdge := range lazyBugEdges {
69 excerpt, err := obj.Repo.Bugs().ResolveExcerpt(lazyBugEdge.Id)
70 if err != nil {
71 return nil, err
72 }
73
74 b := models.NewLazyBug(obj.Repo, excerpt)
75
76 edges[i] = &models.BugEdge{
77 Cursor: lazyBugEdge.Cursor,
78 Node: b,
79 }
80 nodes[i] = b
81 }
82
83 return &models.BugConnection{
84 Edges: edges,
85 Nodes: nodes,
86 PageInfo: info,
87 TotalCount: totalCount,
88 }, nil
89 }
90
91 return connections.Connection(source, edger, conMaker, input)
92}
93
94func (repoResolver) Bug(_ context.Context, obj *models.Repository, prefix string) (models.BugWrapper, error) {
95 excerpt, err := obj.Repo.Bugs().ResolveExcerptPrefix(prefix)
96 if err != nil {
97 return nil, err
98 }
99
100 return models.NewLazyBug(obj.Repo, excerpt), nil
101}
102
103func (repoResolver) AllIdentities(_ context.Context, obj *models.Repository, after *string, before *string, first *int, last *int) (*models.IdentityConnection, error) {
104 input := models.ConnectionInput{
105 Before: before,
106 After: after,
107 First: first,
108 Last: last,
109 }
110
111 // Simply pass a []string with the ids to the pagination algorithm
112 source := obj.Repo.Identities().AllIds()
113
114 // The edger create a custom edge holding just the id
115 edger := func(id entity.Id, offset int) connections.Edge {
116 return connections.LazyIdentityEdge{
117 Id: id,
118 Cursor: connections.OffsetToCursor(offset),
119 }
120 }
121
122 // The conMaker will finally load and compile identities from git to replace the selected edges
123 conMaker := func(lazyIdentityEdges []*connections.LazyIdentityEdge, lazyNode []entity.Id, info *models.PageInfo, totalCount int) (*models.IdentityConnection, error) {
124 edges := make([]*models.IdentityEdge, len(lazyIdentityEdges))
125 nodes := make([]models.IdentityWrapper, len(lazyIdentityEdges))
126
127 for k, lazyIdentityEdge := range lazyIdentityEdges {
128 excerpt, err := obj.Repo.Identities().ResolveExcerpt(lazyIdentityEdge.Id)
129 if err != nil {
130 return nil, err
131 }
132
133 i := models.NewLazyIdentity(obj.Repo, excerpt)
134
135 edges[k] = &models.IdentityEdge{
136 Cursor: lazyIdentityEdge.Cursor,
137 Node: i,
138 }
139 nodes[k] = i
140 }
141
142 return &models.IdentityConnection{
143 Edges: edges,
144 Nodes: nodes,
145 PageInfo: info,
146 TotalCount: totalCount,
147 }, nil
148 }
149
150 return connections.Connection(source, edger, conMaker, input)
151}
152
153func (repoResolver) Identity(_ context.Context, obj *models.Repository, prefix string) (models.IdentityWrapper, error) {
154 excerpt, err := obj.Repo.Identities().ResolveExcerptPrefix(prefix)
155 if err != nil {
156 return nil, err
157 }
158
159 return models.NewLazyIdentity(obj.Repo, excerpt), nil
160}
161
162func (repoResolver) UserIdentity(ctx context.Context, obj *models.Repository) (models.IdentityWrapper, error) {
163 id, err := auth.UserFromCtx(ctx, obj.Repo)
164 if err == auth.ErrNotAuthenticated {
165 return nil, nil
166 } else if err != nil {
167 return nil, err
168 }
169 return models.NewLoadedIdentity(id.Identity), nil
170}
171
172func (repoResolver) ValidLabels(_ context.Context, obj *models.Repository, after *string, before *string, first *int, last *int) (*models.LabelConnection, error) {
173 input := models.ConnectionInput{
174 Before: before,
175 After: after,
176 First: first,
177 Last: last,
178 }
179
180 edger := func(label common.Label, offset int) connections.Edge {
181 return models.LabelEdge{
182 Node: label,
183 Cursor: connections.OffsetToCursor(offset),
184 }
185 }
186
187 conMaker := func(edges []*models.LabelEdge, nodes []common.Label, info *models.PageInfo, totalCount int) (*models.LabelConnection, error) {
188 return &models.LabelConnection{
189 Edges: edges,
190 Nodes: nodes,
191 PageInfo: info,
192 TotalCount: totalCount,
193 }, nil
194 }
195
196 return connections.Connection(obj.Repo.Bugs().ValidLabels(), edger, conMaker, input)
197}