paging

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 28, 2023 License: MIT Imports: 6 Imported by: 3

README

go-paging

Go pagination for SQLBoiler and gqlgen (GraphQL).

Install

go get -u "github.com/nrfta/go-paging"

Usage

  1. Add this GraphQL schema to your project.

  2. Add models to gqlgen.yml:

models:
  PageArgs:
    model: github.com/nrfta/go-paging.PageArgs

  PageInfo:
    model: github.com/nrfta/go-paging.PageInfo

  1. Add PageInfo Resolver for gqlgen
package resolvers

import (
	"github.com/nrfta/go-paging"
)

func (r *RootResolver) PageInfo() PageInfoResolver {
	return paging.NewPageInfoResolver()
}
  1. Full Example

This assumes you have the following GraphQL schema:

type Post {
  id: ID!
  name: String
}

type PostEdge {
  cursor: String
  node: Post!
}

type PostConnection {
  edges: [PostEdge!]!
  pageInfo: PageInfo!
}

type Query {
  posts(page: PageArgs): PostConnection!
}

Note that PageArgs and PageInfo is defined in schema.graphql and your should copy it to your project.

Here is what the resolver function would look like:

package resolvers

import (
  "context"

	"github.com/nrfta/go-paging"
	"github.com/volatiletech/sqlboiler/v4/queries/qm"

	"github.com/my-user/my-app/models"
)

func (r *queryResolver) Posts(ctx context.Context, page *paging.PageArgs) (*PostConnection, error) {
	var mods []qm.QueryMod

	totalCount, err := models.Posts().Count(ctx, DB)
	if err != nil {
		return &PostConnection{
			PageInfo: paging.NewEmptyPageInfo(),
		}, err
	}

	paginator := paging.NewOffsetPaginator(page, totalCount)
	mods = append(mods, paginator.QueryMods()...)

	records, err := models.Posts(mods...).All(ctx, DB)
	if err != nil {
		return &PostConnection{
			PageInfo: paging.NewEmptyPageInfo(),
		}, err
	}

	result := &PostConnection{
		PageInfo: &paginator.PageInfo,
	}

	for i, row := range records {
		result.Edges = append(result.Edges, &PostEdge{
			Cursor: paging.EncodeOffsetCursor(paginator.Offset + i + 1),
			Node:   row,
		})
	}
	return result, nil
}

License

This project is licensed under the MIT License.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DecodeOffsetCursor

func DecodeOffsetCursor(input *string) int

DecodeOffsetCursor takes a base64 string and decotes it to extract the offset from a string based on "cursor:offset:NUMBER". It defails to 0 if cannot decode or has any error.

func EncodeOffsetCursor

func EncodeOffsetCursor(offset int) *string

EncodeOffsetCursor takes an integer and encodes to a base64 string as "cursor:offset:NUMBER"

Types

type OffsetPaginator

type OffsetPaginator struct {
	Limit    int
	Offset   int
	PageInfo PageInfo
	// contains filtered or unexported fields
}

OffsetPaginator is the paginator for offset based pagination

func NewOffsetPaginator

func NewOffsetPaginator(
	page *PageArgs,
	totalCount int64,
	defaultLimit ...*int,
) OffsetPaginator

NewOffsetPaginator creates a new offset paginator

func (*OffsetPaginator) QueryMods

func (p *OffsetPaginator) QueryMods() []qm.QueryMod

QueryMods returns the sqlboilder query mods with pagination concerns

type PageArgs

type PageArgs struct {
	First *int    `json:"first,omitempty"`
	After *string `json:"after,omitempty"`
	// contains filtered or unexported fields
}

PageArgs is used as the query inputs

func WithSortBy added in v0.2.0

func WithSortBy(pa *PageArgs, isDesc bool, cols ...string) *PageArgs

type PageInfo

type PageInfo struct {
	TotalCount      func() (*int, error)
	HasPreviousPage func() (bool, error)
	HasNextPage     func() (bool, error)
	StartCursor     func() (*string, error)
	EndCursor       func() (*string, error)
}

PageInfo is the base struct for building PageInfo. It expects inline functions for all the fields We use inline functions so that one can build a lazy page info

func NewEmptyPageInfo

func NewEmptyPageInfo() *PageInfo

NewEmptyPageInfo returns a empty instance of PageInfo. Useful for when working on a new page to be able to fullfil PageInfo requirements

func NewOffsetBasedPageInfo

func NewOffsetBasedPageInfo(
	pageSize *int,
	totalCount int64,
	currentOffset int,
) PageInfo

NewOffsetBasedPageInfo returns a new PageInfo object with data filled in, based on offset pagination

type PageInfoResolver

type PageInfoResolver interface {
	HasPreviousPage(ctx context.Context, pageInfo *PageInfo) (bool, error)
	HasNextPage(ctx context.Context, pageInfo *PageInfo) (bool, error)
	TotalCount(ctx context.Context, pageInfo *PageInfo) (*int, error)
	StartCursor(ctx context.Context, pageInfo *PageInfo) (*string, error)
	EndCursor(ctx context.Context, pageInfo *PageInfo) (*string, error)
}

PageInfoResolver interface

func NewPageInfoResolver

func NewPageInfoResolver() PageInfoResolver

NewPageInfoResolver returns the resolver for PageInfo

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL