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