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  }