github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/registry/response/pagination.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package response 5 6 import ( 7 "net/url" 8 "strconv" 9 ) 10 11 // PaginationMeta is a structure included in responses for pagination. 12 type PaginationMeta struct { 13 Limit int `json:"limit"` 14 CurrentOffset int `json:"current_offset"` 15 NextOffset *int `json:"next_offset,omitempty"` 16 PrevOffset *int `json:"prev_offset,omitempty"` 17 NextURL string `json:"next_url,omitempty"` 18 PrevURL string `json:"prev_url,omitempty"` 19 } 20 21 // NewPaginationMeta populates pagination meta data from result parameters 22 func NewPaginationMeta(offset, limit int, hasMore bool, currentURL string) PaginationMeta { 23 pm := PaginationMeta{ 24 Limit: limit, 25 CurrentOffset: offset, 26 } 27 28 // Calculate next/prev offsets, leave nil if not valid pages 29 nextOffset := offset + limit 30 if hasMore { 31 pm.NextOffset = &nextOffset 32 } 33 34 prevOffset := offset - limit 35 if prevOffset < 0 { 36 prevOffset = 0 37 } 38 if prevOffset < offset { 39 pm.PrevOffset = &prevOffset 40 } 41 42 // If URL format provided, populate URLs. Intentionally swallow URL errors for now, API should 43 // catch missing URLs if we call with bad URL arg (and we care about them being present). 44 if currentURL != "" && pm.NextOffset != nil { 45 pm.NextURL, _ = setQueryParam(currentURL, "offset", *pm.NextOffset, 0) 46 } 47 if currentURL != "" && pm.PrevOffset != nil { 48 pm.PrevURL, _ = setQueryParam(currentURL, "offset", *pm.PrevOffset, 0) 49 } 50 51 return pm 52 } 53 54 func setQueryParam(baseURL, key string, val, defaultVal int) (string, error) { 55 u, err := url.Parse(baseURL) 56 if err != nil { 57 return "", err 58 } 59 q := u.Query() 60 if val == defaultVal { 61 // elide param if it's the default value 62 q.Del(key) 63 } else { 64 q.Set(key, strconv.Itoa(val)) 65 } 66 u.RawQuery = q.Encode() 67 return u.String(), nil 68 }