Skip to content

Add pagination utilities and move Hooks to contract#21

Draft
ConsoleTVs wants to merge 8 commits into
mainfrom
feat/pagination
Draft

Add pagination utilities and move Hooks to contract#21
ConsoleTVs wants to merge 8 commits into
mainfrom
feat/pagination

Conversation

@ConsoleTVs

@ConsoleTVs ConsoleTVs commented May 30, 2026

Copy link
Copy Markdown
Member

Summary

Pagination

  • Added Page[T] struct and NewPage constructor for offset-based pagination (computes LastPage, clamps inputs)
  • Added Cursor[T] struct with NewCursor (built-in base64-JSON) and NewCursorWith (custom CursorEncoder) for cursor-based pagination
  • Added CursorValue and CursorValueWith for decoding cursor strings
  • Added request helpers: Pagination, PaginationWith, CursorPagination, CursorPaginationWith
  • Added CursorEncoderMock for testing
  • 100% test coverage on all new pagination code

Hooks refactor

  • Moved Hooks from interface (contract) + struct (framework) to concrete struct in contract
  • Mirrors the existing Session pattern — single meaningful implementation, no driver needed
  • Deleted contract/mock/hooks.go (no longer needed — use contract.NewHooks() in tests)
  • Updated request.Hooks / request.TryHooks to return *contract.Hooks
  • framework/hooks_writer.go now embeds *contract.Hooks

Breaking Changes

contract.Hooks is now a struct, not an interface

What changed: Hooks is a concrete *contract.Hooks everywhere instead of the contract.Hooks interface.

Migration:

  • Replace custom Hooks interface implementations with contract.NewHooks()
  • Update type assertions: .(contract.Hooks).(*contract.Hooks)
  • request.Hooks(r) and request.TryHooks(r) now return *contract.Hooks

Why: Only one meaningful implementation exists. Matches the Session pattern.

Add offset-based and cursor-based pagination support:

- Page[T] struct with NewPage constructor (computes LastPage, clamps inputs)
- Cursor[T] struct with NewCursor (built-in base64-JSON encoding) and
  NewCursorWith (custom CursorEncoder interface)
- CursorValue/CursorValueWith for decoding cursor strings
- Request helpers: Pagination, PaginationWith, CursorPagination,
  CursorPaginationWith (query param parsing with defaults and clamping)
- CursorEncoder mock for testing

100% test coverage on all new code.
Move the Hooks implementation from framework to contract as a concrete
struct, mirroring the Session pattern. Only one meaningful implementation
exists, so the interface indirection added no value.

- contract/hooks.go: interface replaced with mutex-protected struct
- contract/request/hooks.go: returns *contract.Hooks instead of interface
- framework/hooks_writer.go: embeds *contract.Hooks
- framework/handler.go: uses contract.NewHooks()
- Deleted contract/mock/hooks.go (use contract.NewHooks() in tests)
- Deleted framework/hooks.go and framework/hooks_test.go (moved to contract)

BREAKING CHANGE: contract.Hooks is now a concrete *Hooks struct.
Type assertions change from .(contract.Hooks) to .(*contract.Hooks).
request.Hooks() and request.TryHooks() now return *contract.Hooks.
@ConsoleTVs ConsoleTVs changed the title Add pagination utilities Add pagination utilities and move Hooks to contract May 30, 2026
Replace CursorExtractor interface and CursorExtractorFunc with a plain
encode func(T) (string, error) parameter on NewCursor. Remove
CursorEncoder interface, NewCursorWith, CursorValue, and CursorValueWith.

New API:
- NewCursor[T](items, perPage, hasNext, hasPrev, encode func(T) (string, error))
- MarshalCursor[V](value) — base64-JSON encode helper
- UnmarshalCursor[V](cursor) — base64-JSON decode helper

The encode function gives full control at the call site without
requiring methods on domain types or hidden encoding behavior.
Add usage examples in doc comments for Paginate, CursorPaginate,
CursorEncode, and CursorDecode. Rename functions from NewPage/NewCursor
to Paginate/CursorPaginate and MarshalCursor/UnmarshalCursor to
CursorEncode/CursorDecode for better API clarity.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant