A social knowledge tool for researchers built on ATProto
at development 109 lines 3.4 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 { CuratorId } from '../../../domain/value-objects/CuratorId'; 8import { CardLibraryService } from '../../../domain/services/CardLibraryService'; 9 10export interface RemoveCardFromLibraryDTO { 11 cardId: string; 12 curatorId: string; 13} 14 15export interface RemoveCardFromLibraryResponseDTO { 16 cardId: string; 17} 18 19export class ValidationError extends UseCaseError { 20 constructor(message: string) { 21 super(message); 22 } 23} 24 25export class RemoveCardFromLibraryUseCase 26 implements 27 UseCase< 28 RemoveCardFromLibraryDTO, 29 Result< 30 RemoveCardFromLibraryResponseDTO, 31 ValidationError | AppError.UnexpectedError 32 > 33 > 34{ 35 constructor( 36 private cardRepository: ICardRepository, 37 private cardLibraryService: CardLibraryService, 38 ) {} 39 40 async execute( 41 request: RemoveCardFromLibraryDTO, 42 ): Promise< 43 Result< 44 RemoveCardFromLibraryResponseDTO, 45 ValidationError | AppError.UnexpectedError 46 > 47 > { 48 try { 49 // Validate and create CuratorId 50 const curatorIdResult = CuratorId.create(request.curatorId); 51 if (curatorIdResult.isErr()) { 52 return err( 53 new ValidationError( 54 `Invalid curator ID: ${curatorIdResult.error.message}`, 55 ), 56 ); 57 } 58 const curatorId = curatorIdResult.value; 59 60 // Validate and create CardId 61 const cardIdResult = CardId.createFromString(request.cardId); 62 if (cardIdResult.isErr()) { 63 return err( 64 new ValidationError(`Invalid card ID: ${cardIdResult.error.message}`), 65 ); 66 } 67 const cardId = cardIdResult.value; 68 69 // Find the card 70 const cardResult = await this.cardRepository.findById(cardId); 71 if (cardResult.isErr()) { 72 return err(AppError.UnexpectedError.create(cardResult.error)); 73 } 74 75 const card = cardResult.value; 76 if (!card) { 77 return err(new ValidationError(`Card not found: ${request.cardId}`)); 78 } 79 80 // Remove card from library using domain service 81 const removeFromLibraryResult = 82 await this.cardLibraryService.removeCardFromLibrary(card, curatorId); 83 if (removeFromLibraryResult.isErr()) { 84 if (removeFromLibraryResult.error instanceof AppError.UnexpectedError) { 85 return err(removeFromLibraryResult.error); 86 } 87 return err(new ValidationError(removeFromLibraryResult.error.message)); 88 } 89 90 const updatedCard = removeFromLibraryResult.value; 91 if ( 92 updatedCard.libraryCount == 0 && 93 updatedCard.curatorId.equals(curatorId) 94 ) { 95 // If no curators have this card in their library and the curator is the owner, delete the card 96 const deleteResult = await this.cardRepository.delete(card.cardId); 97 if (deleteResult.isErr()) { 98 return err(AppError.UnexpectedError.create(deleteResult.error)); 99 } 100 } 101 102 return ok({ 103 cardId: card.cardId.getStringValue(), 104 }); 105 } catch (error) { 106 return err(AppError.UnexpectedError.create(error)); 107 } 108 } 109}