@decaf-ts/core
Version:
Core persistence module for the decaf framework
106 lines (105 loc) • 4.63 kB
TypeScript
import { Adapter } from "../persistence";
import { Model } from "@decaf-ts/decorator-validation";
import { Constructor } from "@decaf-ts/decoration";
import { LoggedClass } from "@decaf-ts/logging";
import { ContextualArgs, MaybeContextualArg } from "../utils/index";
import { PreparedStatement } from "./types";
/**
* @description Handles pagination for database queries
* @summary Provides functionality for navigating through paginated query results
*
* This abstract class manages the state and navigation of paginated database query results.
* It tracks the current page, total pages, and record count, and provides methods for
* moving between pages.
*
* @template M - The model type this paginator operates on
* @template R - The return type of the paginated query (defaults to M[])
* @template Q - The query type (defaults to any)
* @param {Adapter<any, Q, any, any>} adapter - The database adapter to use for executing queries
* @param {Q} query - The query to paginate
* @param {number} size - The number of records per page
* @param {Constructor<M>} clazz - The constructor for the model type
* @class Paginator
* @example
* // Create a paginator for a user query
* const userQuery = db.select().from(User);
* const paginator = await userQuery.paginate(10); // 10 users per page
*
* // Get the first page of results
* const firstPage = await paginator.page(1);
*
* // Navigate to the next page
* const secondPage = await paginator.next();
*
* // Get information about the pagination
* console.log(`Page ${paginator.current} of ${paginator.total}, ${paginator.count} total records`);
*
* @mermaid
* sequenceDiagram
* participant Client
* participant Paginator
* participant Adapter
* participant Database
*
* Client->>Paginator: new Paginator(adapter, query, size, clazz)
* Client->>Paginator: page(1)
* Paginator->>Paginator: validatePage(1)
* Paginator->>Paginator: prepare(query)
* Paginator->>Adapter: execute query with pagination
* Adapter->>Database: execute query
* Database-->>Adapter: return results
* Adapter-->>Paginator: return results
* Paginator-->>Client: return page results
*
* Client->>Paginator: next()
* Paginator->>Paginator: page(current + 1)
* Paginator->>Paginator: validatePage(current + 1)
* Paginator->>Adapter: execute query with pagination
* Adapter->>Database: execute query
* Database-->>Adapter: return results
* Adapter-->>Paginator: return results
* Paginator-->>Client: return page results
*/
export declare abstract class Paginator<M extends Model, R = M[], Q = any> extends LoggedClass {
protected readonly adapter: Adapter<any, any, Q, any>;
protected readonly query: Q | PreparedStatement<M>;
readonly size: number;
protected readonly clazz: Constructor<M>;
protected _currentPage: number;
protected _totalPages: number;
protected _recordCount: number;
protected _bookmark?: number | string;
protected limit: number;
private _statement?;
get current(): number;
get total(): number;
get count(): number;
protected get statement(): Q;
protected constructor(adapter: Adapter<any, any, Q, any>, query: Q | PreparedStatement<M>, size: number, clazz: Constructor<M>);
protected isPreparedStatement(): "" | RegExpMatchArray | null;
protected pagePrefix(page?: number, ...args: MaybeContextualArg<any>): Promise<any[]>;
protected pagePrepared(page?: number, ...argz: ContextualArgs<any>): Promise<M[]>;
/**
* @description Prepares a statement for pagination
* @summary Modifies the raw query statement to include pagination parameters.
* This protected method sets the limit parameter on the query to match the page size.
* @param {RawRamQuery<M>} rawStatement - The original query statement
* @return {RawRamQuery<M>} The modified query with pagination parameters
*/
protected abstract prepare(rawStatement: Q): Q;
next(...args: MaybeContextualArg<any>): Promise<R>;
previous(...args: MaybeContextualArg<any>): Promise<R>;
protected validatePage(page: number): number;
page(page?: number, ...args: MaybeContextualArg<any>): Promise<R>;
serialize(data: M[], toString?: boolean): string | SerializedPage<M>;
apply(serialization: string | SerializedPage<M>): M[];
static deserialize<M extends Model>(str: string): SerializedPage<M>;
static isSerializedPage(obj: SerializedPage<any> | any): any;
}
export type SerializedPage<M extends Model> = {
current: number;
total: number;
count: number;
data: M[];
bookmark?: number | string;
};