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