A social knowledge tool for researchers built on ATProto
at development 122 lines 3.7 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 { CardCollectionService } from '../../../domain/services/CardCollectionService'; 10 11export interface RemoveCardFromCollectionDTO { 12 cardId: string; 13 collectionIds: string[]; 14 curatorId: string; 15} 16 17export interface RemoveCardFromCollectionResponseDTO { 18 cardId: string; 19} 20 21export class ValidationError extends UseCaseError { 22 constructor(message: string) { 23 super(message); 24 } 25} 26 27export class RemoveCardFromCollectionUseCase 28 implements 29 UseCase< 30 RemoveCardFromCollectionDTO, 31 Result< 32 RemoveCardFromCollectionResponseDTO, 33 ValidationError | AppError.UnexpectedError 34 > 35 > 36{ 37 constructor( 38 private cardRepository: ICardRepository, 39 private cardCollectionService: CardCollectionService, 40 ) {} 41 42 async execute( 43 request: RemoveCardFromCollectionDTO, 44 ): Promise< 45 Result< 46 RemoveCardFromCollectionResponseDTO, 47 ValidationError | AppError.UnexpectedError 48 > 49 > { 50 try { 51 // Validate and create CuratorId 52 const curatorIdResult = CuratorId.create(request.curatorId); 53 if (curatorIdResult.isErr()) { 54 return err( 55 new ValidationError( 56 `Invalid curator ID: ${curatorIdResult.error.message}`, 57 ), 58 ); 59 } 60 const curatorId = curatorIdResult.value; 61 62 // Validate and create CardId 63 const cardIdResult = CardId.createFromString(request.cardId); 64 if (cardIdResult.isErr()) { 65 return err( 66 new ValidationError(`Invalid card ID: ${cardIdResult.error.message}`), 67 ); 68 } 69 const cardId = cardIdResult.value; 70 71 // Validate and create CollectionIds 72 const collectionIds: CollectionId[] = []; 73 for (const collectionIdStr of request.collectionIds) { 74 const collectionIdResult = 75 CollectionId.createFromString(collectionIdStr); 76 if (collectionIdResult.isErr()) { 77 return err( 78 new ValidationError( 79 `Invalid collection ID: ${collectionIdResult.error.message}`, 80 ), 81 ); 82 } 83 collectionIds.push(collectionIdResult.value); 84 } 85 86 // Find the card 87 const cardResult = await this.cardRepository.findById(cardId); 88 if (cardResult.isErr()) { 89 return err(AppError.UnexpectedError.create(cardResult.error)); 90 } 91 92 const card = cardResult.value; 93 if (!card) { 94 return err(new ValidationError(`Card not found: ${request.cardId}`)); 95 } 96 97 // Remove card from collections using domain service 98 const removeFromCollectionsResult = 99 await this.cardCollectionService.removeCardFromCollections( 100 card, 101 collectionIds, 102 curatorId, 103 ); 104 if (removeFromCollectionsResult.isErr()) { 105 if ( 106 removeFromCollectionsResult.error instanceof AppError.UnexpectedError 107 ) { 108 return err(removeFromCollectionsResult.error); 109 } 110 return err( 111 new ValidationError(removeFromCollectionsResult.error.message), 112 ); 113 } 114 115 return ok({ 116 cardId: card.cardId.getStringValue(), 117 }); 118 } catch (error) { 119 return err(AppError.UnexpectedError.create(error)); 120 } 121 } 122}