A social knowledge tool for researchers built on ATProto
at development 103 lines 2.8 kB view raw
1import { UseCase } from 'src/shared/core/UseCase'; 2import { ICardQueryRepository } from '../../../domain/ICardQueryRepository'; 3import { IProfileService } from '../../../domain/services/IProfileService'; 4import { err, ok, Result } from 'src/shared/core/Result'; 5 6export interface GetLibrariesForCardQuery { 7 cardId: string; 8} 9 10export interface LibraryUserDTO { 11 id: string; 12 name: string; 13 handle: string; 14 avatarUrl?: string; 15} 16 17export interface GetLibrariesForCardResult { 18 cardId: string; 19 users: LibraryUserDTO[]; 20 totalCount: number; 21} 22 23export class ValidationError extends Error { 24 constructor(message: string) { 25 super(message); 26 this.name = 'ValidationError'; 27 } 28} 29 30export class GetLibrariesForCardUseCase 31 implements 32 UseCase<GetLibrariesForCardQuery, Result<GetLibrariesForCardResult>> 33{ 34 constructor( 35 private cardQueryRepo: ICardQueryRepository, 36 private profileService: IProfileService, 37 ) {} 38 39 async execute( 40 query: GetLibrariesForCardQuery, 41 ): Promise<Result<GetLibrariesForCardResult>> { 42 // Validate card ID 43 if (!query.cardId || query.cardId.trim().length === 0) { 44 return err(new ValidationError('Card ID is required')); 45 } 46 47 try { 48 // Get user IDs who have this card in their library 49 const userIds = await this.cardQueryRepo.getLibrariesForCard( 50 query.cardId, 51 ); 52 53 // Fetch profiles for all users 54 const profilePromises = userIds.map((userId) => 55 this.profileService.getProfile(userId), 56 ); 57 58 const profileResults = await Promise.all(profilePromises); 59 60 // Filter out failed profile fetches and transform to DTOs 61 const users: LibraryUserDTO[] = []; 62 const errors: string[] = []; 63 64 for (let i = 0; i < profileResults.length; i++) { 65 const result = profileResults[i]; 66 if (!result) { 67 errors.push(`No profile found for user ${userIds[i]}`); 68 continue; 69 } 70 if (result.isOk()) { 71 const profile = result.value; 72 users.push({ 73 id: profile.id, 74 name: profile.name, 75 handle: profile.handle, 76 avatarUrl: profile.avatarUrl, 77 }); 78 } else { 79 errors.push( 80 `Failed to fetch profile for user ${userIds[i]}: ${result.error.message}`, 81 ); 82 } 83 } 84 85 // Log errors but don't fail the entire operation 86 if (errors.length > 0) { 87 console.warn('Some profile fetches failed:', errors); 88 } 89 90 return ok({ 91 cardId: query.cardId, 92 users, 93 totalCount: users.length, 94 }); 95 } catch (error) { 96 return err( 97 new Error( 98 `Failed to get libraries for card: ${error instanceof Error ? error.message : 'Unknown error'}`, 99 ), 100 ); 101 } 102 } 103}