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 ICollectionQueryRepository,
5 CollectionSortField,
6 SortOrder,
7} from '../../../domain/ICollectionQueryRepository';
8import { URL } from '../../../domain/value-objects/URL';
9
10export interface GetCollectionsForUrlQuery {
11 url: string;
12 page?: number;
13 limit?: number;
14 sortBy?: CollectionSortField;
15 sortOrder?: SortOrder;
16}
17
18export interface CollectionForUrlDTO {
19 id: string;
20 uri?: string;
21 name: string;
22 description?: string;
23 authorId: string;
24}
25
26export interface GetCollectionsForUrlResult {
27 collections: CollectionForUrlDTO[];
28 pagination: {
29 currentPage: number;
30 totalPages: number;
31 totalCount: number;
32 hasMore: boolean;
33 limit: number;
34 };
35 sorting: {
36 sortBy: CollectionSortField;
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 GetCollectionsForUrlUseCase
49 implements
50 UseCase<GetCollectionsForUrlQuery, Result<GetCollectionsForUrlResult>>
51{
52 constructor(private collectionQueryRepo: ICollectionQueryRepository) {}
53
54 async execute(
55 query: GetCollectionsForUrlQuery,
56 ): Promise<Result<GetCollectionsForUrlResult>> {
57 // Validate URL
58 const urlResult = URL.create(query.url);
59 if (urlResult.isErr()) {
60 return err(
61 new ValidationError(`Invalid URL: ${urlResult.error.message}`),
62 );
63 }
64
65 // Set defaults
66 const page = query.page || 1;
67 const limit = Math.min(query.limit || 20, 100); // Cap at 100
68 const sortBy = query.sortBy || CollectionSortField.NAME;
69 const sortOrder = query.sortOrder || SortOrder.ASC;
70
71 try {
72 // Execute query to get collections containing cards with this URL
73 const result = await this.collectionQueryRepo.getCollectionsWithUrl(
74 query.url,
75 {
76 page,
77 limit,
78 sortBy,
79 sortOrder,
80 },
81 );
82
83 return ok({
84 collections: result.items,
85 pagination: {
86 currentPage: page,
87 totalPages: Math.ceil(result.totalCount / limit),
88 totalCount: result.totalCount,
89 hasMore: result.hasMore,
90 limit,
91 },
92 sorting: {
93 sortBy,
94 sortOrder,
95 },
96 });
97 } catch (error) {
98 return err(
99 new Error(
100 `Failed to retrieve collections for URL: ${error instanceof Error ? error.message : 'Unknown error'}`,
101 ),
102 );
103 }
104 }
105}