EHonda.Pagination.CursorBased 0.6.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package EHonda.Pagination.CursorBased --version 0.6.0
                    
NuGet\Install-Package EHonda.Pagination.CursorBased -Version 0.6.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EHonda.Pagination.CursorBased" Version="0.6.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EHonda.Pagination.CursorBased" Version="0.6.0" />
                    
Directory.Packages.props
<PackageReference Include="EHonda.Pagination.CursorBased" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EHonda.Pagination.CursorBased --version 0.6.0
                    
#r "nuget: EHonda.Pagination.CursorBased, 0.6.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EHonda.Pagination.CursorBased@0.6.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EHonda.Pagination.CursorBased&version=0.6.0
                    
Install as a Cake Addin
#tool nuget:?package=EHonda.Pagination.CursorBased&version=0.6.0
                    
Install as a Cake Tool

EHonda.Pagination

🚧 WIP 🚧

Description

EHonda.Pagination is a .NET library that provides a flexible and extensible way to handle pagination. It offers core interfaces and building blocks, along with implementations for cursor-based, offset-based, and sequential pagination. This repository also includes sample projects in the samples directory to demonstrate the library's usage in various scenarios.

Features and Examples

This library provides several ways to handle pagination, catering to different API designs. Below are some examples of how to use the core pagination handlers, focusing on the fluent builder syntax for a more declarative setup. For more detailed and runnable examples, please refer to the projects in the samples directory.

Offset-Based Pagination

Offset-based pagination uses an index or offset to retrieve specific pages of data. This is common in many web APIs.

Example using the fluent builder:

// Assumes MyPage, MyItem types, and int for the offset index.
// MyPage is the type returned by your API client, containing items and pagination details.
// e.g., public class MyPage { public List<MyItem> Items; public int CurrentOffset; public int PageSize; public int TotalItems; /* ... */ }

var apiClient = new YourApiClient(); // Your actual API client
const int initialOffset = 0;
const int pageSize = 20;

// Or just the shortcut `OffsetBased.Composite.PaginationHandlerBuilder<MyPage, MyItem>`
var handler = new OffsetBased.Composite.PaginationHandlerBuilder<MyPage, int, MyItem>()
    .WithPageRetriever(async (MyPage? prevPage, CancellationToken cancellationToken) =>
    {
        int currentOffset;
        if (prevPage == null)
        {
            currentOffset = initialOffset; // First page
        }
        else
        {
            // Calculate offset for the next page based on the previous one
            currentOffset = prevPage.CurrentOffset + prevPage.PageSize;
        }
        return await apiClient.GetPageByOffsetAsync(currentOffset, pageSize, cancellationToken);
    })
    .WithOffsetStateExtractor((MyPage pageContext, CancellationToken cancellationToken) =>
    {
        // Extract pagination state from the fetched page
        return new OffsetState<int>(
            pageContext.CurrentOffset,
            pageContext.PageSize,
            pageContext.TotalItems);
    })
    .WithItemExtractor((MyPage pageContext, CancellationToken cancellationToken) =>
    {
        // Extract items from the fetched page
        return pageContext.Items;
    })
    .Build();

await foreach (var item in handler.GetAllItemsAsync())
{
    // Process each item
}

The library provides OffsetState<TIndex> (see src/OffsetBased/OffsetState.cs) to manage the current offset. The base handler is in src/OffsetBased/PaginationHandler.cs. For concrete examples, see the samples/SpotifyPagination project.

Cursor-Based Pagination

Cursor-based pagination uses a cursor (often an item's ID or a timestamp) to mark the position from which to fetch the next set of items. This is efficient for large datasets.

Example using the fluent builder (lambda-based components):

// Assumes MyPageContext, TCursor, and MyItem types.
// MyPageContext is the type returned by your API client for a page of data.
// It should contain:
//  - A list of items (e.g., public List<MyItem> Items { get; set; })
//  - The cursor for the next page (e.g., public TCursor? NextPageCursor { get; set; })

var apiClient = new YourApiClient(); // Your actual API client

// If TCursor is string, you can use the shortcut: 
// var handler = new CursorBased.Composite.PaginationHandlerBuilder<MyPageContext, MyItem>()
var handler = new CursorBased.Composite.PaginationHandlerBuilder<MyPageContext, TCursor, MyItem>()
    .WithPageRetriever(async (MyPageContext? prevPageContext, CancellationToken cancellationToken) =>
    {
        if (prevPageContext == null)
        {
            // First call: fetch the initial page (e.g., API might not require a cursor or use a default one).
            return await apiClient.FetchPageAsync(null, cancellationToken); 
        }
        // Subsequent call: fetch the next page using the cursor from the *previous* page's context.
        // prevPageContext.NextPageCursor would have been extracted by WithCursorExtractor in the previous step.
        return await apiClient.FetchPageAsync(prevPageContext.NextPageCursor, cancellationToken);
    })
    // Or async: (MyPageContext currentPageContext, CancellationToken ct) => Task.FromResult(currentPageContext.NextPageCursor)
    .WithCursorExtractor((MyPageContext currentPageContext) => 
    {
        // Extract the cursor that points to the *next* page, from the *current* page's context.
        return currentPageContext.NextPageCursor;
    })
    // Or async: (MyPageContext currentPageContext, CancellationToken ct) => currentPageContext.ItemsAsync
    .WithItemExtractor((MyPageContext currentPageContext) => 
    {
        // Extract the list of items from the *current* page's context.
        return currentPageContext.Items;
    })
    .Build();

await foreach (var item in handler.GetAllItemsAsync())
{
    // Process each item
}

The base handler is in src/CursorBased/PaginationHandler.cs. For concrete examples, see the samples/TwitchPagination (demonstrates both lambda and class-based component setup) and samples/SpotifyPagination projects.

Extensibility

All pagination handlers can be created by:

  1. Inheriting from the base classes (e.g., Sequential.PaginationHandler<TPageContext, TItem>).
  2. Using the composite PaginationHandlerBuilder for a more declarative setup (e.g., Sequential.Composite.PaginationHandlerBuilder<TPageContext, TItem>).

This allows for flexibility in how you define page retrieval, item extraction, and next-page-existence logic.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.1 151 6/23/2025
2.0.0 109 6/21/2025
1.0.0 145 6/19/2025
0.6.0 76 6/6/2025
0.5.0 97 5/24/2025
0.4.0 102 5/24/2025
0.3.0 98 5/24/2025
0.2.0 114 5/24/2025

See package release notes on GitHub: https://github.com/ehonda/Pagination/releases/tag/v0.6.0