@decaf-ts/core
Version:
Core persistence module for the decaf framework
112 lines (111 loc) • 5.78 kB
TypeScript
import { Model } from "@decaf-ts/decorator-validation";
import type { Executor, RawExecutor } from "../interfaces";
import type { FromSelector, GroupBySelector, OrderBySelector, SelectSelector } from "./selectors";
import { Condition } from "./Condition";
import type { CountOption, DistinctOption, LimitOption, MaxOption, MinOption, OffsetOption, OrderAndGroupOption, PreparableStatementExecutor, SelectOption, StatementExecutor, WhereOption } from "./options";
import { Paginatable } from "../interfaces/Paginatable";
import { Paginator } from "./Paginator";
import { Adapter, AdapterFlags, type ContextOf } from "../persistence";
import { Logger } from "@decaf-ts/logging";
import { Constructor } from "@decaf-ts/decoration";
import { type ContextualArgs, ContextualLoggedClass, type MaybeContextualArg } from "../utils/index";
import { PreparedStatement } from "./types";
/**
* @description Base class for database query statements
* @summary Provides a foundation for building and executing database queries
*
* This abstract class implements the query builder pattern for constructing
* database queries. It supports various query operations like select, from,
* where, orderBy, groupBy, limit, and offset. It also provides methods for
* executing queries and handling pagination.
*
* @template Q - The query type specific to the database adapter
* @template M - The model type this statement operates on
* @template R - The return type of the query
* @param {Adapter<any, Q, any, any>} adapter - The database adapter to use for executing queries
* @class Statement
* @example
* // Create a statement to query users
* const statement = new SQLStatement(adapter);
* const users = await statement
* .select()
* .from(User)
* .where(Condition.attribute("status").eq("active"))
* .orderBy(["createdAt", "DESC"])
* .limit(10)
* .execute();
*
* // Use pagination
* const paginator = await statement
* .select()
* .from(User)
* .paginate(20); // 20 users per page
*
* @mermaid
* sequenceDiagram
* participant Client
* participant Statement
* participant Adapter
* participant Database
*
* Client->>Statement: select()
* Client->>Statement: from(Model)
* Client->>Statement: where(condition)
* Client->>Statement: orderBy([field, direction])
* Client->>Statement: limit(value)
* Client->>Statement: execute()
* Statement->>Statement: build()
* Statement->>Adapter: raw(query)
* Adapter->>Database: execute query
* Database-->>Adapter: return results
* Adapter-->>Statement: return processed results
* Statement-->>Client: return final results
*/
export declare abstract class Statement<M extends Model, A extends Adapter<any, any, any, any>, R, Q = A extends Adapter<any, any, infer Q, any> ? Q : never> extends ContextualLoggedClass<ContextOf<A>> implements Executor<R>, RawExecutor<Q>, Paginatable<M, R, Q> {
protected adapter: Adapter<any, any, Q, any>;
protected overrides?: Partial<AdapterFlags> | undefined;
protected readonly selectSelector?: SelectSelector<M>[];
protected distinctSelector?: SelectSelector<M>;
protected maxSelector?: SelectSelector<M>;
protected minSelector?: SelectSelector<M>;
protected countSelector?: SelectSelector<M>;
protected fromSelector: Constructor<M>;
protected whereCondition?: Condition<M>;
protected orderBySelector?: OrderBySelector<M>;
protected groupBySelector?: GroupBySelector<M>;
protected limitSelector?: number;
protected offsetSelector?: number;
protected prepared?: PreparedStatement<M>;
protected constructor(adapter: Adapter<any, any, Q, any>, overrides?: Partial<AdapterFlags> | undefined);
protected get log(): Logger;
select<S extends readonly SelectSelector<M>[]>(): SelectOption<M, M[]>;
select<S extends readonly SelectSelector<M>[]>(selector: readonly [...S]): SelectOption<M, Pick<M, S[number]>[]>;
distinct<S extends SelectSelector<M>>(selector: S): DistinctOption<M, M[S][]>;
max<S extends SelectSelector<M>>(selector: S): MaxOption<M, M[S]>;
min<S extends SelectSelector<M>>(selector: S): MinOption<M, M[S]>;
count<S extends SelectSelector<M>>(selector?: S): CountOption<M, number>;
from(selector: FromSelector<M>): WhereOption<M, R>;
where(condition: Condition<M>): OrderAndGroupOption<M, R>;
orderBy(selector: OrderBySelector<M>): LimitOption<M, R> & OffsetOption<M, R>;
groupBy(selector: GroupBySelector<M>): LimitOption<M, R>;
limit(value: number): OffsetOption<M, R>;
offset(value: number): PreparableStatementExecutor<M, R>;
execute(...args: MaybeContextualArg<ContextOf<A>>): Promise<R>;
protected executePrepared(...argz: MaybeContextualArg<ContextOf<A>>): Promise<R>;
raw<R>(rawInput: Q, ...args: ContextualArgs<ContextOf<A>>): Promise<R>;
protected prepareCondition(condition: Condition<any>, ctx: ContextOf<A>): PreparedStatement<any>;
protected squash(ctx: ContextOf<A>): PreparedStatement<any> | undefined;
prepare(ctx?: ContextOf<A>): Promise<StatementExecutor<M, R>>;
protected isSimpleQuery(): boolean;
protected abstract build(): Q;
protected abstract parseCondition(condition: Condition<M>, ...args: any[]): Q;
/**
* @description Creates a paginator for the query
* @summary Builds the query and wraps it in a RamPaginator to enable pagination of results.
* This allows retrieving large result sets in smaller chunks.
* @param {number} size - The page size (number of results per page)
* @return {Promise<Paginator<M, R, RawRamQuery<M>>>} A promise that resolves to a paginator for the query
*/
paginate(size: number, ...args: MaybeContextualArg<ContextOf<A>>): Promise<Paginator<M, R, Q>>;
toString(): string;
}