A social knowledge tool for researchers built on ATProto
1import { eq } from 'drizzle-orm';
2import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
3import {
4 IAtUriResolutionService,
5 AtUriResourceType,
6 AtUriResolutionResult,
7} from '../../domain/services/IAtUriResolutionService';
8import { CollectionId } from '../../domain/value-objects/CollectionId';
9import { collections } from '../repositories/schema/collection.sql';
10import { publishedRecords } from '../repositories/schema/publishedRecord.sql';
11import { Result, ok, err } from 'src/shared/core/Result';
12
13export class DrizzleAtUriResolutionService implements IAtUriResolutionService {
14 constructor(private db: PostgresJsDatabase) {}
15
16 async resolveAtUri(
17 atUri: string,
18 ): Promise<Result<AtUriResolutionResult | null>> {
19 try {
20 // Try collections first
21 const collectionResult = await this.db
22 .select({
23 id: collections.id,
24 })
25 .from(collections)
26 .innerJoin(
27 publishedRecords,
28 eq(collections.publishedRecordId, publishedRecords.id),
29 )
30 .where(eq(publishedRecords.uri, atUri))
31 .limit(1);
32
33 if (collectionResult.length > 0) {
34 const collectionIdResult = CollectionId.createFromString(
35 collectionResult[0]!.id,
36 );
37 if (collectionIdResult.isErr()) {
38 return err(collectionIdResult.error);
39 }
40
41 return ok({
42 type: AtUriResourceType.COLLECTION,
43 id: collectionIdResult.value,
44 });
45 }
46 return ok(null);
47 } catch (error) {
48 return err(error as Error);
49 }
50 }
51
52 async resolveCollectionId(
53 atUri: string,
54 ): Promise<Result<CollectionId | null>> {
55 const result = await this.resolveAtUri(atUri);
56
57 if (result.isErr()) {
58 return err(result.error);
59 }
60
61 if (!result.value || result.value.type !== AtUriResourceType.COLLECTION) {
62 return ok(null);
63 }
64
65 return ok(result.value.id as CollectionId);
66 }
67}