A social knowledge tool for researchers built on ATProto
1import { ValueObject } from '../../../../shared/domain/ValueObject';
2import { Result, ok, err } from '../../../../shared/core/Result';
3
4export class InvalidURLError extends Error {
5 constructor(message: string) {
6 super(message);
7 this.name = 'InvalidURLError';
8 }
9}
10
11interface URLProps {
12 value: string;
13}
14
15export class URL extends ValueObject<URLProps> {
16 get value(): string {
17 return this.props.value;
18 }
19
20 private constructor(props: URLProps) {
21 super(props);
22 }
23
24 public static create(url: string): Result<URL, InvalidURLError> {
25 if (!url || url.trim().length === 0) {
26 return err(new InvalidURLError('URL cannot be empty'));
27 }
28
29 const trimmedUrl = url.trim();
30
31 try {
32 // Validate URL format using the global URL constructor
33 new globalThis.URL(trimmedUrl);
34 return ok(new URL({ value: trimmedUrl }));
35 } catch (error) {
36 return err(new InvalidURLError('Invalid URL format'));
37 }
38 }
39
40 public toString(): string {
41 return this.value;
42 }
43}