/** * Infrastructure: InMemoryPageViewRepository * * In-memory implementation of IPageViewRepository for development/testing. */ import type { IPageViewRepository } from '../../domain/repositories/IPageViewRepository'; import { PageView, type EntityType } from '../../domain/entities/PageView'; export class InMemoryPageViewRepository implements IPageViewRepository { private pageViews: Map = new Map(); async save(pageView: PageView): Promise { this.pageViews.set(pageView.id, pageView); } async findById(id: string): Promise { return this.pageViews.get(id) ?? null; } async findByEntityId(entityType: EntityType, entityId: string): Promise { return Array.from(this.pageViews.values()).filter( pv => pv.entityType === entityType && pv.entityId === entityId ); } async findByDateRange(startDate: Date, endDate: Date): Promise { return Array.from(this.pageViews.values()).filter( pv => pv.timestamp >= startDate && pv.timestamp <= endDate ); } async findBySession(sessionId: string): Promise { return Array.from(this.pageViews.values()).filter( pv => pv.sessionId === sessionId ); } async countByEntityId(entityType: EntityType, entityId: string, since?: Date): Promise { return Array.from(this.pageViews.values()).filter( pv => pv.entityType === entityType && pv.entityId === entityId && (!since || pv.timestamp >= since) ).length; } async countUniqueVisitors(entityType: EntityType, entityId: string, since?: Date): Promise { const visitors = new Set(); Array.from(this.pageViews.values()) .filter( pv => pv.entityType === entityType && pv.entityId === entityId && (!since || pv.timestamp >= since) ) .forEach(pv => { visitors.add(pv.visitorId ?? pv.sessionId); }); return visitors.size; } // Helper for testing clear(): void { this.pageViews.clear(); } // Helper for seeding demo data seed(pageViews: PageView[]): void { pageViews.forEach(pv => this.pageViews.set(pv.id, pv)); } }