This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

semble / src / modules / cards / application / useCases / queries / GetNoteCardsForUrlUseCase.ts
4.4 kB 151 lines
1import { Result, ok, err } from '../../../../../shared/core/Result'; 2import { UseCase } from '../../../../../shared/core/UseCase'; 3import { 4 ICardQueryRepository, 5 CardSortField, 6 SortOrder, 7} from '../../../domain/ICardQueryRepository'; 8import { URL } from '../../../domain/value-objects/URL'; 9import { IProfileService } from '../../../domain/services/IProfileService'; 10import { NoteCardDTO, PaginationDTO, CardSortingDTO } from '../../dtos'; 11 12export interface GetNoteCardsForUrlQuery { 13 url: string; 14 callingUserId?: string; 15 page?: number; 16 limit?: number; 17 sortBy?: CardSortField; 18 sortOrder?: SortOrder; 19} 20 21export interface GetNoteCardsForUrlResult { 22 notes: NoteCardDTO[]; 23 pagination: PaginationDTO; 24 sorting: CardSortingDTO; 25} 26 27export class ValidationError extends Error { 28 constructor(message: string) { 29 super(message); 30 this.name = 'ValidationError'; 31 } 32} 33 34export class GetNoteCardsForUrlUseCase 35 implements UseCase<GetNoteCardsForUrlQuery, Result<GetNoteCardsForUrlResult>> 36{ 37 constructor( 38 private cardQueryRepo: ICardQueryRepository, 39 private profileService: IProfileService, 40 ) {} 41 42 async execute( 43 query: GetNoteCardsForUrlQuery, 44 ): Promise<Result<GetNoteCardsForUrlResult>> { 45 // Validate URL 46 const urlResult = URL.create(query.url); 47 if (urlResult.isErr()) { 48 return err( 49 new ValidationError(`Invalid URL: ${urlResult.error.message}`), 50 ); 51 } 52 53 // Set defaults 54 const page = query.page || 1; 55 const limit = Math.min(query.limit || 20, 100); // Cap at 100 56 const sortBy = query.sortBy || CardSortField.UPDATED_AT; 57 const sortOrder = query.sortOrder || SortOrder.DESC; 58 59 try { 60 // Execute query to get note cards for the URL (raw data with authorId) 61 const result = await this.cardQueryRepo.getNoteCardsForUrl(query.url, { 62 page, 63 limit, 64 sortBy, 65 sortOrder, 66 }); 67 68 // Enrich with author profiles 69 const uniqueAuthorIds = Array.from( 70 new Set(result.items.map((item) => item.authorId)), 71 ); 72 73 const profilePromises = uniqueAuthorIds.map((authorId) => 74 this.profileService.getProfile(authorId, query.callingUserId), 75 ); 76 77 const profileResults = await Promise.all(profilePromises); 78 79 // Create a map of profiles 80 const profileMap = new Map< 81 string, 82 { 83 id: string; 84 name: string; 85 handle: string; 86 avatarUrl?: string; 87 description?: string; 88 } 89 >(); 90 91 for (let i = 0; i < uniqueAuthorIds.length; i++) { 92 const profileResult = profileResults[i]; 93 const authorId = uniqueAuthorIds[i]; 94 if (!profileResult || !authorId) { 95 return err(new Error('Missing profile result or author ID')); 96 } 97 if (profileResult.isErr()) { 98 return err( 99 new Error( 100 `Failed to fetch author profile: ${profileResult.error instanceof Error ? profileResult.error.message : 'Unknown error'}`, 101 ), 102 ); 103 } 104 const profile = profileResult.value; 105 profileMap.set(authorId, { 106 id: profile.id, 107 name: profile.name, 108 handle: profile.handle, 109 avatarUrl: profile.avatarUrl, 110 description: profile.bio, 111 }); 112 } 113 114 // Map items with enriched author data 115 const enrichedNotes: NoteCardDTO[] = result.items.map((item) => { 116 const author = profileMap.get(item.authorId); 117 if (!author) { 118 throw new Error(`Profile not found for author ${item.authorId}`); 119 } 120 return { 121 id: item.id, 122 note: item.note, 123 author, 124 createdAt: item.createdAt.toISOString(), 125 updatedAt: item.updatedAt.toISOString(), 126 }; 127 }); 128 129 return ok({ 130 notes: enrichedNotes, 131 pagination: { 132 currentPage: page, 133 totalPages: Math.ceil(result.totalCount / limit), 134 totalCount: result.totalCount, 135 hasMore: page * limit < result.totalCount, 136 limit, 137 }, 138 sorting: { 139 sortBy, 140 sortOrder, 141 }, 142 }); 143 } catch (error) { 144 return err( 145 new Error( 146 `Failed to retrieve note cards for URL: ${error instanceof Error ? error.message : 'Unknown error'}`, 147 ), 148 ); 149 } 150 } 151}