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 / commands / RemoveCardFromCollectionUseCase.ts
4.7 kB 141 lines
1import { Result, ok, err } from '../../../../../shared/core/Result'; 2import { BaseUseCase } 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'; 10import { AuthenticationError } from '../../../../../shared/core/AuthenticationError'; 11import { IEventPublisher } from '../../../../../shared/application/events/IEventPublisher'; 12 13export interface RemoveCardFromCollectionDTO { 14 cardId: string; 15 collectionIds: string[]; 16 curatorId: string; 17} 18 19export interface RemoveCardFromCollectionResponseDTO { 20 cardId: string; 21} 22 23export class ValidationError extends UseCaseError { 24 constructor(message: string) { 25 super(message); 26 } 27} 28 29export class RemoveCardFromCollectionUseCase extends BaseUseCase< 30 RemoveCardFromCollectionDTO, 31 Result< 32 RemoveCardFromCollectionResponseDTO, 33 ValidationError | AuthenticationError | AppError.UnexpectedError 34 > 35> { 36 constructor( 37 private cardRepository: ICardRepository, 38 private cardCollectionService: CardCollectionService, 39 eventPublisher: IEventPublisher, 40 ) { 41 super(eventPublisher); 42 } 43 44 async execute( 45 request: RemoveCardFromCollectionDTO, 46 ): Promise< 47 Result< 48 RemoveCardFromCollectionResponseDTO, 49 ValidationError | AuthenticationError | AppError.UnexpectedError 50 > 51 > { 52 try { 53 // Validate and create CuratorId 54 const curatorIdResult = CuratorId.create(request.curatorId); 55 if (curatorIdResult.isErr()) { 56 return err( 57 new ValidationError( 58 `Invalid curator ID: ${curatorIdResult.error.message}`, 59 ), 60 ); 61 } 62 const curatorId = curatorIdResult.value; 63 64 // Validate and create CardId 65 const cardIdResult = CardId.createFromString(request.cardId); 66 if (cardIdResult.isErr()) { 67 return err( 68 new ValidationError(`Invalid card ID: ${cardIdResult.error.message}`), 69 ); 70 } 71 const cardId = cardIdResult.value; 72 73 // Validate and create CollectionIds 74 const collectionIds: CollectionId[] = []; 75 for (const collectionIdStr of request.collectionIds) { 76 const collectionIdResult = 77 CollectionId.createFromString(collectionIdStr); 78 if (collectionIdResult.isErr()) { 79 return err( 80 new ValidationError( 81 `Invalid collection ID: ${collectionIdResult.error.message}`, 82 ), 83 ); 84 } 85 collectionIds.push(collectionIdResult.value); 86 } 87 88 // Find the card 89 const cardResult = await this.cardRepository.findById(cardId); 90 if (cardResult.isErr()) { 91 return err(AppError.UnexpectedError.create(cardResult.error)); 92 } 93 94 const card = cardResult.value; 95 if (!card) { 96 return err(new ValidationError(`Card not found: ${request.cardId}`)); 97 } 98 99 // Remove card from collections using domain service 100 const removeFromCollectionsResult = 101 await this.cardCollectionService.removeCardFromCollections( 102 card, 103 collectionIds, 104 curatorId, 105 ); 106 if (removeFromCollectionsResult.isErr()) { 107 // Propagate authentication errors 108 if (removeFromCollectionsResult.error instanceof AuthenticationError) { 109 return err(removeFromCollectionsResult.error); 110 } 111 if ( 112 removeFromCollectionsResult.error instanceof AppError.UnexpectedError 113 ) { 114 return err(removeFromCollectionsResult.error); 115 } 116 return err( 117 new ValidationError(removeFromCollectionsResult.error.message), 118 ); 119 } 120 121 // Publish events for each updated collection 122 const updatedCollections = removeFromCollectionsResult.value; 123 for (const collection of updatedCollections) { 124 const publishResult = await this.publishEventsForAggregate(collection); 125 if (publishResult.isErr()) { 126 console.error( 127 'Failed to publish events for collection:', 128 publishResult.error, 129 ); 130 // Don't fail the operation if event publishing fails 131 } 132 } 133 134 return ok({ 135 cardId: card.cardId.getStringValue(), 136 }); 137 } catch (error) { 138 return err(AppError.UnexpectedError.create(error)); 139 } 140 } 141}