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  }