import { ExternalGameRatingRepository, PaginatedQueryOptions, PaginatedResult } from '@core/identity/domain/repositories/ExternalGameRatingRepository'; import { ExternalGameRatingProfile } from '@core/identity/domain/entities/ExternalGameRatingProfile'; /** * In-Memory Implementation: IExternalGameRatingRepository * * For testing and development purposes. */ export class InMemoryExternalGameRatingRepository implements ExternalGameRatingRepository { private profiles: Map = new Map(); private getKey(userId: string, gameKey: string): string { return `${userId}|${gameKey}`; } async findByUserIdAndGameKey( userId: string, gameKey: string ): Promise { const key = this.getKey(userId, gameKey); return this.profiles.get(key) || null; } async findByUserId(userId: string): Promise { return Array.from(this.profiles.values()).filter( p => p.userId.toString() === userId ); } async findByGameKey(gameKey: string): Promise { return Array.from(this.profiles.values()).filter( p => p.gameKey.toString() === gameKey ); } async save(profile: ExternalGameRatingProfile): Promise { const key = this.getKey(profile.userId.toString(), profile.gameKey.toString()); this.profiles.set(key, profile); return profile; } async saveMany(profiles: ExternalGameRatingProfile[]): Promise { for (const profile of profiles) { await this.save(profile); } return profiles; } async delete(userId: string, gameKey: string): Promise { const key = this.getKey(userId, gameKey); return this.profiles.delete(key); } async exists(userId: string, gameKey: string): Promise { const key = this.getKey(userId, gameKey); return this.profiles.has(key); } async findProfilesPaginated(userId: string, options?: PaginatedQueryOptions): Promise> { const allProfiles = await this.findByUserId(userId); // Apply filters let filtered = allProfiles; if (options?.filter) { const filter = options.filter; if (filter.gameKeys) { filtered = filtered.filter(p => filter.gameKeys!.includes(p.gameKey.toString())); } if (filter.sources) { filtered = filtered.filter(p => filter.sources!.includes(p.provenance.source)); } if (filter.verified !== undefined) { filtered = filtered.filter(p => p.provenance.verified === filter.verified); } if (filter.lastSyncedAfter) { filtered = filtered.filter(p => p.provenance.lastSyncedAt >= filter.lastSyncedAfter!); } } const total = filtered.length; const limit = options?.limit ?? 10; const offset = options?.offset ?? 0; const items = filtered.slice(offset, offset + limit); const hasMore = offset + limit < total; const nextOffset = hasMore ? offset + limit : undefined; const result: PaginatedResult = { items, total, limit, offset, hasMore }; if (nextOffset !== undefined) { result.nextOffset = nextOffset; } return result; } // Helper method for testing clear(): void { this.profiles.clear(); } // Helper method for testing getAll(): ExternalGameRatingProfile[] { return Array.from(this.profiles.values()); } }