/** * Masks a string by replacing characters with a mask character * @param value - The string to mask * @param visibleStart - Number of characters to show at start (default: 0) * @param visibleEnd - Number of characters to show at end (default: 4) * @param maskChar - Character to use for masking (default: '*') * @returns The masked string */ const maskChar = "*"; export function mask( value: string, options?: { visibleStart?: number; visibleEnd?: number; maxLength?: number }, ): string { if (!value) return ""; const { visibleStart = 2, visibleEnd = 2, maxLength = 10 } = options ?? {}; if (isEmail(value)) { return maskEmail(value); } const totalVisible = visibleStart + visibleEnd; if (value.length <= totalVisible) { return maskChar.repeat(value.length); } const start = value.slice(0, visibleStart); const middle = value.slice(visibleStart, -visibleEnd || undefined); const end = visibleEnd ? value.slice(-visibleEnd) : ""; const maskedLength = Math.min(middle.length, maxLength); return start + maskChar.repeat(maskedLength) + end; } function maskEmail(email: string): string { const [local, domain] = email.split("@"); if (!domain || !local) return mask(email); const [subDomain, tld] = domain.split(/\.(?=[^.]+$)/); return `${mask(local)}@${mask(subDomain ?? "")}.${tld}`; } const isEmail = (value: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);