A social knowledge tool for researchers built on ATProto
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 { IEventPublisher } from '../../../../../shared/application/events/IEventPublisher';
6import { ICardRepository } from '../../../domain/ICardRepository';
7import { ICollectionQueryRepository } from '../../../domain/ICollectionQueryRepository';
8import { CuratorId } from '../../../domain/value-objects/CuratorId';
9import { URL } from '../../../domain/value-objects/URL';
10
11export interface GetUrlStatusForMyLibraryQuery {
12 url: string;
13 curatorId: string;
14}
15
16export interface CollectionInfo {
17 id: string;
18 uri?: string;
19 name: string;
20 description?: string;
21}
22
23export interface GetUrlStatusForMyLibraryResult {
24 cardId?: string;
25 collections?: CollectionInfo[];
26}
27
28export class ValidationError extends UseCaseError {
29 constructor(message: string) {
30 super(message);
31 }
32}
33
34export class GetUrlStatusForMyLibraryUseCase extends BaseUseCase<
35 GetUrlStatusForMyLibraryQuery,
36 Result<
37 GetUrlStatusForMyLibraryResult,
38 ValidationError | AppError.UnexpectedError
39 >
40> {
41 constructor(
42 private cardRepository: ICardRepository,
43 private collectionQueryRepository: ICollectionQueryRepository,
44 eventPublisher: IEventPublisher,
45 ) {
46 super(eventPublisher);
47 }
48
49 async execute(
50 query: GetUrlStatusForMyLibraryQuery,
51 ): Promise<
52 Result<
53 GetUrlStatusForMyLibraryResult,
54 ValidationError | AppError.UnexpectedError
55 >
56 > {
57 try {
58 // Validate and create CuratorId
59 const curatorIdResult = CuratorId.create(query.curatorId);
60 if (curatorIdResult.isErr()) {
61 return err(
62 new ValidationError(
63 `Invalid curator ID: ${curatorIdResult.error.message}`,
64 ),
65 );
66 }
67 const curatorId = curatorIdResult.value;
68
69 // Validate URL
70 const urlResult = URL.create(query.url);
71 if (urlResult.isErr()) {
72 return err(
73 new ValidationError(`Invalid URL: ${urlResult.error.message}`),
74 );
75 }
76 const url = urlResult.value;
77
78 // Check if user has a URL card with this URL
79 const existingCardResult =
80 await this.cardRepository.findUsersUrlCardByUrl(url, curatorId);
81 if (existingCardResult.isErr()) {
82 return err(AppError.UnexpectedError.create(existingCardResult.error));
83 }
84
85 const card = existingCardResult.value;
86 const result: GetUrlStatusForMyLibraryResult = {};
87
88 if (card) {
89 result.cardId = card.cardId.getStringValue();
90
91 // Get collections containing this card for the user
92 try {
93 const collections =
94 await this.collectionQueryRepository.getCollectionsContainingCardForUser(
95 card.cardId.getStringValue(),
96 curatorId.value,
97 );
98
99 result.collections = collections.map((collection) => ({
100 id: collection.id,
101 uri: collection.uri,
102 name: collection.name,
103 description: collection.description,
104 }));
105 } catch (error) {
106 return err(AppError.UnexpectedError.create(error));
107 }
108 }
109
110 return ok(result);
111 } catch (error) {
112 return err(AppError.UnexpectedError.create(error));
113 }
114 }
115}