"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.UserRepository = void 0; const typeorm_1 = require("typeorm"); const ormconfig_1 = require("../ormconfig"); const UserAggregate_1 = require("../../Domain/User/UserAggregate"); const Logger_1 = require("../../Application/Services/Logger"); class UserRepository { constructor() { this.repo = ormconfig_1.AppDataSource.getRepository(UserAggregate_1.UserAggregate); } async create(user) { const startTime = Date.now(); try { const result = await this.repo.save(user); (0, Logger_1.logDatabase)('User created successfully', undefined, Date.now() - startTime, { userId: result.id, username: user.username, email: user.email }); return result; } catch (error) { (0, Logger_1.logError)('UserRepository.create error', error); // Handle unique constraint violations if (error instanceof Error && (error.message.includes('duplicate') || error.message.includes('unique'))) { throw new Error('User with this username or email already exists'); } throw new Error('Failed to create user in database'); } } async findByPage(from, to) { const startTime = Date.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)(UserAggregate_1.UserState.SOFT_DELETE) } }); // Get paginated results const users = await this.repo.find({ where: { state: (0, typeorm_1.Not)(UserAggregate_1.UserState.SOFT_DELETE) }, order: { regdate: 'DESC' }, take: limit, skip: offset }); (0, Logger_1.logDatabase)('User page query completed', `from: ${from}, to: ${to}`, Date.now() - startTime, { found: users.length, total: totalCount }); return { users, totalCount }; } catch (error) { (0, Logger_1.logError)('UserRepository.findByPage error', error); throw new Error('Failed to get users page from database'); } } async findByPageIncludingDeleted(from, to) { const startTime = Date.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 users = await this.repo.find({ order: { regdate: 'DESC' }, take: limit, skip: offset }); (0, Logger_1.logDatabase)('User page query completed (including deleted)', `from: ${from}, to: ${to}`, Date.now() - startTime, { found: users.length, total: totalCount }); return { users, totalCount }; } catch (error) { (0, Logger_1.logError)('UserRepository.findByPageIncludingDeleted error', error); throw new Error('Failed to get users page from database'); } } async findById(id) { const startTime = Date.now(); try { const result = await this.repo.findOne({ where: { id, state: (0, typeorm_1.Not)(UserAggregate_1.UserState.SOFT_DELETE) } }); (0, Logger_1.logDatabase)('User findById query completed', `findOneBy({ id: ${id} })`, Date.now() - startTime, { found: !!result, userId: id }); return result; } catch (error) { (0, Logger_1.logError)('UserRepository.findById error', error); if (error instanceof Error && error.message.includes('invalid input syntax for type uuid')) { return null; } throw new Error('Failed to retrieve user from database'); } } async findByIdIncludingDeleted(id) { const startTime = Date.now(); try { const result = await this.repo.findOneBy({ id }); (0, Logger_1.logDatabase)('User findByIdIncludingDeleted query completed', `findOneBy({ id: ${id} })`, Date.now() - startTime, { found: !!result, userId: id }); return result; } catch (error) { (0, Logger_1.logError)('UserRepository.findByIdIncludingDeleted error', error); if (error instanceof Error && error.message.includes('invalid input syntax for type uuid')) { return null; } throw new Error('Failed to retrieve user from database'); } } async findByUsername(username) { const startTime = Date.now(); try { const result = await this.repo.findOneBy({ username }); (0, Logger_1.logDatabase)('User findByUsername query completed', `findOneBy({ username: ${username} })`, Date.now() - startTime, { found: !!result, username }); return result; } catch (error) { (0, Logger_1.logError)('UserRepository.findByUsername error', error); throw new Error('Failed to retrieve user by username from database'); } } async findByEmail(email) { const startTime = Date.now(); try { const result = await this.repo.findOneBy({ email }); (0, Logger_1.logDatabase)('User findByEmail query completed', `findOneBy({ email: ${email} })`, Date.now() - startTime, { found: !!result, email }); return result; } catch (error) { (0, Logger_1.logError)('UserRepository.findByEmail error', error); throw new Error('Failed to retrieve user by email from database'); } } async findByToken(token) { const startTime = Date.now(); try { const result = await this.repo.findOneBy({ token: token }); (0, Logger_1.logDatabase)('User findByToken query completed', `findOneBy({ token })`, Date.now() - startTime, { found: !!result, tokenPrefix: token.substring(0, 8) + '...' }); return result; } catch (error) { (0, Logger_1.logError)('UserRepository.findByToken error', error); throw new Error('Failed to retrieve user by token from database'); } } async update(id, update) { const startTime = Date.now(); try { await this.repo.update(id, update); const result = await this.findById(id); (0, Logger_1.logDatabase)('User updated successfully', `update(${id})`, Date.now() - startTime, { userId: id, updatedFields: Object.keys(update), success: !!result }); return result; } catch (error) { (0, Logger_1.logError)('UserRepository.update error', error); // Handle unique constraint violations if (error instanceof Error && (error.message.includes('duplicate') || error.message.includes('unique'))) { throw new Error('Username or email already exists'); } // Handle invalid UUID format if (error instanceof Error && error.message.includes('invalid input syntax for type uuid')) { throw new Error('Invalid user ID format'); } throw new Error('Failed to update user in database'); } } async delete(id) { const startTime = Date.now(); try { const result = await this.repo.delete(id); (0, Logger_1.logDatabase)('User deleted successfully', `delete(${id})`, Date.now() - startTime, { userId: id, affected: result.affected }); return result; } catch (error) { (0, Logger_1.logError)('UserRepository.delete error', error); // Handle invalid UUID format if (error instanceof Error && error.message.includes('invalid input syntax for type uuid')) { throw new Error('Invalid user ID format'); } throw new Error('Failed to delete user from database'); } } async softDelete(id) { const startTime = Date.now(); try { await this.repo.update(id, { state: UserAggregate_1.UserState.SOFT_DELETE }); const result = await this.findById(id); (0, Logger_1.logDatabase)('User soft deleted successfully', `update(${id}, { state: SOFT_DELETE })`, Date.now() - startTime, { userId: id, success: !!result }); return result; } catch (error) { (0, Logger_1.logError)('UserRepository.softDelete error', error); // Handle invalid UUID format if (error instanceof Error && error.message.includes('invalid input syntax for type uuid')) { throw new Error('Invalid user ID format'); } throw new Error('Failed to soft delete user in database'); } } async deactivate(id) { const startTime = Date.now(); try { await this.repo.update(id, { state: UserAggregate_1.UserState.DEACTIVATED }); const result = await this.findById(id); (0, Logger_1.logDatabase)('User deactivated successfully', `update(${id}, { state: DEACTIVATED })`, Date.now() - startTime, { userId: id, success: !!result }); return result; } catch (error) { (0, Logger_1.logError)('UserRepository.deactivate error', error); // Handle invalid UUID format if (error instanceof Error && error.message.includes('invalid input syntax for type uuid')) { throw new Error('Invalid user ID format'); } throw new Error('Failed to deactivate user in database'); } } async search(query, limit = 20, offset = 0) { const startTime = Date.now(); try { const searchPattern = `%${query.toLowerCase()}%`; const queryBuilder = this.repo.createQueryBuilder('user') .where('user.state != :softDelete', { softDelete: UserAggregate_1.UserState.SOFT_DELETE }) .andWhere('(LOWER(user.username) LIKE :pattern OR LOWER(user.email) LIKE :pattern OR LOWER(user.fname) LIKE :pattern OR LOWER(user.lname) LIKE :pattern OR LOWER(CONCAT(user.fname, \' \', user.lname)) LIKE :pattern)', { pattern: searchPattern }); const totalCount = await queryBuilder.getCount(); const users = await queryBuilder .orderBy('user.username', 'ASC') .limit(limit) .offset(offset) .getMany(); (0, Logger_1.logDatabase)('User search completed', `search query: ${query.substring(0, 50)}...`, Date.now() - startTime, { query, limit, offset, totalCount, returnedCount: users.length }); return { users, totalCount }; } catch (error) { (0, Logger_1.logError)('UserRepository.search error', error); throw new Error('Failed to search users in database'); } } async searchIncludingDeleted(query, limit = 20, offset = 0) { const startTime = Date.now(); try { const searchPattern = `%${query.toLowerCase()}%`; const queryBuilder = this.repo.createQueryBuilder('user') .where('LOWER(user.username) LIKE :pattern', { pattern: searchPattern }) .orWhere('LOWER(user.email) LIKE :pattern', { pattern: searchPattern }) .orWhere('LOWER(user.fname) LIKE :pattern', { pattern: searchPattern }) .orWhere('LOWER(user.lname) LIKE :pattern', { pattern: searchPattern }) .orWhere('LOWER(CONCAT(user.fname, \' \', user.lname)) LIKE :pattern', { pattern: searchPattern }); const totalCount = await queryBuilder.getCount(); const users = await queryBuilder .orderBy('user.username', 'ASC') .limit(limit) .offset(offset) .getMany(); (0, Logger_1.logDatabase)('User search completed (including deleted)', `search query: ${query.substring(0, 50)}...`, Date.now() - startTime, { query, limit, offset, totalCount, returnedCount: users.length }); return { users, totalCount }; } catch (error) { (0, Logger_1.logError)('UserRepository.searchIncludingDeleted error', error); throw new Error('Failed to search all users in database'); } } } exports.UserRepository = UserRepository; //# sourceMappingURL=UserRepository.js.map