import 'source-map-support/register'; import type { ObjectLiteral } from 'typeorm'; import type { AbstractEntity } from './abstract.entity'; import type { AbstractDto } from './dto/abstract.dto'; import type { CreateTranslationDto } from './dto/create-translation.dto'; import { PageDto } from './dto/page.dto'; import { PageMetaDto } from './dto/page-meta.dto'; import type { PageOptionsDto } from './dto/page-options.dto'; import type { LanguageCode } from '../constants/language-code'; import type { KeyOfType } from './types'; declare global { interface Array { toDtos(this: T[], options?: unknown): Dto[]; getByLanguage(this: CreateTranslationDto[], languageCode: LanguageCode): string; toPageDto(this: T[], pageMetaDto: PageMetaDto, options?: unknown): PageDto; } } declare module 'typeorm' { interface SelectQueryBuilder { searchByString(q: string, columnNames: string[], options?: { formStart: boolean; }): this; withTenant(tenantId?: string | number, tenantFieldName?: string): this; paginate(this: SelectQueryBuilder, pageOptionsDto: PageOptionsDto, options?: Partial<{ takeAll: boolean; skipCount: boolean; }>): Promise<[Entity[], PageMetaDto]>; /** * Paginate and automatically map entities to DTOs in a single call. * This method combines paginate() and toPageDto() into one convenient method. * * @param pageOptionsDto Pagination options (page, pageSize, order, etc.) * @param options Configuration options * @param options.dtoOptions Options to pass to the toDto() method of each entity * @param options.skipCount Skip counting total items (improves performance) * @param options.takeAll Fetch all items without limit (ignores pageSize) * @param options.transform Optional callback to transform items before mapping to DTOs (supports both sync and async) * * @example * Basic usage - automatically maps entities to DTOs: * ```typescript * const queryBuilder = userRepository.createQueryBuilder('user'); * const pageDto = await queryBuilder.paginateAndMap(pageOptionsDto); * return pageDto; // Returns PageDto * ``` * * @example * With toDto options: * ```typescript * const queryBuilder = userRepository.createQueryBuilder('user'); * const pageDto = await queryBuilder.paginateAndMap(pageOptionsDto, { * dtoOptions: { includeRelations: true } * }); * ``` * * @example * With synchronous transform callback: * ```typescript * const queryBuilder = orderRepository.createQueryBuilder('order'); * const pageDto = await queryBuilder.paginateAndMap(pageOptionsDto, { * transform: (items) => items.filter(order => order.status === 'active') * }); * ``` * * @example * With async transform callback for complex operations: * ```typescript * const queryBuilder = orderRepository.createQueryBuilder('order'); * const pageDto = await queryBuilder.paginateAndMap(pageOptionsDto, { * transform: async (items) => { * // Perform async operations on items * const enrichedItems = await Promise.all( * items.map(async (order) => { * order.additionalData = await externalService.getData(order.id); * return order; * }) * ); * return enrichedItems.filter(order => order.isValid); * } * }); * ``` * * @example * Complete example with all options: * ```typescript * const queryBuilder = productRepository * .createQueryBuilder('product') * .leftJoinAndSelect('product.category', 'category') * .where('product.isActive = :isActive', { isActive: true }); * * const pageDto = await queryBuilder.paginateAndMap(pageOptionsDto, { * dtoOptions: { includeCategory: true }, * skipCount: false, * transform: async (items) => { * // Enrich products with external data * const enrichedProducts = await Promise.all( * items.map(async (product) => { * product.reviews = await reviewService.getReviews(product.id); * return product; * }) * ); * // Filter out products with no stock * return enrichedProducts.filter(product => product.stock > 0); * } * }); * * // Returns PageDto with enriched and filtered data * return pageDto; * ``` * * @returns Promise resolving to PageDto with mapped DTOs */ paginateAndMap(this: SelectQueryBuilder, pageOptionsDto: PageOptionsDto, options?: Partial<{ dtoOptions: DtoOptions; skipCount: boolean; takeAll: boolean; transform: (items: Entity[]) => Entity[] | Promise; }>): Promise>; leftJoinAndSelect(this: SelectQueryBuilder, property: `${A}.${Exclude, symbol>}`, alias: string, condition?: string, parameters?: ObjectLiteral): this; leftJoin(this: SelectQueryBuilder, property: `${A}.${Exclude, symbol>}`, alias: string, condition?: string, parameters?: ObjectLiteral): this; innerJoinAndSelect(this: SelectQueryBuilder, property: `${A}.${Exclude, symbol>}`, alias: string, condition?: string, parameters?: ObjectLiteral): this; innerJoin(this: SelectQueryBuilder, property: `${A}.${Exclude, symbol>}`, alias: string, condition?: string, parameters?: ObjectLiteral): this; /** * Iterate over entity results in batches using async iteration. * * @param options.batchSize Number of entities to retrieve per batch (default: 1000) * * @example * ```typescript * const queryBuilder = repository.createQueryBuilder('entity'); * * for await (const batch of queryBuilder.iterate({ batchSize: 500 })) { * console.log(`Processing batch of ${batch.length} entities`); * // Process each batch of entities * await processEntities(batch); * } * ``` * * @returns An async iterator that yields arrays of entities */ iterate(this: SelectQueryBuilder, options?: { batchSize?: number; }): AsyncIterableIterator; /** * Process entity results in batches by calling a callback function. * The callback can accept either individual entities or batches of entities. * * @param callback Function to process each entity or batch of entities * @param options * @param options.batchSize Number of entities to retrieve per batch (default: 1000) * @param options.mode Whether to pass entities individually or as batches to the callback (default: 'batch') * * @example * Processing individual entities: * ```typescript * const queryBuilder = repository.createQueryBuilder('entity'); * * await queryBuilder.eachBatch( * async (entity) => { * // Process each individual entity * console.log(`Processing entity: ${entity.id}`); * await processEntity(entity); * }, * { batchSize: 100, mode: 'single' } * ); * ``` * * @example * Processing batches of entities: * ```typescript * const queryBuilder = repository.createQueryBuilder('entity'); * * await queryBuilder.eachBatch( * async (batch) => { * // Process each batch of entities * console.log(`Processing batch of ${batch.length} entities`); * await processEntities(batch); * }, * { batchSize: 500, mode: 'batch' } * ); * ``` */ eachBatch(this: SelectQueryBuilder, callback: (item: Entity) => Promise | void, options?: { batchSize?: number; mode?: 'single'; }): Promise; eachBatch(this: SelectQueryBuilder, callback: (items: Entity[]) => Promise | void, options?: { batchSize?: number; mode?: 'batch'; }): Promise; findField(this: SelectQueryBuilder, field: K): Promise; } }