/** * Verification Code Domain Entity * Pure domain object without infrastructure dependencies */ export class VerificationCodeEntity { readonly id: string; readonly phone: string; readonly code: string; readonly expiresAt: Date; isUsed: boolean; readonly createdAt: Date; private constructor(props: { id: string; phone: string; code: string; expiresAt: Date; isUsed: boolean; createdAt: Date; }) { this.id = props.id; this.phone = props.phone; this.code = props.code; this.expiresAt = props.expiresAt; this.isUsed = props.isUsed; this.createdAt = props.createdAt; } /** * Create a new verification code * Code expires in 5 minutes by default */ static create(phone: string, expirationMinutes: number = 5): VerificationCodeEntity { const now = new Date(); return new VerificationCodeEntity({ id: crypto.randomUUID(), phone, code: VerificationCodeEntity.generateCode(), expiresAt: new Date(now.getTime() + expirationMinutes * 60 * 1000), isUsed: false, createdAt: now, }); } /** * Reconstruct from persistence */ static fromPersistence(props: { id: string; phone: string; code: string; expiresAt: Date; isUsed: boolean; createdAt: Date; }): VerificationCodeEntity { return new VerificationCodeEntity(props); } /** * Generate 6-digit verification code */ private static generateCode(): string { return Math.floor(100000 + Math.random() * 900000).toString(); } /** * Check if the code is valid (not used and not expired) */ isValid(): boolean { return !this.isUsed && this.expiresAt > new Date(); } /** * Mark the code as used */ markAsUsed(): void { this.isUsed = true; } /** * Check if this code matches the provided code */ matches(code: string): boolean { return this.code === code; } }