"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DeckRepository = void 0; const typeorm_1 = require("typeorm"); const ormconfig_1 = require("../ormconfig"); const DeckAggregate_1 = require("../../Domain/Deck/DeckAggregate"); const Logger_1 = require("../../Application/Services/Logger"); const AdminBypassService_1 = require("../../Application/Services/AdminBypassService"); class DeckRepository { constructor() { this.repo = ormconfig_1.AppDataSource.getRepository(DeckAggregate_1.DeckAggregate); } async create(deck) { return this.repo.save(deck); } async findByPage(from, to) { const startTime = performance.now(); try { const limit = to - from + 1; const offset = from; // Get total count for pagination const totalCount = await this.repo.count({ where: { state: (0, typeorm_1.Not)(DeckAggregate_1.State.SOFT_DELETE) } }); // Get paginated results const decks = await this.repo.find({ where: { state: (0, typeorm_1.Not)(DeckAggregate_1.State.SOFT_DELETE) }, order: { updatedate: 'DESC' }, take: limit, skip: offset }); const endTime = performance.now(); (0, Logger_1.logDatabase)('Deck page query completed', `executionTime: ${Math.round(endTime - startTime)}ms, found: ${decks.length}, total: ${totalCount}, from: ${from}, to: ${to}`); return { decks, totalCount }; } catch (error) { const endTime = performance.now(); (0, Logger_1.logDatabase)('Deck page query failed', `executionTime: ${Math.round(endTime - startTime)}ms, from: ${from}, to: ${to}`); (0, Logger_1.logError)('DeckRepository.findByPage error', error instanceof Error ? error : new Error(String(error))); throw new Error('Failed to get decks page from database'); } } async findByPageIncludingDeleted(from, to) { const startTime = performance.now(); try { const limit = to - from + 1; const offset = from; // Get total count for pagination const totalCount = await this.repo.count(); // Get paginated results const decks = await this.repo.find({ order: { updatedate: 'DESC' }, take: limit, skip: offset }); const endTime = performance.now(); (0, Logger_1.logDatabase)('Deck page query completed (including deleted)', `executionTime: ${Math.round(endTime - startTime)}ms, found: ${decks.length}, total: ${totalCount}, from: ${from}, to: ${to}`); return { decks, totalCount }; } catch (error) { const endTime = performance.now(); (0, Logger_1.logDatabase)('Deck page query failed (including deleted)', `executionTime: ${Math.round(endTime - startTime)}ms, from: ${from}, to: ${to}`); (0, Logger_1.logError)('DeckRepository.findByPageIncludingDeleted error', error instanceof Error ? error : new Error(String(error))); throw new Error('Failed to get decks page from database'); } } async findById(id) { return this.repo.findOne({ where: { id, state: (0, typeorm_1.Not)(DeckAggregate_1.State.SOFT_DELETE) } }); } async findByIdIncludingDeleted(id) { return this.repo.findOneBy({ id }); } async update(id, update) { await this.repo.update(id, update); return this.findById(id); } async delete(id) { return this.repo.delete(id); } async softDelete(id) { await this.repo.update(id, { state: DeckAggregate_1.State.SOFT_DELETE }); return this.findById(id); } async search(query, limit = 20, offset = 0) { const startTime = performance.now(); try { const searchPattern = `%${query.toLowerCase()}%`; const queryBuilder = this.repo.createQueryBuilder('deck') .where('deck.state != :softDelete', { softDelete: DeckAggregate_1.State.SOFT_DELETE }) .andWhere('LOWER(deck.name) LIKE :pattern', { pattern: searchPattern }); const totalCount = await queryBuilder.getCount(); const decks = await queryBuilder .orderBy('deck.name', 'ASC') .limit(limit) .offset(offset) .getMany(); const endTime = performance.now(); (0, Logger_1.logDatabase)('Deck search completed', `executionTime: ${Math.round(endTime - startTime)}ms, found: ${decks.length}, total: ${totalCount}, searchTerm: "${query}", limit: ${limit}, offset: ${offset}`); return { decks, totalCount }; } catch (error) { const endTime = performance.now(); (0, Logger_1.logDatabase)('Deck search failed', `executionTime: ${Math.round(endTime - startTime)}ms, searchTerm: "${query}"`); (0, Logger_1.logError)('DeckRepository.search error', error instanceof Error ? error : new Error(String(error))); throw new Error('Failed to search decks in database'); } } async searchIncludingDeleted(query, limit = 20, offset = 0) { const startTime = performance.now(); try { const searchPattern = `%${query.toLowerCase()}%`; const queryBuilder = this.repo.createQueryBuilder('deck') .where('LOWER(deck.name) LIKE :pattern', { pattern: searchPattern }); const totalCount = await queryBuilder.getCount(); const decks = await queryBuilder .orderBy('deck.name', 'ASC') .limit(limit) .offset(offset) .getMany(); const endTime = performance.now(); (0, Logger_1.logDatabase)('Deck search completed (including deleted)', `executionTime: ${Math.round(endTime - startTime)}ms, found: ${decks.length}, total: ${totalCount}, searchTerm: "${query}", limit: ${limit}, offset: ${offset}`); return { decks, totalCount }; } catch (error) { const endTime = performance.now(); (0, Logger_1.logDatabase)('Deck search failed (including deleted)', `executionTime: ${Math.round(endTime - startTime)}ms, searchTerm: "${query}"`); (0, Logger_1.logError)('DeckRepository.searchIncludingDeleted error', error instanceof Error ? error : new Error(String(error))); throw new Error('Failed to search all decks in database'); } } /** * Count active (non-soft-deleted) decks for a specific user * @param userId - User ID to count decks for * @returns Number of active decks */ async countActiveByUserId(userId) { const startTime = performance.now(); try { const count = await this.repo.count({ where: { userid: userId, state: (0, typeorm_1.Not)(DeckAggregate_1.State.SOFT_DELETE) } }); const endTime = performance.now(); (0, Logger_1.logDatabase)('User active deck count completed', `executionTime: ${Math.round(endTime - startTime)}ms, userId: ${userId}, count: ${count}`); return count; } catch (error) { const endTime = performance.now(); (0, Logger_1.logDatabase)('User active deck count failed', `executionTime: ${Math.round(endTime - startTime)}ms, userId: ${userId}`); (0, Logger_1.logError)('DeckRepository.countActiveByUserId error', error instanceof Error ? error : new Error(String(error))); throw new Error('Failed to count active decks for user'); } } /** * Count organizational decks for a specific user * @param userId - User ID to count organizational decks for * @returns Number of organizational decks */ async countOrganizationalByUserId(userId) { const startTime = performance.now(); try { const count = await this.repo.count({ where: { userid: userId, ctype: DeckAggregate_1.CType.ORGANIZATION, state: (0, typeorm_1.Not)(DeckAggregate_1.State.SOFT_DELETE) } }); const endTime = performance.now(); (0, Logger_1.logDatabase)('User organizational deck count completed', `executionTime: ${Math.round(endTime - startTime)}ms, userId: ${userId}, count: ${count}`); return count; } catch (error) { const endTime = performance.now(); (0, Logger_1.logDatabase)('User organizational deck count failed', `executionTime: ${Math.round(endTime - startTime)}ms, userId: ${userId}`); (0, Logger_1.logError)('DeckRepository.countOrganizationalByUserId error', error instanceof Error ? error : new Error(String(error))); throw new Error('Failed to count organizational decks for user'); } } /** * Find decks with filtering based on user permissions and mandatory pagination * @param userId - User ID for filtering * @param userOrgId - User's organization ID (if any) * @param isAdmin - Whether user is admin (bypasses filtering) * @param from - Start index for pagination (default: 0) * @param to - End index for pagination (default: 49) * @returns Paginated filtered list of decks with total count */ async findFilteredDecks(userId, userOrgId, isAdmin, from = 0, to = 49) { const startTime = performance.now(); try { // Validate pagination parameters if (from < 0 || to < from) { throw new Error('Invalid pagination parameters'); } const limit = to - from + 1; if (limit > 100) { throw new Error('Page size too large. Maximum 100 records per request'); } const skip = from; const take = limit; // Admin gets ALL decks with pagination if (isAdmin) { AdminBypassService_1.AdminBypassService.logAdminBypass('FIND_FILTERED_DECKS_BYPASS', userId, 'all-decks-filtered', { bypassType: 'admin-all-decks-filtered', userOrgId, from, to, operation: 'read' }); const [decks, totalCount] = await this.repo.findAndCount({ where: { state: (0, typeorm_1.Not)(DeckAggregate_1.State.SOFT_DELETE) }, relations: ['organization'], order: { creationdate: 'DESC' }, skip, take }); const endTime = performance.now(); (0, Logger_1.logDatabase)('Admin filtered deck query completed', `executionTime: ${Math.round(endTime - startTime)}ms, userId: ${userId}, found: ${decks.length}, totalCount: ${totalCount}, isAdmin: true`); return { decks, totalCount }; } // Regular user complex filtering const queryBuilder = this.repo.createQueryBuilder('deck') .leftJoinAndSelect('deck.organization', 'org') .where('deck.state != :deletedState', { deletedState: DeckAggregate_1.State.SOFT_DELETE }); queryBuilder.andWhere('(' + // User's private decks '(deck.userid = :userId AND deck.ctype = :privateType) OR ' + // All public decks '(deck.ctype = :publicType)' + // Organization decks from same org (if user has org) (userOrgId ? ' OR (deck.ctype = :orgType AND org.id = :orgId)' : '') + ')', { userId, privateType: DeckAggregate_1.CType.PRIVATE, publicType: DeckAggregate_1.CType.PUBLIC, ...(userOrgId && { orgType: DeckAggregate_1.CType.ORGANIZATION, orgId: userOrgId }) }); queryBuilder .orderBy('deck.creationdate', 'DESC') .skip(skip) .take(take); const [decks, totalCount] = await queryBuilder.getManyAndCount(); const endTime = performance.now(); (0, Logger_1.logDatabase)('User filtered deck query completed', `executionTime: ${Math.round(endTime - startTime)}ms, userId: ${userId}, userOrgId: ${userOrgId}, found: ${decks.length}, totalCount: ${totalCount}, isAdmin: false`); return { decks, totalCount }; } catch (error) { const endTime = performance.now(); (0, Logger_1.logDatabase)('Filtered deck query failed', `executionTime: ${Math.round(endTime - startTime)}ms, userId: ${userId}, isAdmin: ${isAdmin}`); (0, Logger_1.logError)('DeckRepository.findFilteredDecks error', error instanceof Error ? error : new Error(String(error))); throw new Error('Failed to find filtered decks'); } } } exports.DeckRepository = DeckRepository; //# sourceMappingURL=DeckRepository.js.map