github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/label/http.go (about) 1 package label 2 3 import ( 4 "fmt" 5 "net/http" 6 "strings" 7 8 "github.com/ungtb10d/cli/v2/api" 9 "github.com/ungtb10d/cli/v2/internal/ghrepo" 10 ) 11 12 const ( 13 maxPageSize = 100 14 15 defaultOrder = "asc" 16 defaultSort = "created" 17 ) 18 19 var defaultFields = []string{ 20 "color", 21 "description", 22 "name", 23 } 24 25 type listLabelsResponseData struct { 26 Repository struct { 27 Labels struct { 28 TotalCount int 29 Nodes []label 30 PageInfo struct { 31 HasNextPage bool 32 EndCursor string 33 } 34 } 35 } 36 } 37 38 type listQueryOptions struct { 39 Limit int 40 Query string 41 Order string 42 Sort string 43 44 fields []string 45 } 46 47 func (opts listQueryOptions) OrderBy() map[string]string { 48 // Set on copy to keep original intact. 49 if opts.Order == "" { 50 opts.Order = defaultOrder 51 } 52 if opts.Sort == "" { 53 opts.Sort = defaultSort 54 } 55 56 field := strings.ToUpper(opts.Sort) 57 if opts.Sort == "created" { 58 field = "CREATED_AT" 59 } 60 return map[string]string{ 61 "direction": strings.ToUpper(opts.Order), 62 "field": field, 63 } 64 } 65 66 // listLabels lists the labels in the given repo. Pass -1 for limit to list all labels; 67 // otherwise, only that number of labels is returned for any number of pages. 68 func listLabels(client *http.Client, repo ghrepo.Interface, opts listQueryOptions) ([]label, int, error) { 69 if len(opts.fields) == 0 { 70 opts.fields = defaultFields 71 } 72 73 apiClient := api.NewClientFromHTTP(client) 74 fragment := fmt.Sprintf("fragment label on Label{%s}", strings.Join(opts.fields, ",")) 75 query := fragment + ` 76 query LabelList($owner: String!, $repo: String!, $limit: Int!, $endCursor: String, $query: String, $orderBy: LabelOrder) { 77 repository(owner: $owner, name: $repo) { 78 labels(first: $limit, after: $endCursor, query: $query, orderBy: $orderBy) { 79 totalCount, 80 nodes { 81 ...label 82 } 83 pageInfo { 84 hasNextPage 85 endCursor 86 } 87 } 88 } 89 }` 90 91 variables := map[string]interface{}{ 92 "owner": repo.RepoOwner(), 93 "repo": repo.RepoName(), 94 "orderBy": opts.OrderBy(), 95 "query": opts.Query, 96 } 97 98 var labels []label 99 var totalCount int 100 101 loop: 102 for { 103 var response listLabelsResponseData 104 variables["limit"] = determinePageSize(opts.Limit - len(labels)) 105 err := apiClient.GraphQL(repo.RepoHost(), query, variables, &response) 106 if err != nil { 107 return nil, 0, err 108 } 109 110 totalCount = response.Repository.Labels.TotalCount 111 112 for _, label := range response.Repository.Labels.Nodes { 113 labels = append(labels, label) 114 if len(labels) == opts.Limit { 115 break loop 116 } 117 } 118 119 if response.Repository.Labels.PageInfo.HasNextPage { 120 variables["endCursor"] = response.Repository.Labels.PageInfo.EndCursor 121 } else { 122 break 123 } 124 } 125 126 return labels, totalCount, nil 127 } 128 129 func determinePageSize(numRequestedItems int) int { 130 // If numRequestedItems is -1 then retrieve maxPageSize 131 if numRequestedItems < 0 || numRequestedItems > maxPageSize { 132 return maxPageSize 133 } 134 return numRequestedItems 135 }