46 lines
1.2 KiB
TypeScript
46 lines
1.2 KiB
TypeScript
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
|
|
|
/**
|
|
* Value Object: MediaUrl
|
|
*
|
|
* Represents a validated media URL used for user-uploaded or generated assets.
|
|
* For now this is a conservative wrapper around strings with basic invariants:
|
|
* - non-empty
|
|
* - must start with "http", "https", "data:", or "/"
|
|
*/
|
|
export interface MediaUrlProps {
|
|
value: string;
|
|
}
|
|
|
|
export class MediaUrl implements ValueObject<MediaUrlProps> {
|
|
public readonly props: MediaUrlProps;
|
|
|
|
private constructor(value: string) {
|
|
this.props = { value };
|
|
}
|
|
|
|
static create(raw: string): MediaUrl {
|
|
const value = raw?.trim();
|
|
|
|
if (!value) {
|
|
throw new Error('Media URL cannot be empty');
|
|
}
|
|
|
|
const allowedPrefixes = ['http://', 'https://', 'data:', '/'];
|
|
const isAllowed = allowedPrefixes.some((prefix) => value.startsWith(prefix));
|
|
|
|
if (!isAllowed) {
|
|
throw new Error('Media URL must be http(s), data URI, or root-relative path');
|
|
}
|
|
|
|
return new MediaUrl(value);
|
|
}
|
|
|
|
get value(): string {
|
|
return this.props.value;
|
|
}
|
|
|
|
equals(other: ValueObject<MediaUrlProps>): boolean {
|
|
return this.props.value === other.props.value;
|
|
}
|
|
} |