This repository has no description
4.1 kB
145 lines
1import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
2import { eq, and, sql } from 'drizzle-orm';
3import { IFollowsRepository } from '../../domain/repositories/IFollowsRepository';
4import { Follow } from '../../domain/Follow';
5import { DID } from '../../domain/value-objects/DID';
6import {
7 FollowTargetType,
8 FollowTargetTypeEnum,
9} from '../../domain/value-objects/FollowTargetType';
10import { follows } from './schema/follows.sql';
11import { UniqueEntityID } from 'src/shared/domain/UniqueEntityID';
12import { err, ok, Result } from 'src/shared/core/Result';
13
14export class DrizzleFollowsRepository implements IFollowsRepository {
15 constructor(private db: PostgresJsDatabase) {}
16
17 async getFollowers(
18 targetId: string,
19 targetType: FollowTargetType,
20 ): Promise<Result<Follow[]>> {
21 try {
22 const results = await this.db
23 .select()
24 .from(follows)
25 .where(
26 and(
27 eq(follows.targetId, targetId),
28 eq(follows.targetType, targetType.value),
29 ),
30 );
31
32 const followEntities: Follow[] = [];
33
34 for (const row of results) {
35 const followerDIDResult = DID.create(row.followerId);
36 if (followerDIDResult.isErr()) {
37 console.error(
38 `Invalid follower DID: ${row.followerId}`,
39 followerDIDResult.error,
40 );
41 continue;
42 }
43
44 const targetTypeResult = FollowTargetType.create(
45 row.targetType as FollowTargetTypeEnum,
46 );
47 if (targetTypeResult.isErr()) {
48 console.error(
49 `Invalid target type: ${row.targetType}`,
50 targetTypeResult.error,
51 );
52 continue;
53 }
54
55 const followResult = Follow.create(
56 {
57 followerId: followerDIDResult.value,
58 targetId: row.targetId,
59 targetType: targetTypeResult.value,
60 createdAt: row.createdAt,
61 },
62 new UniqueEntityID(
63 `${row.followerId}:${row.targetId}:${row.targetType}`,
64 ),
65 );
66
67 if (followResult.isOk()) {
68 followEntities.push(followResult.value);
69 } else {
70 console.error('Failed to create Follow entity:', followResult.error);
71 }
72 }
73
74 return ok(followEntities);
75 } catch (error: any) {
76 return err(error);
77 }
78 }
79
80 async getFollowersOfCollections(
81 collectionIds: string[],
82 ): Promise<Result<Follow[]>> {
83 try {
84 if (collectionIds.length === 0) {
85 return ok([]);
86 }
87
88 const results = await this.db
89 .select()
90 .from(follows)
91 .where(
92 and(
93 sql`${follows.targetId} = ANY(${collectionIds}::text[])`,
94 eq(follows.targetType, FollowTargetTypeEnum.COLLECTION),
95 ),
96 );
97
98 const followEntities: Follow[] = [];
99
100 for (const row of results) {
101 const followerDIDResult = DID.create(row.followerId);
102 if (followerDIDResult.isErr()) {
103 console.error(
104 `Invalid follower DID: ${row.followerId}`,
105 followerDIDResult.error,
106 );
107 continue;
108 }
109
110 const targetTypeResult = FollowTargetType.create(
111 row.targetType as FollowTargetTypeEnum,
112 );
113 if (targetTypeResult.isErr()) {
114 console.error(
115 `Invalid target type: ${row.targetType}`,
116 targetTypeResult.error,
117 );
118 continue;
119 }
120
121 const followResult = Follow.create(
122 {
123 followerId: followerDIDResult.value,
124 targetId: row.targetId,
125 targetType: targetTypeResult.value,
126 createdAt: row.createdAt,
127 },
128 new UniqueEntityID(
129 `${row.followerId}:${row.targetId}:${row.targetType}`,
130 ),
131 );
132
133 if (followResult.isOk()) {
134 followEntities.push(followResult.value);
135 } else {
136 console.error('Failed to create Follow entity:', followResult.error);
137 }
138 }
139
140 return ok(followEntities);
141 } catch (error: any) {
142 return err(error);
143 }
144 }
145}