/** * Infrastructure: InMemoryAnalyticsSnapshotRepository * * In-memory implementation of IAnalyticsSnapshotRepository for development/testing. */ import { AnalyticsSnapshot, IAnalyticsSnapshotRepository, SnapshotEntityType, SnapshotPeriod } from '@core/analytics'; import { Logger } from '@core/shared/application'; export class InMemoryAnalyticsSnapshotRepository implements IAnalyticsSnapshotRepository { private snapshots: Map = new Map(); private readonly logger: Logger; constructor(logger: Logger) { this.logger = logger; this.logger.info('InMemoryAnalyticsSnapshotRepository initialized.'); } async save(snapshot: AnalyticsSnapshot): Promise { this.logger.debug(`Saving AnalyticsSnapshot: ${snapshot.id}`); try { this.snapshots.set(snapshot.id, snapshot); this.logger.info(`AnalyticsSnapshot ${snapshot.id} saved successfully.`); } catch (error) { this.logger.error(`Error saving AnalyticsSnapshot ${snapshot.id}:`, error instanceof Error ? error : new Error(String(error))); throw error; } } async findById(id: string): Promise { this.logger.debug(`Finding AnalyticsSnapshot by ID: ${id}`); try { const snapshot = this.snapshots.get(id) ?? null; if (snapshot) { this.logger.info(`Found AnalyticsSnapshot with ID: ${id}`); } else { this.logger.warn(`AnalyticsSnapshot with ID ${id} not found.`); } return snapshot; } catch (error) { this.logger.error(`Error finding AnalyticsSnapshot by ID ${id}:`, error instanceof Error ? error : new Error(String(error))); throw error; } } async findByEntity(entityType: SnapshotEntityType, entityId: string): Promise { this.logger.debug(`Finding AnalyticsSnapshots by Entity: ${entityType}, ${entityId}`); try { const snapshots = Array.from(this.snapshots.values()).filter( s => s.entityType === entityType && s.entityId === entityId ); this.logger.info(`Found ${snapshots.length} AnalyticsSnapshots for entity ${entityId}.`); return snapshots; } catch (error) { this.logger.error(`Error finding AnalyticsSnapshots for entity ${entityId}:`, error instanceof Error ? error : new Error(String(error))); throw error; } } async findByPeriod( entityType: SnapshotEntityType, entityId: string, period: SnapshotPeriod, startDate: Date, endDate: Date ): Promise { this.logger.debug(`Finding AnalyticsSnapshot by Period for entity ${entityId}, period ${period}, from ${startDate.toISOString()} to ${endDate.toISOString()}`); try { const snapshot = Array.from(this.snapshots.values()).find( s => s.entityType === entityType && s.entityId === entityId && s.period === period && s.startDate >= startDate && s.endDate <= endDate ) ?? null; if (snapshot) { this.logger.info(`Found AnalyticsSnapshot for entity ${entityId}, period ${period}.`); } else { this.logger.warn(`No AnalyticsSnapshot found for entity ${entityId}, period ${period}, from ${startDate.toISOString()} to ${endDate.toISOString()}.`); } return snapshot; } catch (error) { this.logger.error(`Error finding AnalyticsSnapshot by period for entity ${entityId}:`, error instanceof Error ? error : new Error(String(error))); throw error; } } async findLatest( entityType: SnapshotEntityType, entityId: string, period: SnapshotPeriod ): Promise { this.logger.debug(`Finding latest AnalyticsSnapshot for entity ${entityId}, period ${period}`); try { const matching = Array.from(this.snapshots.values()) .filter(s => s.entityType === entityType && s.entityId === entityId && s.period === period) .sort((a, b) => b.endDate.getTime() - a.endDate.getTime()); const snapshot = matching[0] ?? null; if (snapshot) { this.logger.info(`Found latest AnalyticsSnapshot for entity ${entityId}, period ${period}.`); } else { this.logger.warn(`No latest AnalyticsSnapshot found for entity ${entityId}, period ${period}.`); } return snapshot; } catch (error) { this.logger.error(`Error finding latest AnalyticsSnapshot for entity ${entityId}:`, error instanceof Error ? error : new Error(String(error))); throw error; } } async getHistoricalSnapshots( entityType: SnapshotEntityType, entityId: string, period: SnapshotPeriod, limit: number ): Promise { this.logger.debug(`Getting historical AnalyticsSnapshots for entity ${entityId}, period ${period}, limit ${limit}`); try { const snapshots = Array.from(this.snapshots.values()) .filter(s => s.entityType === entityType && s.entityId === entityId && s.period === period) .sort((a, b) => b.endDate.getTime() - a.endDate.getTime()) .slice(0, limit); this.logger.info(`Found ${snapshots.length} historical AnalyticsSnapshots for entity ${entityId}, period ${period}.`); return snapshots; } catch (error) { this.logger.error(`Error getting historical AnalyticsSnapshots for entity ${entityId}:`, error instanceof Error ? error : new Error(String(error))); throw error; } } // Helper for testing clear(): void { this.snapshots.clear(); } // Helper for seeding demo data seed(snapshots: AnalyticsSnapshot[]): void { snapshots.forEach(s => this.snapshots.set(s.id, s)); } }