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}