A social knowledge tool for researchers built on ATProto
at development 156 lines 4.8 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 { CardTypeEnum } from '../../../domain/value-objects/CardType'; 9import { CardContent } from '../../../domain/value-objects/CardContent'; 10import { ICardPublisher } from '../../ports/ICardPublisher'; 11 12export interface UpdateNoteCardDTO { 13 cardId: string; 14 note: string; 15 curatorId: string; 16} 17 18export interface UpdateNoteCardResponseDTO { 19 cardId: string; 20} 21 22export class ValidationError extends UseCaseError { 23 constructor(message: string) { 24 super(message); 25 } 26} 27 28export class UpdateNoteCardUseCase 29 implements 30 UseCase< 31 UpdateNoteCardDTO, 32 Result< 33 UpdateNoteCardResponseDTO, 34 ValidationError | AppError.UnexpectedError 35 > 36 > 37{ 38 constructor( 39 private cardRepository: ICardRepository, 40 private cardPublisher: ICardPublisher, 41 ) {} 42 43 async execute( 44 request: UpdateNoteCardDTO, 45 ): Promise< 46 Result< 47 UpdateNoteCardResponseDTO, 48 ValidationError | AppError.UnexpectedError 49 > 50 > { 51 try { 52 // Validate and create CuratorId 53 const curatorIdResult = CuratorId.create(request.curatorId); 54 if (curatorIdResult.isErr()) { 55 return err( 56 new ValidationError( 57 `Invalid curator ID: ${curatorIdResult.error.message}`, 58 ), 59 ); 60 } 61 const curatorId = curatorIdResult.value; 62 63 // Validate and create CardId 64 const cardIdResult = CardId.createFromString(request.cardId); 65 if (cardIdResult.isErr()) { 66 return err( 67 new ValidationError(`Invalid card ID: ${cardIdResult.error.message}`), 68 ); 69 } 70 const cardId = cardIdResult.value; 71 72 // Find the card 73 const cardResult = await this.cardRepository.findById(cardId); 74 if (cardResult.isErr()) { 75 return err(AppError.UnexpectedError.create(cardResult.error)); 76 } 77 78 const card = cardResult.value; 79 if (!card) { 80 return err(new ValidationError(`Card not found: ${request.cardId}`)); 81 } 82 83 // Verify it's a note card 84 if (card.type.value !== CardTypeEnum.NOTE) { 85 return err( 86 new ValidationError('Card is not a note card and cannot be updated'), 87 ); 88 } 89 90 // Get the note content and verify authorship 91 const noteContent = card.content.noteContent; 92 if (!noteContent) { 93 return err( 94 new ValidationError('Card does not have valid note content'), 95 ); 96 } 97 98 if (!card.curatorId.equals(curatorId)) { 99 return err( 100 new ValidationError('Only the author can update this note card'), 101 ); 102 } 103 104 // Update the note content 105 const updatedNoteContentResult = noteContent.updateText(request.note); 106 if (updatedNoteContentResult.isErr()) { 107 return err(new ValidationError(updatedNoteContentResult.error.message)); 108 } 109 110 // Create new card content with updated note 111 const updatedCardContentResult = CardContent.createNoteContent( 112 request.note, 113 ); 114 if (updatedCardContentResult.isErr()) { 115 return err(new ValidationError(updatedCardContentResult.error.message)); 116 } 117 118 // Update the card content 119 const updateResult = card.updateContent(updatedCardContentResult.value); 120 if (updateResult.isErr()) { 121 return err(new ValidationError(updateResult.error.message)); 122 } 123 124 // Publish the updated card to library first 125 const publishResult = await this.cardPublisher.publishCardToLibrary( 126 card, 127 curatorId, 128 card.publishedRecordId, 129 ); 130 if (publishResult.isErr()) { 131 return err(AppError.UnexpectedError.create(publishResult.error)); 132 } 133 134 // Mark the card in library as published with the new record ID 135 const markPublishedResult = card.markCardInLibraryAsPublished( 136 curatorId, 137 publishResult.value, 138 ); 139 if (markPublishedResult.isErr()) { 140 return err(new ValidationError(markPublishedResult.error.message)); 141 } 142 143 // Save the updated card to repository 144 const saveResult = await this.cardRepository.save(card); 145 if (saveResult.isErr()) { 146 return err(AppError.UnexpectedError.create(saveResult.error)); 147 } 148 149 return ok({ 150 cardId: card.cardId.getStringValue(), 151 }); 152 } catch (error) { 153 return err(AppError.UnexpectedError.create(error)); 154 } 155 } 156}