diff --git a/.custom-gcl.yml b/.custom-gcl.yml index 10b9ba2..52fc938 100644 --- a/.custom-gcl.yml +++ b/.custom-gcl.yml @@ -1,5 +1,5 @@ --- -version: v2.12.2 +version: v2.13.1 plugins: - module: "github.com/manuelarte/testcomments" import: "github.com/manuelarte/testcomments/plugin" diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 1ad0d80..dcc8d29 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -83,4 +83,4 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@82606bf257cbaff209d206a39f5134f0cfbfd2ee # v9.2.1 with: - version: v2.12 + version: v2.13 diff --git a/.golangci.yml b/.golangci.yml index 10bd1b0..68129b2 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -15,7 +15,8 @@ formatters: - pattern: "interface{}" replacement: "any" gofumpt: - extra-rules: true + extra: + group-params: true gci: sections: - standard @@ -32,6 +33,7 @@ linters: - err113 - errchkjson - exhaustruct + - exhaustruct_v5 - forcetypeassert - ginkgolinter # Related to Ginkgo. - goheader @@ -42,8 +44,8 @@ linters: - intrange - ireturn - maintidx - - noinlineerr # I prefer inlined errors. - nlreturn + - noinlineerr # I prefer inlined errors. - prealloc - promlinter # Related to prometheus. - protogetter # Related to protocol buffer. @@ -51,9 +53,7 @@ linters: - sqlclosecheck # Related to SQL. - tagliatelle - testpackage - - thelper - varnamelen - - wrapcheck - wsl # Deprecated, use wsl_v5 instead. - zerologlint # keep-sorted end @@ -121,6 +121,11 @@ linters: paramsOnly: false underef: skipRecvDeref: false + godoclint: + default: all + options: + max-len: + length: 120 godox: keywords: - FIXME @@ -177,6 +182,7 @@ linters: - funlen - gocognit - goconst + - godoclint - gosec path: _test\.go diff --git a/cursorpagination/errors.go b/cursorpagination/errors.go index 4d227bc..df95330 100644 --- a/cursorpagination/errors.go +++ b/cursorpagination/errors.go @@ -7,17 +7,22 @@ import ( ) var ( - ErrSizeCantBeNegative = errors.New("size can't be negative") - ErrCursorsRequired = errors.New("order is required") - ErrOrderNotValid = errors.New("order is not valid") - _ error = new(CursorValuesNotValidError) + // ErrSizeCantBeNegative is returned when the size is negative. + ErrSizeCantBeNegative = errors.New("size can't be negative") + // ErrCursorsRequired is returned when the order is required. + ErrCursorsRequired = errors.New("order is required") + // ErrOrderNotValid is returned when the order is not valid. + ErrOrderNotValid = errors.New("order is not valid") + _ error = new(CursorValuesNotValidError) ) +// CursorValuesNotValidError is an error type that represents an invalid cursor values. type CursorValuesNotValidError struct { CursorsHaveValues []string CursorsNilValue []string } +// Error returns the error message. func (c CursorValuesNotValidError) Error() string { return fmt.Sprintf( "some cursor have values and some others don't, with:[%v], without[%v]", @@ -26,7 +31,7 @@ func (c CursorValuesNotValidError) Error() string { ) } -// Is allows errors.Is to compare CursorValuesNotValidError values even though +// Is allows [errors.Is] to compare CursorValuesNotValidError values even though // the struct contains slice fields (which are not directly comparable). // It returns true when the target error is a CursorValuesNotValidError (or // pointer to) and both slices have the same contents in the same order. diff --git a/cursorpagination/pagination.go b/cursorpagination/pagination.go index 90b68fc..3da7b1b 100644 --- a/cursorpagination/pagination.go +++ b/cursorpagination/pagination.go @@ -8,6 +8,7 @@ import ( ) type ( + // Cursor represents a cursor. //go:structinit Cursor struct { order pagegeneric.Order @@ -107,6 +108,7 @@ func (p *Pagination) Cursors() []Cursor { return slices.Clone(p.cursors) } +// TotalElements returns the total elements. func (p *Pagination) TotalElements() (int64, bool) { p.mu.RLock() defer p.mu.RUnlock() @@ -138,6 +140,7 @@ func (p *Pagination) IsUnPaged() bool { return p.size == 0 && len(p.cursors) == 0 } +// IsTotalElementsSet Check whether the total elements are set. func (p *Pagination) IsTotalElementsSet() bool { p.mu.RLock() defer p.mu.RUnlock() @@ -198,6 +201,7 @@ func newCursor(order pagegeneric.Order, value any) Cursor { return Cursor{order: order, value: value} } +// Column returns the cursor column. func (c Cursor) Column() string { return c.order.Column() } diff --git a/docs.go b/docs.go new file mode 100644 index 0000000..8045ec2 --- /dev/null +++ b/docs.go @@ -0,0 +1,4 @@ +// Package pagorminator providers pagination utilities for GORM. +// It provides two types of pagination: cursor-based and page-based. +// It also provides a generic interface for pagination that can be used to implement custom pagination strategies. +package pagorminator diff --git a/models.go b/models.go index b91bc3a..b8fb56c 100644 --- a/models.go +++ b/models.go @@ -18,6 +18,7 @@ var ( ) type ( + // PaginationRequest is the interface that contains the information about the pagination. PaginationRequest interface { // Size returns the pagination size, a.k.a. limit Size() int diff --git a/pagegeneric/errors.go b/pagegeneric/errors.go index 6394bad..288e402 100644 --- a/pagegeneric/errors.go +++ b/pagegeneric/errors.go @@ -13,6 +13,7 @@ type ( } ) +// Error returns the error message. func (e TotalElementsNotValidError) Error() string { return fmt.Sprintf("total elements is not valid: %d", e.TotalElements) } diff --git a/pagegeneric/sort.go b/pagegeneric/sort.go index a7aa17f..3271915 100644 --- a/pagegeneric/sort.go +++ b/pagegeneric/sort.go @@ -18,6 +18,7 @@ type ( order() } + // Sort represents a collection of Order. Sort []Order // Asc is ascending order. @@ -27,20 +28,24 @@ type ( Desc string ) +// Column returns the column name of the order. func (a Asc) Column() string { return string(a) } +// GormString returns the string representation of the order for gorm. func (a Asc) GormString() string { return fmt.Sprintf("%s ASC", a) } func (a Asc) order() {} +// Column returns the column name of the order. func (d Desc) Column() string { return string(d) } +// GormString returns the string representation of the order for gorm. func (d Desc) GormString() string { return fmt.Sprintf("%s DESC", d) } @@ -57,6 +62,7 @@ func Unsorted() Sort { return Sort{} } +// String returns the string representation of the sort. func (s Sort) String() string { orderStrings := make([]string, len(s)) for i, order := range s { diff --git a/pagepagination/errors.go b/pagepagination/errors.go index 739245f..ca34baa 100644 --- a/pagepagination/errors.go +++ b/pagepagination/errors.go @@ -3,7 +3,10 @@ package pagepagination import "errors" var ( + // ErrPageCantBeNegative is an error type that represents an invalid page value. ErrPageCantBeNegative = errors.New("page number can't be negative") + // ErrSizeCantBeNegative is an error type that represents an invalid size value. ErrSizeCantBeNegative = errors.New("size can't be negative") - ErrSizeNotAllowed = errors.New("size is not allowed") + // ErrSizeNotAllowed is an error type that represents an invalid size value. + ErrSizeNotAllowed = errors.New("size is not allowed") ) diff --git a/pagepagination/pagination.go b/pagepagination/pagination.go index b4dd1da..14583bb 100644 --- a/pagepagination/pagination.go +++ b/pagepagination/pagination.go @@ -127,6 +127,7 @@ func (p *Pagination) IsSort() bool { return len(p.sort) > 0 } +// IsTotalElementsSet Check whether the total elements are set. func (p *Pagination) IsTotalElementsSet() bool { p.mu.RLock() defer p.mu.RUnlock() diff --git a/pagorminator.go b/pagorminator.go index 409dd75..07c9d6a 100644 --- a/pagorminator.go +++ b/pagorminator.go @@ -22,6 +22,7 @@ type PaGorminator struct { Debug bool } +// Name returns the name of the plugin. func (p PaGorminator) Name() string { return "pagorminator" } diff --git a/pagorminator_test.go b/pagorminator_test.go index e92e7c3..59ef02b 100644 --- a/pagorminator_test.go +++ b/pagorminator_test.go @@ -1463,6 +1463,8 @@ func TestCursorPaginationTotalElementsIgnoreCursorWhere(t *testing.T) { } func setupDB(t *testing.T) *gorm.DB { + t.Helper() + db, err := gorm.Open(sqlite.Open(fmt.Sprintf("file:%s?mode=memory&cache=shared", t.Name())), &gorm.Config{}) if err != nil { t.Fatal("failed to connect database") @@ -1587,6 +1589,8 @@ func compareTestStructs(t *testing.T, got, want []*TestStruct) { } func comparePaginations(t *testing.T, got Pagination, want any) { + t.Helper() + switch actual := got.(type) { case *pagepagination.Pagination: if diff := cmp.Diff(