@nexim/sanitizer
Version:
A collection of sanitization utilities for phone numbers and numeric inputs with TypeScript type safety.
8 lines (7 loc) • 6.59 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../src/main.ts"],
"sourcesContent": ["import { isNumber } from '@alwatr/is-number';\nimport { createLogger } from '@alwatr/logger';\nimport { packageTracer } from '@alwatr/package-tracer';\nimport { UnicodeDigits } from '@alwatr/unicode-digits';\n\n__dev_mode__: packageTracer.add(__package_name__, __package_version__);\n\nconst logger = createLogger(__package_name__);\nconst unicodeDigits = new UnicodeDigits('en');\n\n/**\n * Sanitizes a number to English format. If input is already a number, returns it as-is.\n * If input is a string, converts Unicode digits to English and validates it's a valid number.\n *\n * @param number - The input to sanitize (number or string)\n * @returns The sanitized number or string, or null if invalid\n *\n * @example\n * ```ts\n * sanitizeNumberToEnglish(123); // returns 123\n * sanitizeNumberToEnglish('۱۲۳'); // returns '123'\n * sanitizeNumberToEnglish('abc'); // returns null\n * ```\n */\nexport function sanitizeNumberToEnglish(number: number): number;\nexport function sanitizeNumberToEnglish<T>(number: T): number | null;\nexport function sanitizeNumberToEnglish(number: unknown): number | null {\n // logger.logMethodArgs?.('sanitizeNumberToEnglish', { number });\n\n if (typeof number === 'number') {\n return number;\n }\n\n if (typeof number === 'string') {\n let str = number.trim();\n if (str === '') {\n logger.incident?.('sanitizeNumberToEnglish', 'empty_string', { number });\n return null;\n }\n\n str = unicodeDigits.translate(str);\n if (!isNumber(str)) {\n logger.incident?.('sanitizeNumberToEnglish', 'not_a_number', { number });\n return null;\n }\n\n return +str;\n }\n\n logger.incident?.('sanitizeNumberToEnglish', 'invalid_input', { number });\n return null;\n}\n\n/**\n * Sanitizes a number to English string format, preserving leading zeros.\n * If input is a string, converts Unicode digits to English and validates it's a valid number.\n * If input is already a number, converts it to string.\n *\n * @param number - The input to sanitize (number or string)\n * @returns The sanitized number as string, or null if invalid\n *\n * @example\n * ```ts\n * sanitizeNumberStringToEnglish(123); // returns '123'\n * sanitizeNumberStringToEnglish('۰۱۲۳'); // returns '0123' (preserves leading zero)\n * sanitizeNumberStringToEnglish('abc'); // returns null\n * ```\n */\nexport function sanitizeNumberStringToEnglish<T>(number: T): string | null;\nexport function sanitizeNumberStringToEnglish(number: unknown): string | null {\n // logger.logMethodArgs?.('sanitizeNumberStringToEnglish', { number });\n\n if (typeof number === 'number') {\n return String(number);\n }\n\n if (typeof number === 'string') {\n let str = number.trim();\n if (str === '') {\n logger.incident?.('sanitizeNumberStringToEnglish', 'empty_string', { number });\n return null;\n }\n\n str = unicodeDigits.translate(str);\n if (!isNumber(str)) {\n logger.incident?.('sanitizeNumberStringToEnglish', 'not_a_number', { number });\n return null;\n }\n\n return str; // Return string to preserve leading zeros\n }\n\n logger.incident?.('sanitizeNumberStringToEnglish', 'invalid_input', { number });\n return null;\n}\n\n/**\n * Sanitizes a phone number by converting Unicode digits, removing special characters,\n * and standardizing the format with country code.\n *\n * @param input - The phone number input to sanitize\n * @param countryCode - The country code to apply (default: '98' for Iran)\n * @returns The sanitized phone number as a number, or null if invalid\n *\n * @example\n * ```ts\n * sanitizePhoneNumber('09123456789'); // returns 989123456789\n * sanitizePhoneNumber('+98 912 345 6789'); // returns 989123456789\n * sanitizePhoneNumber('۰۹۱۲۳۴۵۶۷۸۹'); // returns 989123456789\n * sanitizePhoneNumber('invalid'); // returns null\n * ```\n */\nexport function sanitizePhoneNumber(input: unknown, countryCode = '98'): number | null {\n // logger.logMethodArgs?.('sanitizePhoneNumber', { input, countryCode });\n\n if (input == null) {\n logger.incident?.('sanitizePhoneNumber', 'undefined_or_null_input', { input });\n return null;\n }\n\n const inputStr = typeof input === 'string' ? input.trim() : String(input);\n\n if (inputStr === '') {\n logger.incident?.('sanitizePhoneNumber', 'empty_input_string', { input });\n return null;\n }\n\n const englishDigits = unicodeDigits.translate(inputStr);\n const withoutSpecialChars = englishDigits.replace(/[ )(-]+/g, '');\n const cleanNumber = withoutSpecialChars.replace(new RegExp(`^(\\\\+${countryCode}|${countryCode}|^0)`), '');\n const fullNumber = countryCode + cleanNumber;\n\n if (fullNumber.length !== countryCode.length + 10 || !isNumber(fullNumber)) {\n logger.incident?.('sanitizePhoneNumber', 'invalid_full_number', { fullNumber });\n return null;\n }\n\n return +fullNumber;\n}\n"],
"mappings": ";;;AAAA,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAE9B,aAAc,eAAc,IAAI,oBAAkB,OAAmB;AAErE,IAAM,SAAS,aAAa,kBAAgB;AAC5C,IAAM,gBAAgB,IAAI,cAAc,IAAI;AAkBrC,SAAS,wBAAwB,QAAgC;AAGtE,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,WAAW,UAAU;AAC9B,QAAI,MAAM,OAAO,KAAK;AACtB,QAAI,QAAQ,IAAI;AACd,aAAO,WAAW,2BAA2B,gBAAgB,EAAE,OAAO,CAAC;AACvE,aAAO;AAAA,IACT;AAEA,UAAM,cAAc,UAAU,GAAG;AACjC,QAAI,CAAC,SAAS,GAAG,GAAG;AAClB,aAAO,WAAW,2BAA2B,gBAAgB,EAAE,OAAO,CAAC;AACvE,aAAO;AAAA,IACT;AAEA,WAAO,CAAC;AAAA,EACV;AAEA,SAAO,WAAW,2BAA2B,iBAAiB,EAAE,OAAO,CAAC;AACxE,SAAO;AACT;AAkBO,SAAS,8BAA8B,QAAgC;AAG5E,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO,OAAO,MAAM;AAAA,EACtB;AAEA,MAAI,OAAO,WAAW,UAAU;AAC9B,QAAI,MAAM,OAAO,KAAK;AACtB,QAAI,QAAQ,IAAI;AACd,aAAO,WAAW,iCAAiC,gBAAgB,EAAE,OAAO,CAAC;AAC7E,aAAO;AAAA,IACT;AAEA,UAAM,cAAc,UAAU,GAAG;AACjC,QAAI,CAAC,SAAS,GAAG,GAAG;AAClB,aAAO,WAAW,iCAAiC,gBAAgB,EAAE,OAAO,CAAC;AAC7E,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAEA,SAAO,WAAW,iCAAiC,iBAAiB,EAAE,OAAO,CAAC;AAC9E,SAAO;AACT;AAkBO,SAAS,oBAAoB,OAAgB,cAAc,MAAqB;AAGrF,MAAI,SAAS,MAAM;AACjB,WAAO,WAAW,uBAAuB,2BAA2B,EAAE,MAAM,CAAC;AAC7E,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,OAAO,UAAU,WAAW,MAAM,KAAK,IAAI,OAAO,KAAK;AAExE,MAAI,aAAa,IAAI;AACnB,WAAO,WAAW,uBAAuB,sBAAsB,EAAE,MAAM,CAAC;AACxE,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,cAAc,UAAU,QAAQ;AACtD,QAAM,sBAAsB,cAAc,QAAQ,YAAY,EAAE;AAChE,QAAM,cAAc,oBAAoB,QAAQ,IAAI,OAAO,QAAQ,WAAW,IAAI,WAAW,MAAM,GAAG,EAAE;AACxG,QAAM,aAAa,cAAc;AAEjC,MAAI,WAAW,WAAW,YAAY,SAAS,MAAM,CAAC,SAAS,UAAU,GAAG;AAC1E,WAAO,WAAW,uBAAuB,uBAAuB,EAAE,WAAW,CAAC;AAC9E,WAAO;AAAA,EACT;AAEA,SAAO,CAAC;AACV;",
"names": []
}