refactor adapters
This commit is contained in:
117
adapters/identity/persistence/inmemory/InMemoryUserRepository.ts
Normal file
117
adapters/identity/persistence/inmemory/InMemoryUserRepository.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* In-Memory User Repository
|
||||
*
|
||||
* Stores users in memory for demo/development purposes.
|
||||
*/
|
||||
|
||||
import type { IUserRepository, StoredUser } from '../../domain/repositories/IUserRepository';
|
||||
import type { ILogger } from '@gridpilot/shared/logging/ILogger';
|
||||
|
||||
export class InMemoryUserRepository implements IUserRepository {
|
||||
private users: Map<string, StoredUser> = new Map();
|
||||
private emailIndex: Map<string, string> = new Map(); // email -> userId
|
||||
private readonly logger: ILogger;
|
||||
|
||||
constructor(logger: ILogger, 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<StoredUser | null> {
|
||||
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<StoredUser | null> {
|
||||
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<StoredUser> {
|
||||
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<StoredUser> {
|
||||
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<boolean> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user