...

Source file src/edge-infra.dev/pkg/edge/api/graph/pagination/pagination.go

Documentation: edge-infra.dev/pkg/edge/api/graph/pagination

     1  package pagination
     2  
     3  import (
     4  	"encoding/base64"
     5  	"encoding/json"
     6  	"time"
     7  
     8  	"edge-infra.dev/pkg/edge/api/graph/model"
     9  	"edge-infra.dev/pkg/edge/api/utils"
    10  )
    11  
    12  var (
    13  	// defaultCount is the default count used
    14  	// when a count is not provided.
    15  	defaultCount = 20
    16  )
    17  
    18  // Pager is a structure that holds pagination details.
    19  type Pager struct {
    20  	Cursor   string `json:"cursor"`
    21  	Offset   int    `json:"offset"`
    22  	Previous bool   `json:"previous"`
    23  }
    24  
    25  // Parse is used to parse the pagination cursor and count
    26  // and set default values if any is not provided.
    27  func Parse(cursor *string, count *int) (Pager, int) {
    28  	// defaultCursor is the default cursor value used
    29  	// when a cursor value is not provided.
    30  	defaultCursor := Pager{
    31  		Cursor:   time.Now().Format(time.RFC3339),
    32  		Offset:   0,
    33  		Previous: false,
    34  	}
    35  	startCursor := defaultCursor
    36  	if !utils.IsNullOrEmpty(cursor) {
    37  		decodedCursor, err := decode(*cursor)
    38  		if err != nil {
    39  			return defaultCursor, 0
    40  		}
    41  		decodedPager := Pager{}
    42  		err = json.Unmarshal(decodedCursor, &decodedPager)
    43  		if err != nil {
    44  			return defaultCursor, 0
    45  		}
    46  		startCursor = decodedPager
    47  	}
    48  	if count == nil {
    49  		count = &defaultCount
    50  	}
    51  	return startCursor, *count
    52  }
    53  
    54  // Overall returns a pager instance that can be returned
    55  // in an API call to paginate data.
    56  func Overall(currentCursor Pager, nextCursor, previousTime string, length, totalCount, offset int) *model.PageInfo {
    57  	encodedPreviousCursor := ""
    58  	encodedCurrentCursor := encode(currentCursor)
    59  	encodedNextCursor := ""
    60  	if length > 0 {
    61  		encodedNextCursor = encode(Pager{
    62  			Cursor:   nextCursor,
    63  			Offset:   offset + length,
    64  			Previous: false,
    65  		})
    66  	}
    67  	if previousTime != "" {
    68  		offst := offset - length
    69  		if offst < 0 {
    70  			offst = 0
    71  		}
    72  		encodedPreviousCursor = encode(Pager{
    73  			Cursor:   previousTime,
    74  			Offset:   offst,
    75  			Previous: true,
    76  		})
    77  	}
    78  	return &model.PageInfo{
    79  		PreviousCursor: encodedPreviousCursor,
    80  		CurrentCursor:  encodedCurrentCursor,
    81  		NextCursor:     encodedNextCursor,
    82  		HasNextPage:    (totalCount - offset) > length,
    83  		TotalCount:     totalCount,
    84  	}
    85  }
    86  
    87  // Encode base64 encodes the cursor value.
    88  func Encode(cursor Pager) string {
    89  	return encode(cursor)
    90  }
    91  
    92  // Decode decodes the base64 cursor value.
    93  func Decode(cursor string) ([]byte, error) {
    94  	return decode(cursor)
    95  }
    96  
    97  // encode utility value for base64 encoding a string.
    98  func encode(value Pager) string {
    99  	res, err := json.Marshal(value)
   100  	if err != nil {
   101  		return ""
   102  	}
   103  	return base64.RawStdEncoding.EncodeToString(res)
   104  }
   105  
   106  // decode a utility value for base64 decoding a string.
   107  func decode(value string) ([]byte, error) {
   108  	val, err := base64.RawStdEncoding.DecodeString(value)
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  	return val, nil
   113  }
   114  

View as plain text