https://project.mdnd-it.cc/work_packages/94
This commit is contained in:
2025-08-23 04:25:28 +02:00
parent 725516ad6c
commit 19cfa031d0
25823 changed files with 1095587 additions and 2801760 deletions
@@ -0,0 +1,14 @@
import { ChatArchiveAggregate } from '../../Domain/Chat/ChatArchiveAggregate';
import { IChatArchiveRepository } from '../../Domain/IRepository/IChatArchiveRepository';
export declare class ChatArchiveRepository implements IChatArchiveRepository {
private repo;
constructor();
create(archive: Partial<ChatArchiveAggregate>): Promise<Partial<ChatArchiveAggregate> & ChatArchiveAggregate>;
findAll(): Promise<ChatArchiveAggregate[]>;
findById(id: string): Promise<ChatArchiveAggregate | null>;
findByChatId(chatId: string): Promise<ChatArchiveAggregate[]>;
findByGameId(gameId: string): Promise<ChatArchiveAggregate[]>;
delete(id: string): Promise<import("typeorm").DeleteResult>;
cleanup(olderThanDays: number): Promise<number>;
}
//# sourceMappingURL=ChatArchiveRepository.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"ChatArchiveRepository.d.ts","sourceRoot":"","sources":["../../../src/Infrastructure/Repository/ChatArchiveRepository.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,iDAAiD,CAAC;AAIzF,qBAAa,qBAAsB,YAAW,sBAAsB;IAChE,OAAO,CAAC,IAAI,CAAmC;;IAMzC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,oBAAoB,CAAC;IAgB7C,OAAO;IAcP,QAAQ,CAAC,EAAE,EAAE,MAAM;IAenB,YAAY,CAAC,MAAM,EAAE,MAAM;IAoB3B,YAAY,CAAC,MAAM,EAAE,MAAM;IAoB3B,MAAM,CAAC,EAAE,EAAE,MAAM;IAejB,OAAO,CAAC,aAAa,EAAE,MAAM;CAuBtC"}
@@ -0,0 +1,132 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChatArchiveRepository = void 0;
const ormconfig_1 = require("../ormconfig");
const ChatArchiveAggregate_1 = require("../../Domain/Chat/ChatArchiveAggregate");
const Logger_1 = require("../../Application/Services/Logger");
class ChatArchiveRepository {
constructor() {
this.repo = ormconfig_1.AppDataSource.getRepository(ChatArchiveAggregate_1.ChatArchiveAggregate);
}
async create(archive) {
const startTime = Date.now();
try {
const result = await this.repo.save(archive);
(0, Logger_1.logDatabase)('Chat archive created successfully', undefined, Date.now() - startTime, {
archiveId: result.id,
chatId: result.chatId,
messageCount: result.archivedMessages?.length || 0
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatArchiveRepository.create error', error);
throw new Error('Failed to create chat archive in database');
}
}
async findAll() {
const startTime = Date.now();
try {
const result = await this.repo.find();
(0, Logger_1.logDatabase)('All chat archives retrieved', undefined, Date.now() - startTime, {
count: result.length
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatArchiveRepository.findAll error', error);
throw new Error('Failed to retrieve chat archives from database');
}
}
async findById(id) {
const startTime = Date.now();
try {
const result = await this.repo.findOneBy({ id });
(0, Logger_1.logDatabase)('Chat archive retrieved by id', `findById(${id})`, Date.now() - startTime, {
archiveId: id,
found: !!result
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatArchiveRepository.findById error', error);
throw new Error('Failed to find chat archive by id');
}
}
async findByChatId(chatId) {
const startTime = Date.now();
try {
const result = await this.repo
.find({
where: { chatId },
order: { archivedAt: 'DESC' }
});
(0, Logger_1.logDatabase)('Chat archives retrieved by chat id', `findByChatId(${chatId})`, Date.now() - startTime, {
chatId,
count: result.length
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatArchiveRepository.findByChatId error', error);
throw new Error('Failed to find chat archives by chat id');
}
}
async findByGameId(gameId) {
const startTime = Date.now();
try {
const result = await this.repo
.find({
where: { gameId },
order: { archivedAt: 'DESC' }
});
(0, Logger_1.logDatabase)('Chat archives retrieved by game id', `findByGameId(${gameId})`, Date.now() - startTime, {
gameId,
count: result.length
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatArchiveRepository.findByGameId error', error);
throw new Error('Failed to find chat archives by game id');
}
}
async delete(id) {
const startTime = Date.now();
try {
const result = await this.repo.delete(id);
(0, Logger_1.logDatabase)('Chat archive deleted', `delete(${id})`, Date.now() - startTime, {
archiveId: id,
affected: result.affected
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatArchiveRepository.delete error', error);
throw new Error('Failed to delete chat archive');
}
}
async cleanup(olderThanDays) {
const startTime = Date.now();
try {
const cutoffDate = new Date(Date.now() - olderThanDays * 24 * 60 * 60 * 1000);
const result = await this.repo
.createQueryBuilder()
.delete()
.where('archivedAt < :cutoffDate', { cutoffDate })
.execute();
(0, Logger_1.logDatabase)('Chat archive cleanup completed', `cleanup(${olderThanDays} days)`, Date.now() - startTime, {
olderThanDays,
deleted: result.affected,
cutoffDate
});
return result.affected || 0;
}
catch (error) {
(0, Logger_1.logError)('ChatArchiveRepository.cleanup error', error);
throw new Error('Failed to cleanup old chat archives');
}
}
}
exports.ChatArchiveRepository = ChatArchiveRepository;
//# sourceMappingURL=ChatArchiveRepository.js.map
@@ -0,0 +1 @@
{"version":3,"file":"ChatArchiveRepository.js","sourceRoot":"","sources":["../../../src/Infrastructure/Repository/ChatArchiveRepository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
import { ChatAggregate } from '../../Domain/Chat/ChatAggregate';
import { ChatArchiveAggregate } from '../../Domain/Chat/ChatArchiveAggregate';
import { IChatRepository } from '../../Domain/IRepository/IChatRepository';
export declare class ChatRepository implements IChatRepository {
private repo;
private archiveRepo;
constructor();
create(chat: Partial<ChatAggregate>): Promise<Partial<ChatAggregate> & ChatAggregate>;
findByPage(from: number, to: number): Promise<{
chats: ChatAggregate[];
totalCount: number;
}>;
findByPageIncludingDeleted(from: number, to: number): Promise<{
chats: ChatAggregate[];
totalCount: number;
}>;
findById(id: string): Promise<ChatAggregate | null>;
findByIdIncludingDeleted(id: string): Promise<ChatAggregate | null>;
findByUserId(userId: string): Promise<ChatAggregate[]>;
findByUserIdIncludingDeleted(userId: string): Promise<ChatAggregate[]>;
findByGameId(gameId: string): Promise<ChatAggregate | null>;
findActiveChatsForUser(userId: string): Promise<ChatAggregate[]>;
findInactiveChats(inactivityMinutes: number): Promise<ChatAggregate[]>;
update(id: string, update: Partial<ChatAggregate>): Promise<ChatAggregate | null>;
delete(id: string): Promise<import("typeorm").DeleteResult>;
softDelete(id: string): Promise<ChatAggregate | null>;
archiveChat(chat: ChatAggregate): Promise<ChatArchiveAggregate>;
getArchivedChat(chatId: string): Promise<ChatArchiveAggregate | null>;
restoreFromArchive(chatId: string): Promise<ChatAggregate | null>;
}
//# sourceMappingURL=ChatRepository.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"ChatRepository.d.ts","sourceRoot":"","sources":["../../../src/Infrastructure/Repository/ChatRepository.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAuB,MAAM,iCAAiC,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAG3E,qBAAa,cAAe,YAAW,eAAe;IAClD,OAAO,CAAC,IAAI,CAA4B;IACxC,OAAO,CAAC,WAAW,CAAmC;;IAOhD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,aAAa,CAAC;IAgBnC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IA2B7F,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IA0B7G,QAAQ,CAAC,EAAE,EAAE,MAAM;IAoBnB,wBAAwB,CAAC,EAAE,EAAE,MAAM;IAenC,YAAY,CAAC,MAAM,EAAE,MAAM;IAoB3B,4BAA4B,CAAC,MAAM,EAAE,MAAM;IAmB3C,YAAY,CAAC,MAAM,EAAE,MAAM;IAmB3B,sBAAsB,CAAC,MAAM,EAAE,MAAM;IAqBrC,iBAAiB,CAAC,iBAAiB,EAAE,MAAM;IAuB3C,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC;IAiBjD,MAAM,CAAC,EAAE,EAAE,MAAM;IAejB,UAAU,CAAC,EAAE,EAAE,MAAM;IAgBrB,WAAW,CAAC,IAAI,EAAE,aAAa;IAiC/B,eAAe,CAAC,MAAM,EAAE,MAAM;IAe9B,kBAAkB,CAAC,MAAM,EAAE,MAAM;CAuC1C"}
@@ -0,0 +1,339 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChatRepository = void 0;
const typeorm_1 = require("typeorm");
const ormconfig_1 = require("../ormconfig");
const ChatAggregate_1 = require("../../Domain/Chat/ChatAggregate");
const ChatArchiveAggregate_1 = require("../../Domain/Chat/ChatArchiveAggregate");
const Logger_1 = require("../../Application/Services/Logger");
class ChatRepository {
constructor() {
this.repo = ormconfig_1.AppDataSource.getRepository(ChatAggregate_1.ChatAggregate);
this.archiveRepo = ormconfig_1.AppDataSource.getRepository(ChatArchiveAggregate_1.ChatArchiveAggregate);
}
async create(chat) {
const startTime = Date.now();
try {
const result = await this.repo.save(chat);
(0, Logger_1.logDatabase)('Chat created successfully', undefined, Date.now() - startTime, {
chatId: result.id,
type: result.type,
participants: result.users?.length || 0
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatRepository.create error', error);
throw new Error('Failed to create chat in database');
}
}
async findByPage(from, to) {
const startTime = Date.now();
try {
const skip = from;
const take = to - from + 1;
const [chats, totalCount] = await this.repo.findAndCount({
where: { state: (0, typeorm_1.Not)(ChatAggregate_1.ChatState.SOFT_DELETE) },
order: { createDate: 'DESC' },
skip,
take
});
(0, Logger_1.logDatabase)('Chats page retrieved successfully', undefined, Date.now() - startTime, {
from,
to,
returned: chats.length,
totalCount
});
return { chats, totalCount };
}
catch (error) {
(0, Logger_1.logError)('ChatRepository.findByPage error', error);
throw new Error('Failed to retrieve chats page from database');
}
}
async findByPageIncludingDeleted(from, to) {
const startTime = Date.now();
try {
const skip = from;
const take = to - from + 1;
const [chats, totalCount] = await this.repo.findAndCount({
order: { createDate: 'DESC' },
skip,
take
});
(0, Logger_1.logDatabase)('Chats page retrieved successfully (including deleted)', undefined, Date.now() - startTime, {
from,
to,
returned: chats.length,
totalCount
});
return { chats, totalCount };
}
catch (error) {
(0, Logger_1.logError)('ChatRepository.findByPageIncludingDeleted error', error);
throw new Error('Failed to retrieve chats page from database');
}
}
async findById(id) {
const startTime = Date.now();
try {
const result = await this.repo.findOne({
where: {
id,
state: (0, typeorm_1.Not)(ChatAggregate_1.ChatState.SOFT_DELETE)
}
});
(0, Logger_1.logDatabase)('Chat findById query completed', undefined, Date.now() - startTime, {
found: !!result,
chatId: id
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatRepository.findById error', error);
throw new Error('Failed to retrieve chat from database');
}
}
async findByIdIncludingDeleted(id) {
const startTime = Date.now();
try {
const result = await this.repo.findOneBy({ id });
(0, Logger_1.logDatabase)('Chat findByIdIncludingDeleted query completed', undefined, Date.now() - startTime, {
found: !!result,
chatId: id
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatRepository.findByIdIncludingDeleted error', error);
throw new Error('Failed to retrieve chat from database');
}
}
async findByUserId(userId) {
const startTime = Date.now();
try {
const result = await this.repo
.createQueryBuilder('chat')
.where(':userId = ANY(chat.users)', { userId })
.andWhere('chat.state != :softDelete', { softDelete: ChatAggregate_1.ChatState.SOFT_DELETE })
.getMany();
(0, Logger_1.logDatabase)('Chats retrieved by user id', `findByUserId(${userId})`, Date.now() - startTime, {
userId,
count: result.length
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatRepository.findByUserId error', error);
throw new Error('Failed to find chats by user id');
}
}
async findByUserIdIncludingDeleted(userId) {
const startTime = Date.now();
try {
const result = await this.repo
.createQueryBuilder('chat')
.where(':userId = ANY(chat.users)', { userId })
.getMany();
(0, Logger_1.logDatabase)('Chats retrieved by user id (including deleted)', `findByUserIdIncludingDeleted(${userId})`, Date.now() - startTime, {
userId,
count: result.length
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatRepository.findByUserIdIncludingDeleted error', error);
throw new Error('Failed to find all chats by user id');
}
}
async findByGameId(gameId) {
const startTime = Date.now();
try {
const result = await this.repo.findOneBy({
gameId,
type: ChatAggregate_1.ChatType.GAME,
state: ChatAggregate_1.ChatState.ACTIVE
});
(0, Logger_1.logDatabase)('Chat retrieved by game id', `findByGameId(${gameId})`, Date.now() - startTime, {
gameId,
found: !!result
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatRepository.findByGameId error', error);
throw new Error('Failed to find chat by game id');
}
}
async findActiveChatsForUser(userId) {
const startTime = Date.now();
try {
const result = await this.repo
.createQueryBuilder('chat')
.where(':userId = ANY(chat.users)', { userId })
.andWhere('chat.state = :state', { state: ChatAggregate_1.ChatState.ACTIVE })
.orderBy('chat.lastActivity', 'DESC')
.getMany();
(0, Logger_1.logDatabase)('Active chats retrieved for user', `findActiveChatsForUser(${userId})`, Date.now() - startTime, {
userId,
count: result.length
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatRepository.findActiveChatsForUser error', error);
throw new Error('Failed to find active chats for user');
}
}
async findInactiveChats(inactivityMinutes) {
const startTime = Date.now();
try {
const cutoffDate = new Date(Date.now() - inactivityMinutes * 60 * 1000);
const result = await this.repo
.createQueryBuilder('chat')
.where('chat.state = :state', { state: ChatAggregate_1.ChatState.ACTIVE })
.andWhere('(chat.lastActivity < :cutoffDate OR chat.lastActivity IS NULL)', { cutoffDate })
.getMany();
(0, Logger_1.logDatabase)('Inactive chats retrieved', `findInactiveChats(${inactivityMinutes}min)`, Date.now() - startTime, {
inactivityMinutes,
count: result.length,
cutoffDate
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatRepository.findInactiveChats error', error);
throw new Error('Failed to find inactive chats');
}
}
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)('Chat updated successfully', `update(${id})`, Date.now() - startTime, {
chatId: id,
updatedFields: Object.keys(update),
success: !!result
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatRepository.update error', error);
throw new Error('Failed to update chat in database');
}
}
async delete(id) {
const startTime = Date.now();
try {
const result = await this.repo.delete(id);
(0, Logger_1.logDatabase)('Chat deleted', `delete(${id})`, Date.now() - startTime, {
chatId: id,
affected: result.affected
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatRepository.delete error', error);
throw new Error('Failed to delete chat');
}
}
async softDelete(id) {
const startTime = Date.now();
try {
await this.repo.update(id, { state: ChatAggregate_1.ChatState.SOFT_DELETE });
const result = await this.findById(id);
(0, Logger_1.logDatabase)('Chat soft deleted', `softDelete(${id})`, Date.now() - startTime, {
chatId: id,
success: !!result
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatRepository.softDelete error', error);
throw new Error('Failed to soft delete chat');
}
}
async archiveChat(chat) {
const startTime = Date.now();
try {
const archive = new ChatArchiveAggregate_1.ChatArchiveAggregate();
archive.chatId = chat.id;
archive.archivedMessages = chat.messages;
archive.archivedAt = new Date();
archive.chatType = chat.type;
archive.chatName = chat.name;
archive.gameId = chat.gameId;
archive.participants = chat.users;
const archivedResult = await this.archiveRepo.save(archive);
await this.repo.update(chat.id, {
state: ChatAggregate_1.ChatState.ARCHIVE,
messages: [],
archiveDate: new Date()
});
(0, Logger_1.logDatabase)('Chat archived successfully', `archiveChat(${chat.id})`, Date.now() - startTime, {
chatId: chat.id,
messageCount: chat.messages.length,
archiveId: archivedResult.id
});
return archivedResult;
}
catch (error) {
(0, Logger_1.logError)('ChatRepository.archiveChat error', error);
throw new Error('Failed to archive chat');
}
}
async getArchivedChat(chatId) {
const startTime = Date.now();
try {
const result = await this.archiveRepo.findOneBy({ chatId });
(0, Logger_1.logDatabase)('Archived chat retrieved', `getArchivedChat(${chatId})`, Date.now() - startTime, {
chatId,
found: !!result
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatRepository.getArchivedChat error', error);
throw new Error('Failed to retrieve archived chat');
}
}
async restoreFromArchive(chatId) {
const startTime = Date.now();
try {
const archive = await this.archiveRepo.findOneBy({ chatId });
if (!archive) {
return null;
}
// Game chats cannot be restored, only viewed
if (archive.chatType === ChatAggregate_1.ChatType.GAME) {
(0, Logger_1.logDatabase)('Game chat restore attempt blocked', `restoreFromArchive(${chatId})`, Date.now() - startTime, {
chatId,
chatType: archive.chatType,
blocked: true
});
return null;
}
// Restore messages to the chat
await this.repo.update(chatId, {
state: ChatAggregate_1.ChatState.ACTIVE,
messages: archive.archivedMessages,
lastActivity: new Date(),
archiveDate: null
});
const result = await this.findById(chatId);
(0, Logger_1.logDatabase)('Chat restored from archive', `restoreFromArchive(${chatId})`, Date.now() - startTime, {
chatId,
messageCount: archive.archivedMessages.length,
success: !!result
});
return result;
}
catch (error) {
(0, Logger_1.logError)('ChatRepository.restoreFromArchive error', error);
throw new Error('Failed to restore chat from archive');
}
}
}
exports.ChatRepository = ChatRepository;
//# sourceMappingURL=ChatRepository.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,23 @@
import { ContactAggregate } from '../../Domain/Contact/ContactAggregate';
import { IContactRepository } from '../../Domain/IRepository/IContactRepository';
export declare class ContactRepository implements IContactRepository {
private repo;
constructor();
create(contact: Partial<ContactAggregate>): Promise<Partial<ContactAggregate> & ContactAggregate>;
findById(id: string): Promise<ContactAggregate | null>;
findByPage(from: number, to: number): Promise<{
contacts: ContactAggregate[];
totalCount: number;
}>;
findByPageIncludingDeleted(from: number, to: number): Promise<{
contacts: ContactAggregate[];
totalCount: number;
}>;
update(id: string, update: Partial<ContactAggregate>): Promise<ContactAggregate | null>;
delete(id: string): Promise<import("typeorm").DeleteResult>;
softDelete(id: string): Promise<ContactAggregate | null>;
findByIdIncludingDeleted(id: string): Promise<ContactAggregate | null>;
searchIncludingDeleted(searchTerm: string): Promise<ContactAggregate[]>;
search(searchTerm: string): Promise<ContactAggregate[]>;
}
//# sourceMappingURL=ContactRepository.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"ContactRepository.d.ts","sourceRoot":"","sources":["../../../src/Infrastructure/Repository/ContactRepository.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAgB,MAAM,uCAAuC,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AAGjF,qBAAa,iBAAkB,YAAW,kBAAkB;IACxD,OAAO,CAAC,IAAI,CAA+B;;IAMrC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC;IAIzC,QAAQ,CAAC,EAAE,EAAE,MAAM;IAQnB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAkCnG,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IA6BnH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC;IAKpD,MAAM,CAAC,EAAE,EAAE,MAAM;IAIjB,UAAU,CAAC,EAAE,EAAE,MAAM;IAKrB,wBAAwB,CAAC,EAAE,EAAE,MAAM;IAInC,sBAAsB,CAAC,UAAU,EAAE,MAAM;IASzC,MAAM,CAAC,UAAU,EAAE,MAAM;CASlC"}
@@ -0,0 +1,110 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ContactRepository = void 0;
const typeorm_1 = require("typeorm");
const ormconfig_1 = require("../ormconfig");
const ContactAggregate_1 = require("../../Domain/Contact/ContactAggregate");
const Logger_1 = require("../../Application/Services/Logger");
class ContactRepository {
constructor() {
this.repo = ormconfig_1.AppDataSource.getRepository(ContactAggregate_1.ContactAggregate);
}
async create(contact) {
return this.repo.save(contact);
}
async findById(id) {
return this.repo
.createQueryBuilder('contact')
.where('contact.id = :id', { id })
.andWhere('contact.state != :softDelete', { softDelete: ContactAggregate_1.ContactState.SOFT_DELETE })
.getOne();
}
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)(ContactAggregate_1.ContactState.SOFT_DELETE)
}
});
// Get paginated results
const contacts = await this.repo
.createQueryBuilder('contact')
.where('contact.state != :softDelete', { softDelete: ContactAggregate_1.ContactState.SOFT_DELETE })
.orderBy('contact.createDate', 'DESC')
.limit(limit)
.offset(offset)
.getMany();
const endTime = performance.now();
(0, Logger_1.logDatabase)('Contact page query completed', `executionTime: ${Math.round(endTime - startTime)}ms, found: ${contacts.length}, total: ${totalCount}, from: ${from}, to: ${to}`);
return { contacts, totalCount };
}
catch (error) {
const endTime = performance.now();
(0, Logger_1.logDatabase)('Contact page query failed', `executionTime: ${Math.round(endTime - startTime)}ms, from: ${from}, to: ${to}`);
(0, Logger_1.logError)('ContactRepository.findByPage error', error instanceof Error ? error : new Error(String(error)));
throw new Error('Failed to get contacts 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 contacts = await this.repo
.createQueryBuilder('contact')
.orderBy('contact.createDate', 'DESC')
.limit(limit)
.offset(offset)
.getMany();
const endTime = performance.now();
(0, Logger_1.logDatabase)('Contact page query completed (including deleted)', `executionTime: ${Math.round(endTime - startTime)}ms, found: ${contacts.length}, total: ${totalCount}, from: ${from}, to: ${to}`);
return { contacts, totalCount };
}
catch (error) {
const endTime = performance.now();
(0, Logger_1.logDatabase)('Contact page query failed (including deleted)', `executionTime: ${Math.round(endTime - startTime)}ms, from: ${from}, to: ${to}`);
(0, Logger_1.logError)('ContactRepository.findByPageIncludingDeleted error', error instanceof Error ? error : new Error(String(error)));
throw new Error('Failed to get contacts page from database');
}
}
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: ContactAggregate_1.ContactState.SOFT_DELETE });
return this.findById(id);
}
async findByIdIncludingDeleted(id) {
return this.repo.findOneBy({ id }); // Returns contact regardless of state
}
async searchIncludingDeleted(searchTerm) {
return this.repo
.createQueryBuilder('contact')
.where('contact.name ILIKE :searchTerm', { searchTerm: `%${searchTerm}%` })
.orWhere('contact.email ILIKE :searchTerm', { searchTerm: `%${searchTerm}%` })
.orWhere('contact.txt ILIKE :searchTerm', { searchTerm: `%${searchTerm}%` })
.getMany();
}
async search(searchTerm) {
return this.repo
.createQueryBuilder('contact')
.where('contact.name ILIKE :searchTerm', { searchTerm: `%${searchTerm}%` })
.orWhere('contact.email ILIKE :searchTerm', { searchTerm: `%${searchTerm}%` })
.orWhere('contact.txt ILIKE :searchTerm', { searchTerm: `%${searchTerm}%` })
.andWhere('contact.state != :softDelete', { softDelete: ContactAggregate_1.ContactState.SOFT_DELETE })
.getMany();
}
}
exports.ContactRepository = ContactRepository;
//# sourceMappingURL=ContactRepository.js.map
@@ -0,0 +1 @@
{"version":3,"file":"ContactRepository.js","sourceRoot":"","sources":["../../../src/Infrastructure/Repository/ContactRepository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
import { DeckAggregate } from '../../Domain/Deck/DeckAggregate';
import { IDeckRepository } from '../../Domain/IRepository/IDeckRepository';
export declare class DeckRepository implements IDeckRepository {
private repo;
constructor();
create(deck: Partial<DeckAggregate>): Promise<Partial<DeckAggregate> & DeckAggregate>;
findByPage(from: number, to: number): Promise<{
decks: DeckAggregate[];
totalCount: number;
}>;
findByPageIncludingDeleted(from: number, to: number): Promise<{
decks: DeckAggregate[];
totalCount: number;
}>;
findById(id: string): Promise<DeckAggregate | null>;
findByIdIncludingDeleted(id: string): Promise<DeckAggregate | null>;
update(id: string, update: Partial<DeckAggregate>): Promise<DeckAggregate | null>;
delete(id: string): Promise<import("typeorm").DeleteResult>;
softDelete(id: string): Promise<DeckAggregate | null>;
search(query: string, limit?: number, offset?: number): Promise<{
decks: DeckAggregate[];
totalCount: number;
}>;
searchIncludingDeleted(query: string, limit?: number, offset?: number): Promise<{
decks: DeckAggregate[];
totalCount: number;
}>;
/**
* Count active (non-soft-deleted) decks for a specific user
* @param userId - User ID to count decks for
* @returns Number of active decks
*/
countActiveByUserId(userId: string): Promise<number>;
/**
* Count organizational decks for a specific user
* @param userId - User ID to count organizational decks for
* @returns Number of organizational decks
*/
countOrganizationalByUserId(userId: string): Promise<number>;
/**
* 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
*/
findFilteredDecks(userId: string, userOrgId?: string | null, isAdmin?: boolean, from?: number, to?: number): Promise<{
decks: DeckAggregate[];
totalCount: number;
}>;
}
//# sourceMappingURL=DeckRepository.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"DeckRepository.d.ts","sourceRoot":"","sources":["../../../src/Infrastructure/Repository/DeckRepository.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAgB,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAI3E,qBAAa,cAAe,YAAW,eAAe;IAClD,OAAO,CAAC,IAAI,CAA4B;;IAKlC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,aAAa,CAAC;IAInC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IA+B7F,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IA4B7G,QAAQ,CAAC,EAAE,EAAE,MAAM;IASnB,wBAAwB,CAAC,EAAE,EAAE,MAAM;IAInC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC;IAKjD,MAAM,CAAC,EAAE,EAAE,MAAM;IAIjB,UAAU,CAAC,EAAE,EAAE,MAAM;IAKrB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,MAAM,GAAE,MAAU,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IA6BtH,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,MAAM,GAAE,MAAU,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IA4B5I;;;;OAIG;IACG,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAsB1D;;;;OAIG;IACG,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAuBlE;;;;;;;;OAQG;IACG,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,GAAE,MAAU,EAAE,EAAE,GAAE,MAAW,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAkFpL"}
@@ -0,0 +1,264 @@
"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
File diff suppressed because one or more lines are too long
@@ -0,0 +1,29 @@
import { OrganizationAggregate } from '../../Domain/Organization/OrganizationAggregate';
import { IOrganizationRepository } from '../../Domain/IRepository/IOrganizationRepository';
export declare class OrganizationRepository implements IOrganizationRepository {
private repo;
constructor();
create(org: Partial<OrganizationAggregate>): Promise<Partial<OrganizationAggregate> & OrganizationAggregate>;
findByPage(from: number, to: number): Promise<{
organizations: OrganizationAggregate[];
totalCount: number;
}>;
findByPageIncludingDeleted(from: number, to: number): Promise<{
organizations: OrganizationAggregate[];
totalCount: number;
}>;
findById(id: string): Promise<OrganizationAggregate | null>;
findByIdIncludingDeleted(id: string): Promise<OrganizationAggregate | null>;
update(id: string, update: Partial<OrganizationAggregate>): Promise<OrganizationAggregate | null>;
delete(id: string): Promise<import("typeorm").DeleteResult>;
softDelete(id: string): Promise<OrganizationAggregate | null>;
search(query: string, limit?: number, offset?: number): Promise<{
organizations: OrganizationAggregate[];
totalCount: number;
}>;
searchIncludingDeleted(query: string, limit?: number, offset?: number): Promise<{
organizations: OrganizationAggregate[];
totalCount: number;
}>;
}
//# sourceMappingURL=OrganizationRepository.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"OrganizationRepository.d.ts","sourceRoot":"","sources":["../../../src/Infrastructure/Repository/OrganizationRepository.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAqB,MAAM,iDAAiD,CAAC;AAC3G,OAAO,EAAE,uBAAuB,EAAE,MAAM,kDAAkD,CAAC;AAG3F,qBAAa,sBAAuB,YAAW,uBAAuB;IAClE,OAAO,CAAC,IAAI,CAAoC;;IAK1C,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,qBAAqB,CAAC;IAI1C,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,aAAa,EAAE,qBAAqB,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IA+B7G,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,aAAa,EAAE,qBAAqB,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IA4B7H,QAAQ,CAAC,EAAE,EAAE,MAAM;IASnB,wBAAwB,CAAC,EAAE,EAAE,MAAM;IAInC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,qBAAqB,CAAC;IAKzD,MAAM,CAAC,EAAE,EAAE,MAAM;IAIjB,UAAU,CAAC,EAAE,EAAE,MAAM;IAKrB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,MAAM,GAAE,MAAU,GAAG,OAAO,CAAC;QAAE,aAAa,EAAE,qBAAqB,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IA6BtI,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,MAAM,GAAE,MAAU,GAAG,OAAO,CAAC;QAAE,aAAa,EAAE,qBAAqB,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAgC/J"}
@@ -0,0 +1,141 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OrganizationRepository = void 0;
const typeorm_1 = require("typeorm");
const ormconfig_1 = require("../ormconfig");
const OrganizationAggregate_1 = require("../../Domain/Organization/OrganizationAggregate");
const Logger_1 = require("../../Application/Services/Logger");
class OrganizationRepository {
constructor() {
this.repo = ormconfig_1.AppDataSource.getRepository(OrganizationAggregate_1.OrganizationAggregate);
}
async create(org) {
return this.repo.save(org);
}
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)(OrganizationAggregate_1.OrganizationState.SOFT_DELETE) }
});
// Get paginated results
const organizations = await this.repo.find({
where: { state: (0, typeorm_1.Not)(OrganizationAggregate_1.OrganizationState.SOFT_DELETE) },
order: { name: 'ASC' },
take: limit,
skip: offset
});
const endTime = performance.now();
(0, Logger_1.logDatabase)('Organization page query completed', `executionTime: ${Math.round(endTime - startTime)}ms, found: ${organizations.length}, total: ${totalCount}, from: ${from}, to: ${to}`);
return { organizations, totalCount };
}
catch (error) {
const endTime = performance.now();
(0, Logger_1.logDatabase)('Organization page query failed', `executionTime: ${Math.round(endTime - startTime)}ms, from: ${from}, to: ${to}`);
(0, Logger_1.logError)('OrganizationRepository.findByPage error', error instanceof Error ? error : new Error(String(error)));
throw new Error('Failed to get organizations 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 organizations = await this.repo.find({
order: { name: 'ASC' },
take: limit,
skip: offset
});
const endTime = performance.now();
(0, Logger_1.logDatabase)('Organization page query completed (including deleted)', `executionTime: ${Math.round(endTime - startTime)}ms, found: ${organizations.length}, total: ${totalCount}, from: ${from}, to: ${to}`);
return { organizations, totalCount };
}
catch (error) {
const endTime = performance.now();
(0, Logger_1.logDatabase)('Organization page query failed (including deleted)', `executionTime: ${Math.round(endTime - startTime)}ms, from: ${from}, to: ${to}`);
(0, Logger_1.logError)('OrganizationRepository.findByPageIncludingDeleted error', error instanceof Error ? error : new Error(String(error)));
throw new Error('Failed to get organizations page from database');
}
}
async findById(id) {
return this.repo.findOne({
where: {
id,
state: (0, typeorm_1.Not)(OrganizationAggregate_1.OrganizationState.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: OrganizationAggregate_1.OrganizationState.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('org')
.where('org.state != :softDelete', { softDelete: OrganizationAggregate_1.OrganizationState.SOFT_DELETE })
.andWhere('(LOWER(org.name) LIKE :pattern OR LOWER(org.contactfname) LIKE :pattern OR LOWER(org.contactlname) LIKE :pattern OR LOWER(org.contactemail) LIKE :pattern OR LOWER(CONCAT(org.contactfname, \' \', org.contactlname)) LIKE :pattern)', { pattern: searchPattern });
const totalCount = await queryBuilder.getCount();
const organizations = await queryBuilder
.orderBy('org.name', 'ASC')
.limit(limit)
.offset(offset)
.getMany();
const endTime = performance.now();
(0, Logger_1.logDatabase)('Organization search completed', `executionTime: ${Math.round(endTime - startTime)}ms, found: ${organizations.length}, total: ${totalCount}, searchTerm: "${query}", limit: ${limit}, offset: ${offset}`);
return { organizations, totalCount };
}
catch (error) {
const endTime = performance.now();
(0, Logger_1.logDatabase)('Organization search failed', `executionTime: ${Math.round(endTime - startTime)}ms, searchTerm: "${query}"`);
(0, Logger_1.logError)('OrganizationRepository.search error', error instanceof Error ? error : new Error(String(error)));
throw new Error('Failed to search organizations in database');
}
}
async searchIncludingDeleted(query, limit = 20, offset = 0) {
const startTime = performance.now();
try {
const searchPattern = `%${query.toLowerCase()}%`;
const queryBuilder = this.repo.createQueryBuilder('org')
.where('LOWER(org.name) LIKE :pattern', { pattern: searchPattern })
.orWhere('LOWER(org.contactfname) LIKE :pattern', { pattern: searchPattern })
.orWhere('LOWER(org.contactlname) LIKE :pattern', { pattern: searchPattern })
.orWhere('LOWER(org.contactemail) LIKE :pattern', { pattern: searchPattern })
.orWhere('LOWER(CONCAT(org.contactfname, \' \', org.contactlname)) LIKE :pattern', { pattern: searchPattern });
const totalCount = await queryBuilder.getCount();
const organizations = await queryBuilder
.orderBy('org.name', 'ASC')
.limit(limit)
.offset(offset)
.getMany();
const endTime = performance.now();
(0, Logger_1.logDatabase)('Organization search completed (including deleted)', `executionTime: ${Math.round(endTime - startTime)}ms, found: ${organizations.length}, total: ${totalCount}, searchTerm: "${query}", limit: ${limit}, offset: ${offset}`);
return { organizations, totalCount };
}
catch (error) {
const endTime = performance.now();
(0, Logger_1.logDatabase)('Organization search failed (including deleted)', `executionTime: ${Math.round(endTime - startTime)}ms, searchTerm: "${query}"`);
(0, Logger_1.logError)('OrganizationRepository.searchIncludingDeleted error', error instanceof Error ? error : new Error(String(error)));
throw new Error('Failed to search all organizations in database');
}
}
}
exports.OrganizationRepository = OrganizationRepository;
//# sourceMappingURL=OrganizationRepository.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,33 @@
import { UserAggregate } from '../../Domain/User/UserAggregate';
import { IUserRepository } from '../../Domain/IRepository/IUserRepository';
export declare class UserRepository implements IUserRepository {
private repo;
constructor();
create(user: Partial<UserAggregate>): Promise<Partial<UserAggregate> & UserAggregate>;
findByPage(from: number, to: number): Promise<{
users: UserAggregate[];
totalCount: number;
}>;
findByPageIncludingDeleted(from: number, to: number): Promise<{
users: UserAggregate[];
totalCount: number;
}>;
findById(id: string): Promise<UserAggregate | null>;
findByIdIncludingDeleted(id: string): Promise<UserAggregate | null>;
findByUsername(username: string): Promise<UserAggregate | null>;
findByEmail(email: string): Promise<UserAggregate | null>;
findByToken(token: string): Promise<UserAggregate | null>;
update(id: string, update: Partial<UserAggregate>): Promise<UserAggregate | null>;
delete(id: string): Promise<import("typeorm").DeleteResult>;
softDelete(id: string): Promise<UserAggregate | null>;
deactivate(id: string): Promise<UserAggregate | null>;
search(query: string, limit?: number, offset?: number): Promise<{
users: UserAggregate[];
totalCount: number;
}>;
searchIncludingDeleted(query: string, limit?: number, offset?: number): Promise<{
users: UserAggregate[];
totalCount: number;
}>;
}
//# sourceMappingURL=UserRepository.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"UserRepository.d.ts","sourceRoot":"","sources":["../../../src/Infrastructure/Repository/UserRepository.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAa,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAG3E,qBAAa,cAAe,YAAW,eAAe;IAClD,OAAO,CAAC,IAAI,CAA4B;;IAKlC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,aAAa,CAAC;IAsBnC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IA+B7F,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IA4B7G,QAAQ,CAAC,EAAE,EAAE,MAAM;IAyBnB,wBAAwB,CAAC,EAAE,EAAE,MAAM;IAoBnC,cAAc,CAAC,QAAQ,EAAE,MAAM;IAe/B,WAAW,CAAC,KAAK,EAAE,MAAM;IAezB,WAAW,CAAC,KAAK,EAAE,MAAM;IAezB,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC;IA4BjD,MAAM,CAAC,EAAE,EAAE,MAAM;IAqBjB,UAAU,CAAC,EAAE,EAAE,MAAM;IAsBrB,UAAU,CAAC,EAAE,EAAE,MAAM;IAsBrB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,MAAM,GAAE,MAAU,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAkCtH,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,MAAM,GAAE,MAAU,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAsC/I"}
@@ -0,0 +1,312 @@
"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
File diff suppressed because one or more lines are too long