A social knowledge tool for researchers built on ATProto
1import { ValueObject } from '../../../../shared/domain/ValueObject';
2import { CardTypeEnum } from './CardType';
3import { ok, err, Result } from '../../../../shared/core/Result';
4import { UrlMetadata } from './UrlMetadata';
5import { URL } from './URL';
6import { UrlCardContent } from './content/UrlCardContent';
7import { NoteCardContent } from './content/NoteCardContent';
8import { CuratorId } from './CuratorId';
9
10// Union type for all card content types
11type CardContentUnion = UrlCardContent | NoteCardContent;
12
13export class CardContentValidationError extends Error {
14 constructor(message: string) {
15 super(message);
16 this.name = 'CardContentValidationError';
17 }
18}
19
20export class CardContent extends ValueObject<{ content: CardContentUnion }> {
21 get type(): CardTypeEnum {
22 return this.props.content.type;
23 }
24
25 get content(): CardContentUnion {
26 return this.props.content;
27 }
28
29 // Type-safe getters
30 get urlContent(): UrlCardContent | null {
31 return this.props.content instanceof UrlCardContent
32 ? this.props.content
33 : null;
34 }
35
36 get noteContent(): NoteCardContent | null {
37 return this.props.content instanceof NoteCardContent
38 ? this.props.content
39 : null;
40 }
41
42 private constructor(content: CardContentUnion) {
43 super({ content });
44 }
45
46 // Factory methods that delegate to specific content classes
47 public static createUrlContent(
48 url: URL,
49 metadata?: UrlMetadata,
50 ): Result<CardContent, CardContentValidationError> {
51 const urlContentResult = UrlCardContent.create(url, metadata);
52 if (urlContentResult.isErr()) {
53 return err(
54 new CardContentValidationError(urlContentResult.error.message),
55 );
56 }
57 return ok(new CardContent(urlContentResult.value));
58 }
59
60 public static createNoteContent(
61 text: string,
62 ): Result<CardContent, CardContentValidationError> {
63 // Use provided curatorId or create a dummy one for backward compatibility
64 const noteContentResult = NoteCardContent.create(text);
65 if (noteContentResult.isErr()) {
66 return err(
67 new CardContentValidationError(noteContentResult.error.message),
68 );
69 }
70 return ok(new CardContent(noteContentResult.value));
71 }
72}