import { ArrayPrimitive, InferredType, KeysOf, KeysOfNonPrimitives, NonArrayPrimitive, Primitive, TypeOf } from 'tsds-tools'; import { FindManyOptions, FindOperator, FindOptionsWhere, ObjectLiteral } from 'typeorm'; import { Repository } from '../repository'; import { NestedKeysOf, NestedKeysOf2, TypeOfNested } from './nested-types'; export declare const DEFAULT_PAGE_SIZE = 20; export declare const DEFAULT_CACHE_TIME: number; type QueryBuilder = (q: QueryWithWhere) => QueryWithWhere | TerminalQuery; /** * Context flags to track query building state for runtime validation */ interface QueryContext { insideWhereJoin: boolean; insideWhereOr: boolean; } export declare function isQuery(query: any): query is Query; export declare function isTerminalQuery(query: any): query is TerminalQuery; /** * A terminal query that restricts further where clause chaining. * * This class is returned by `whereIn()` and `whereOr()` methods to enforce * query chain ordering at compile time. TypeORM's `In()` operator can cause * unexpected behavior when combined with subsequent where clauses, so this * pattern ensures such combinations are caught during development. * * ## Why Terminal Queries Exist * * When using TypeORM's `In()` operator (via `whereIn()`), adding more where * conditions after it can lead to incorrect SQL generation. The Terminal Query * Pattern enforces that these operators must be last in your query chain. * * ## Available Methods * * After calling `whereIn()` or `whereOr()`, you can still use: * - `orderByAscending()` / `orderByDescending()` - Sort results * - `select()` - Choose specific columns * - `fetchRelation()` - Eagerly load related entities * - `loadRelationIds()` - Load only relation IDs * - `cache()` - Enable query caching * * ## Restricted Methods * * The following methods are NOT available after terminal operations: * - All `where*()` methods (e.g., `whereEqualTo()`, `whereMoreThan()`) * - `whereJoin()` * * ## Migration Guide * * If you have existing code that chains where clauses after `whereIn()`, * reorder your query to place `whereIn()` last: * * ```typescript * // Before (will cause TypeScript error) * q.whereIn('status', statuses).whereEqualTo('active', true) * * // After (correct) * q.whereEqualTo('active', true).whereIn('status', statuses) * ``` * * @see {@link TerminalPaginatedQuery} for the paginated variant * @see README.md#terminal-query-pattern for full documentation */ export declare class TerminalQuery { readonly repository: Repository; protected query: FindManyOptions; constructor(repository: Repository); static from(source: QueryWithWhere | Query | PaginatedQuery | TerminalQuery): TerminalQuery; orderByAscending>(key: Key): this; orderByDescending>(key: Key): this; select>(key: Key): this; fetchRelation, Key2 extends KeysOfNonPrimitives>, Key3 extends KeysOfNonPrimitives, Key2>>, Key4 extends KeysOfNonPrimitives, Key2>, Key3>>>(key1: Key1, key2?: Key2, key3?: Key3, key4?: Key4): this; loadRelationIds(loadRelationIds?: boolean): this; cache(cache?: boolean | number): this; toQuery(): FindManyOptions; } /** * A terminal paginated query that restricts further where clause chaining. * * This class extends {@link TerminalQuery} with pagination capabilities. It is * returned by `whereIn()` and `whereOr()` methods when called on a * {@link PaginatedQuery}. * * ## Additional Methods (beyond TerminalQuery) * * - `pagination()` - Set both limit and cursor token * - `next()` - Set the cursor token for pagination * - `limit()` - Set the page size * * ## Example * * ```typescript * const { items, next } = await userRepo.find(q => * q.whereEqualTo('active', true) * .whereIn('role', ['admin', 'moderator']) * .orderByDescending('createdAt') * .limit(25) * ) * ``` * * @see {@link TerminalQuery} for base terminal query documentation * @see README.md#terminal-query-pattern for full documentation */ export declare class TerminalPaginatedQuery extends TerminalQuery { static from(source: QueryWithWhere | Query | PaginatedQuery | TerminalQuery): TerminalPaginatedQuery; pagination(pagination: { next?: string | null; limit?: number | null; } | null | undefined): this; next(next: string | null | undefined): this; limit(limit: number | null | undefined): this; } export declare class QueryWithWhere { readonly repository: Repository; protected query: FindManyOptions; protected context: QueryContext; constructor(repository: Repository); static from | Query | PaginatedQuery>(query: QueryType): QueryWithWhere; /** * Filter by equal value - supports both direct and nested field paths * * @example Direct field * q.whereEqualTo('status', 'active') * * @example Nested relation field (1 level) * q.whereEqualTo('author.id', userId) * * @example Nested relation field (2 levels) * q.whereEqualTo('author.profile.age', 25) */ whereEqualTo>(key: Key, value: TypeOf | undefined): this; whereEqualTo>(path: Path, value: NoInfer> | undefined): this; whereEqualTo>(path: Path, value: NoInfer> | undefined): this; /** * Filter by not equal value - supports both direct and nested field paths */ whereNotEqualTo>(key: Key, value: TypeOf | undefined): this; whereNotEqualTo>(path: Path, value: NoInfer> | undefined): this; whereNotEqualTo>(path: Path, value: NoInfer> | undefined): this; /** * Filter by more than value - supports both direct and nested field paths */ whereMoreThan>(key: Key, value: TypeOf | undefined): this; whereMoreThan>(path: Path, value: NoInfer> | undefined): this; whereMoreThan>(path: Path, value: NoInfer> | undefined): this; /** * Filter by not more than value - supports both direct and nested field paths */ whereNotMoreThan>(key: Key, value: TypeOf | undefined): this; whereNotMoreThan>(path: Path, value: NoInfer> | undefined): this; whereNotMoreThan>(path: Path, value: NoInfer> | undefined): this; /** * Filter by more than or equal value - supports both direct and nested field paths */ whereMoreThanOrEqual>(key: Key, value: TypeOf | undefined): this; whereMoreThanOrEqual>(path: Path, value: NoInfer> | undefined): this; whereMoreThanOrEqual>(path: Path, value: NoInfer> | undefined): this; /** * Filter by not more than or equal value - supports both direct and nested field paths */ whereNotMoreThanOrEqual>(key: Key, value: TypeOf | undefined): this; whereNotMoreThanOrEqual>(path: Path, value: NoInfer> | undefined): this; whereNotMoreThanOrEqual>(path: Path, value: NoInfer> | undefined): this; /** * Filter by less than value - supports both direct and nested field paths */ whereLessThan>(key: Key, value: TypeOf | undefined): this; whereLessThan>(path: Path, value: NoInfer> | undefined): this; whereLessThan>(path: Path, value: NoInfer> | undefined): this; /** * Filter by not less than value - supports both direct and nested field paths */ whereNotLessThan>(key: Key, value: TypeOf | undefined): this; whereNotLessThan>(path: Path, value: NoInfer> | undefined): this; whereNotLessThan>(path: Path, value: NoInfer> | undefined): this; /** * Filter by less than or equal value - supports both direct and nested field paths */ whereLessThanOrEqual>(key: Key, value: TypeOf | undefined): this; whereLessThanOrEqual>(path: Path, value: NoInfer> | undefined): this; whereLessThanOrEqual>(path: Path, value: NoInfer> | undefined): this; /** * Filter by not less than or equal value - supports both direct and nested field paths */ whereNotLessThanOrEqual>(key: Key, value: TypeOf | undefined): this; whereNotLessThanOrEqual>(path: Path, value: NoInfer> | undefined): this; whereNotLessThanOrEqual>(path: Path, value: NoInfer> | undefined): this; /** * Filter by between values - supports both direct and nested field paths */ whereBetween>(key: Key, from: TypeOf | undefined, to: TypeOf | undefined): this; whereBetween>(path: Path, from: TypeOfNested | undefined, to: TypeOfNested | undefined): this; whereBetween>(path: Path, from: TypeOfNested | undefined, to: TypeOfNested | undefined): this; /** * Filter by text containing value - supports both direct and nested field paths */ whereTextContains>(key: Key, value: TypeOf | undefined): this; whereTextContains>(path: Path, value: NoInfer> | undefined): this; whereTextContains>(path: Path, value: NoInfer> | undefined): this; /** * Filter by text starting with value - supports both direct and nested field paths */ whereTextStartsWith>(key: Key, value: TypeOf | undefined): this; whereTextStartsWith>(path: Path, value: NoInfer> | undefined): this; whereTextStartsWith>(path: Path, value: NoInfer> | undefined): this; /** * Filter by text ending with value - supports both direct and nested field paths */ whereTextEndsWith>(key: Key, value: TypeOf | undefined): this; whereTextEndsWith>(path: Path, value: NoInfer> | undefined): this; whereTextEndsWith>(path: Path, value: NoInfer> | undefined): this; /** * Filter by text containing value (case insensitive) - supports both direct and nested field paths */ whereTextInAnyCaseContains>(key: Key, value: TypeOf | undefined): this; whereTextInAnyCaseContains>(path: Path, value: NoInfer> | undefined): this; whereTextInAnyCaseContains>(path: Path, value: NoInfer> | undefined): this; /** * Filter by text starting with value (case insensitive) - supports both direct and nested field paths */ whereTextInAnyCaseStartsWith>(key: Key, value: TypeOf | undefined): this; whereTextInAnyCaseStartsWith>(path: Path, value: NoInfer> | undefined): this; whereTextInAnyCaseStartsWith>(path: Path, value: NoInfer> | undefined): this; /** * Filter by text ending with value (case insensitive) - supports both direct and nested field paths */ whereTextInAnyCaseEndsWith>(key: Key, value: TypeOf | undefined): this; whereTextInAnyCaseEndsWith>(path: Path, value: NoInfer> | undefined): this; whereTextInAnyCaseEndsWith>(path: Path, value: NoInfer> | undefined): this; /** * Filter by value in array - supports both direct and nested field paths * Note: This is a terminal operation and returns a TerminalQuery */ whereIn>(key: Key, value: TypeOf[] | undefined): TerminalQuery; whereIn>(path: Path, value: NoInfer>[] | undefined): TerminalQuery; whereIn>(path: Path, value: NoInfer>[] | undefined): TerminalQuery; /** * Filter by null value - supports both direct and nested field paths */ whereIsNull>(key: Key): this; whereIsNull>(path: Path): this; whereIsNull>(path: Path): this; /** * Filter by not null value - supports both direct and nested field paths */ whereIsNotNull>(key: Key): this; whereIsNotNull>(path: Path): this; whereIsNotNull>(path: Path): this; whereArrayContains>(key: Key, value: InferredType | undefined): this; whereArrayContainsAny>(key: Key, value: InferredType[] | undefined): this; whereJoin, Type extends InferredType & ObjectLiteral>(key: Key, queryBuilder: QueryBuilder): this; protected setWhere>(key: Key, where: FindOperator | FindOptionsWhere | FindOptionsWhere[] | TypeOf | undefined): this; /** * Helper method to handle nested path where conditions * Automatically adds the relation and builds the nested where structure */ protected setNestedWhere(path: string, value: unknown): this; whereOr(queryBuilder1: QueryBuilder, queryBuilder2: QueryBuilder, ...otherQueryBuilder: QueryBuilder[]): TerminalQuery; toQuery(): FindManyOptions; } export declare class Query extends QueryWithWhere { static from | Query | PaginatedQuery>(query: QueryType): Query; orderByAscending>(key: Key): this; orderByDescending>(key: Key): this; select>(key: Key): this; fetchRelation, Key2 extends KeysOfNonPrimitives>, Key3 extends KeysOfNonPrimitives, Key2>>, Key4 extends KeysOfNonPrimitives, Key2>, Key3>>>(key1: Key1, key2?: Key2, key3?: Key3, key4?: Key4): this; loadRelationIds(loadRelationIds?: boolean): this; cache(cache?: boolean | number): this; } export declare class PaginatedQuery extends Query { static from | Query | PaginatedQuery | TerminalQuery | TerminalPaginatedQuery>(query: QueryType): PaginatedQuery; pagination(pagination: { next?: string | null; limit?: number | null; } | null | undefined): this; next(next: string | null | undefined): this; limit(limit: number | null | undefined): this; whereIn>(key: Key, value: TypeOf[] | undefined): TerminalPaginatedQuery; whereIn>(path: Path, value: NoInfer>[] | undefined): TerminalPaginatedQuery; whereIn>(path: Path, value: NoInfer>[] | undefined): TerminalPaginatedQuery; whereOr(queryBuilder1: QueryBuilder, queryBuilder2: QueryBuilder, ...otherQueryBuilder: QueryBuilder[]): TerminalPaginatedQuery; } export {};