A social knowledge tool for researchers built on ATProto
at main 146 lines 4.9 kB view raw
1import { Result, ok, err } from '../../../../../shared/core/Result'; 2import { UseCase } from '../../../../../shared/core/UseCase'; 3import { UseCaseError } from '../../../../../shared/core/UseCaseError'; 4import { AppError } from '../../../../../shared/core/AppError'; 5import { ICardRepository } from '../../../domain/ICardRepository'; 6import { CardId } from '../../../domain/value-objects/CardId'; 7import { CollectionId } from '../../../domain/value-objects/CollectionId'; 8import { CuratorId } from '../../../domain/value-objects/CuratorId'; 9import { CardLibraryService } from '../../../domain/services/CardLibraryService'; 10import { CardCollectionService } from '../../../domain/services/CardCollectionService'; 11import { AuthenticationError } from '../../../../../shared/core/AuthenticationError'; 12 13export interface AddCardToLibraryDTO { 14 cardId: string; 15 curatorId: string; 16 collectionIds?: string[]; 17} 18 19export interface AddCardToLibraryResponseDTO { 20 cardId: string; 21} 22 23export class ValidationError extends UseCaseError { 24 constructor(message: string) { 25 super(message); 26 } 27} 28 29export class AddCardToLibraryUseCase 30 implements 31 UseCase< 32 AddCardToLibraryDTO, 33 Result< 34 AddCardToLibraryResponseDTO, 35 ValidationError | AuthenticationError | AppError.UnexpectedError 36 > 37 > 38{ 39 constructor( 40 private cardRepository: ICardRepository, 41 private cardLibraryService: CardLibraryService, 42 private cardCollectionService: CardCollectionService, 43 ) {} 44 45 async execute( 46 request: AddCardToLibraryDTO, 47 ): Promise< 48 Result< 49 AddCardToLibraryResponseDTO, 50 ValidationError | AuthenticationError | AppError.UnexpectedError 51 > 52 > { 53 try { 54 // Validate and create CuratorId 55 const curatorIdResult = CuratorId.create(request.curatorId); 56 if (curatorIdResult.isErr()) { 57 return err( 58 new ValidationError( 59 `Invalid curator ID: ${curatorIdResult.error.message}`, 60 ), 61 ); 62 } 63 const curatorId = curatorIdResult.value; 64 65 // Validate and create CardId 66 const cardIdResult = CardId.createFromString(request.cardId); 67 if (cardIdResult.isErr()) { 68 return err( 69 new ValidationError(`Invalid card ID: ${cardIdResult.error.message}`), 70 ); 71 } 72 const cardId = cardIdResult.value; 73 74 // Find the card 75 const cardResult = await this.cardRepository.findById(cardId); 76 if (cardResult.isErr()) { 77 return err(AppError.UnexpectedError.create(cardResult.error)); 78 } 79 80 const card = cardResult.value; 81 if (!card) { 82 return err(new ValidationError(`Card not found: ${request.cardId}`)); 83 } 84 85 // Add card to library using domain service 86 const addToLibraryResult = await this.cardLibraryService.addCardToLibrary( 87 card, 88 curatorId, 89 ); 90 if (addToLibraryResult.isErr()) { 91 // Propagate authentication errors 92 if (addToLibraryResult.error instanceof AuthenticationError) { 93 return err(addToLibraryResult.error); 94 } 95 if (addToLibraryResult.error instanceof AppError.UnexpectedError) { 96 return err(addToLibraryResult.error); 97 } 98 return err(new ValidationError(addToLibraryResult.error.message)); 99 } 100 101 // Handle collection additions if specified 102 if (request.collectionIds && request.collectionIds.length > 0) { 103 // Validate and create CollectionIds 104 const collectionIds: CollectionId[] = []; 105 for (const collectionIdStr of request.collectionIds) { 106 const collectionIdResult = 107 CollectionId.createFromString(collectionIdStr); 108 if (collectionIdResult.isErr()) { 109 return err( 110 new ValidationError( 111 `Invalid collection ID: ${collectionIdResult.error.message}`, 112 ), 113 ); 114 } 115 collectionIds.push(collectionIdResult.value); 116 } 117 118 // Add card to collections using domain service 119 const addToCollectionsResult = 120 await this.cardCollectionService.addCardToCollections( 121 card, 122 collectionIds, 123 curatorId, 124 ); 125 if (addToCollectionsResult.isErr()) { 126 // Propagate authentication errors 127 if (addToCollectionsResult.error instanceof AuthenticationError) { 128 return err(addToCollectionsResult.error); 129 } 130 if ( 131 addToCollectionsResult.error instanceof AppError.UnexpectedError 132 ) { 133 return err(addToCollectionsResult.error); 134 } 135 return err(new ValidationError(addToCollectionsResult.error.message)); 136 } 137 } 138 139 return ok({ 140 cardId: card.cardId.getStringValue(), 141 }); 142 } catch (error) { 143 return err(AppError.UnexpectedError.create(error)); 144 } 145 } 146}