112 lines
3.5 KiB
TypeScript
112 lines
3.5 KiB
TypeScript
import { IExternalGameRatingRepository, PaginatedQueryOptions, PaginatedResult } from '@core/identity/domain/repositories/IExternalGameRatingRepository';
|
|
import { ExternalGameRatingProfile } from '@core/identity/domain/entities/ExternalGameRatingProfile';
|
|
|
|
/**
|
|
* In-Memory Implementation: IExternalGameRatingRepository
|
|
*
|
|
* For testing and development purposes.
|
|
*/
|
|
export class InMemoryExternalGameRatingRepository implements IExternalGameRatingRepository {
|
|
private profiles: Map<string, ExternalGameRatingProfile> = new Map();
|
|
|
|
private getKey(userId: string, gameKey: string): string {
|
|
return `${userId}|${gameKey}`;
|
|
}
|
|
|
|
async findByUserIdAndGameKey(
|
|
userId: string,
|
|
gameKey: string
|
|
): Promise<ExternalGameRatingProfile | null> {
|
|
const key = this.getKey(userId, gameKey);
|
|
return this.profiles.get(key) || null;
|
|
}
|
|
|
|
async findByUserId(userId: string): Promise<ExternalGameRatingProfile[]> {
|
|
return Array.from(this.profiles.values()).filter(
|
|
p => p.userId.toString() === userId
|
|
);
|
|
}
|
|
|
|
async findByGameKey(gameKey: string): Promise<ExternalGameRatingProfile[]> {
|
|
return Array.from(this.profiles.values()).filter(
|
|
p => p.gameKey.toString() === gameKey
|
|
);
|
|
}
|
|
|
|
async save(profile: ExternalGameRatingProfile): Promise<ExternalGameRatingProfile> {
|
|
const key = this.getKey(profile.userId.toString(), profile.gameKey.toString());
|
|
this.profiles.set(key, profile);
|
|
return profile;
|
|
}
|
|
|
|
async saveMany(profiles: ExternalGameRatingProfile[]): Promise<ExternalGameRatingProfile[]> {
|
|
for (const profile of profiles) {
|
|
await this.save(profile);
|
|
}
|
|
return profiles;
|
|
}
|
|
|
|
async delete(userId: string, gameKey: string): Promise<boolean> {
|
|
const key = this.getKey(userId, gameKey);
|
|
return this.profiles.delete(key);
|
|
}
|
|
|
|
async exists(userId: string, gameKey: string): Promise<boolean> {
|
|
const key = this.getKey(userId, gameKey);
|
|
return this.profiles.has(key);
|
|
}
|
|
|
|
async findProfilesPaginated(userId: string, options?: PaginatedQueryOptions): Promise<PaginatedResult<ExternalGameRatingProfile>> {
|
|
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<ExternalGameRatingProfile> = {
|
|
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());
|
|
}
|
|
}
|