/** * In-Memory User Repository * * Stores users in memory for demo/development purposes. */ import { Logger } from '@core/shared/application'; import type { IUserRepository, StoredUser } from '../../domain/repositories/IUserRepository'; export class InMemoryUserRepository implements IUserRepository { private users: Map = new Map(); private emailIndex: Map = new Map(); // email -> userId private readonly logger: Logger; constructor(logger: Logger, initialUsers: StoredUser[] = []) { this.logger = logger; this.logger.info('InMemoryUserRepository initialized.'); for (const user of initialUsers) { this.users.set(user.id, user); this.emailIndex.set(user.email.toLowerCase(), user.id); this.logger.debug(`Seeded user: ${user.id} (${user.email}).`); } } async findByEmail(email: string): Promise { this.logger.debug(`Finding user by email: ${email}`); try { const userId = this.emailIndex.get(email.toLowerCase()); if (!userId) { this.logger.warn(`User with email ${email} not found.`); return null; } const user = this.users.get(userId) ?? null; if (user) { this.logger.info(`Found user by email: ${email}.`); } else { this.logger.warn(`User with ID ${userId} (from email index) not found.`); } return user; } catch (error) { this.logger.error(`Error finding user by email ${email}:`, error); throw error; } } async findById(id: string): Promise { this.logger.debug(`Finding user by id: ${id}`); try { const user = this.users.get(id) ?? null; if (user) { this.logger.info(`Found user: ${id}.`); } else { this.logger.warn(`User with id ${id} not found.`); } return user; } catch (error) { this.logger.error(`Error finding user by id ${id}:`, error); throw error; } } async create(user: StoredUser): Promise { this.logger.debug(`Creating user: ${user.id} with email: ${user.email}`); try { if (this.emailIndex.has(user.email.toLowerCase())) { this.logger.warn(`Email ${user.email} already exists.`); throw new Error('Email already exists'); } this.users.set(user.id, user); this.emailIndex.set(user.email.toLowerCase(), user.id); this.logger.info(`User ${user.id} (${user.email}) created successfully.`); return user; } catch (error) { this.logger.error(`Error creating user ${user.id} (${user.email}):`, error); throw error; } } async update(user: StoredUser): Promise { this.logger.debug(`Updating user: ${user.id} with email: ${user.email}`); try { const existing = this.users.get(user.id); if (!existing) { this.logger.warn(`User with ID ${user.id} not found for update.`); throw new Error('User not found'); } // If email changed, update index if (existing.email.toLowerCase() !== user.email.toLowerCase()) { if (this.emailIndex.has(user.email.toLowerCase()) && this.emailIndex.get(user.email.toLowerCase()) !== user.id) { this.logger.warn(`Cannot update user ${user.id} to email ${user.email} as it's already taken.`); throw new Error('Email already exists for another user'); } this.logger.debug(`Updating email index from ${existing.email} to ${user.email}.`); this.emailIndex.delete(existing.email.toLowerCase()); this.emailIndex.set(user.email.toLowerCase(), user.id); } this.users.set(user.id, user); this.logger.info(`User ${user.id} (${user.email}) updated successfully.`); return user; } catch (error) { this.logger.error(`Error updating user ${user.id} (${user.email}):`, error); throw error; } } async emailExists(email: string): Promise { this.logger.debug(`Checking existence of email: ${email}`); try { const exists = this.emailIndex.has(email.toLowerCase()); this.logger.debug(`Email ${email} exists: ${exists}.`); return exists; } catch (error) { this.logger.error(`Error checking existence of email ${email}:`, error); throw error; } } }