A social knowledge tool for researchers built on ATProto
1import { Result, ok, err } from '../../../../../shared/core/Result';
2import { UseCase } from '../../../../../shared/core/UseCase';
3import {
4 ICardQueryRepository,
5 CardSortField,
6 SortOrder,
7} from '../../../domain/ICardQueryRepository';
8import { URL } from '../../../domain/value-objects/URL';
9
10export interface GetNoteCardsForUrlQuery {
11 url: string;
12 page?: number;
13 limit?: number;
14 sortBy?: CardSortField;
15 sortOrder?: SortOrder;
16}
17
18export interface NoteCardForUrlDTO {
19 id: string;
20 note: string;
21 authorId: string;
22 createdAt: Date;
23 updatedAt: Date;
24}
25
26export interface GetNoteCardsForUrlResult {
27 notes: NoteCardForUrlDTO[];
28 pagination: {
29 currentPage: number;
30 totalPages: number;
31 totalCount: number;
32 hasMore: boolean;
33 limit: number;
34 };
35 sorting: {
36 sortBy: CardSortField;
37 sortOrder: SortOrder;
38 };
39}
40
41export class ValidationError extends Error {
42 constructor(message: string) {
43 super(message);
44 this.name = 'ValidationError';
45 }
46}
47
48export class GetNoteCardsForUrlUseCase
49 implements UseCase<GetNoteCardsForUrlQuery, Result<GetNoteCardsForUrlResult>>
50{
51 constructor(private cardQueryRepo: ICardQueryRepository) {}
52
53 async execute(
54 query: GetNoteCardsForUrlQuery,
55 ): Promise<Result<GetNoteCardsForUrlResult>> {
56 // Validate URL
57 const urlResult = URL.create(query.url);
58 if (urlResult.isErr()) {
59 return err(
60 new ValidationError(`Invalid URL: ${urlResult.error.message}`),
61 );
62 }
63
64 // Set defaults
65 const page = query.page || 1;
66 const limit = Math.min(query.limit || 20, 100); // Cap at 100
67 const sortBy = query.sortBy || CardSortField.UPDATED_AT;
68 const sortOrder = query.sortOrder || SortOrder.DESC;
69
70 try {
71 // Execute query to get note cards for the URL
72 const result = await this.cardQueryRepo.getNoteCardsForUrl(query.url, {
73 page,
74 limit,
75 sortBy,
76 sortOrder,
77 });
78
79 return ok({
80 notes: result.items,
81 pagination: {
82 currentPage: page,
83 totalPages: Math.ceil(result.totalCount / limit),
84 totalCount: result.totalCount,
85 hasMore: page * limit < result.totalCount,
86 limit,
87 },
88 sorting: {
89 sortBy,
90 sortOrder,
91 },
92 });
93 } catch (error) {
94 return err(
95 new Error(
96 `Failed to retrieve note cards for URL: ${error instanceof Error ? error.message : 'Unknown error'}`,
97 ),
98 );
99 }
100 }
101}