312 lines
13 KiB
JavaScript
312 lines
13 KiB
JavaScript
"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
|