import numeral from 'numeral'; import { customAlphabet, nanoid } from 'nanoid'; import iso6391 from 'iso-639-1'; import { get, isEqual } from './native'; import { EMAIL_REGEX, USERNAME_REGEX } from '.'; import { compareVersions, validate as validateVersion } from 'compare-versions'; export const CHARACTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; export const DEFAULT_CURRENCY_FORMAT = '0,0.00'; export const FOREX_CURRENCY_FORMAT = '0,0.00[000000]'; export type Numeral = number | string; export function getFirstLetters(str: string) { return str ? str.charAt(0) : ''; } export function formatMoneyWithoutCurrency(amount: Numeral) { return `${numeral(amount).format(DEFAULT_CURRENCY_FORMAT)}`; } export function formatForexWithCurrency(num: Numeral, currencyCode: string) { return `${numeral(toForex(num)).format( FOREX_CURRENCY_FORMAT )} ${currencyCode}`; } export function formatForexWithoutCurrency(num: Numeral) { return `${numeral(toForex(num)).format(FOREX_CURRENCY_FORMAT)}`; } export function formatForex(num: Numeral) { return `${numeral(toForex(num)).format(FOREX_CURRENCY_FORMAT)}`; } export const toDecimal = (n: Numeral, r: number) => Number(Number(n).toFixed(r)); export const toForex = (n: Numeral) => { const defaultDecimal = 4; const limits = [0.1, 0.01, 0.001, 0.0001]; for (let i = 0; i < limits.length; i += 1) { const fx = toDecimal(n, defaultDecimal + i); if (fx > limits[i]) { return fx; } } return toDecimal(n, 8); }; export function hideEmail(email: string) { let avg, splitted, part1, part2; splitted = email.split('@'); part1 = splitted[0]; avg = part1.length / 2; part1 = part1.substring(0, part1.length - avg); part2 = splitted[1]; return part1 + '...@' + part2; } export function hidePhoneNumber(phone: string) { return '******' + phone.slice(-3); } export function formatBytes(bytes: number, decimals: number = 2): string { if (bytes === 0) return '0 Bytes'; const k = 1024; const dm = decimals < 0 ? 0 : decimals; const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; } export function randomIDs() { return nanoid(); } export function randomNumIDs() { return Math.floor(Math.random() * new Date().getTime()); } export const getText = (obj: any, key: string) => { return get(obj, key); }; export const isEmptyObject = (obj: any) => { if (typeof obj !== 'object') { return false; } return Object.keys(obj).length > 0; }; export const isValuesEqual = (o1: any, o2: any) => isEqual(o1, o2); export const removeSpecialCharacters = (str: string = '') => typeof str === 'string' ? str.replace(/^a-zA-Z0-9 ]/g, '').replace(/(\r\n|\n|\r)/gm, '') : str; export const removeSpecialCharacterOnObject = (object: any) => { if (!object) { return object; } if (typeof object !== 'object') { return object; } const formattedObject = {} as any; Object.entries(object).forEach(([key, value]) => { if (typeof value === 'string') { formattedObject[key] = removeSpecialCharacters(value); } else { formattedObject[key] = value; } }); return formattedObject; }; export const truncateStr = (size: number, str = '', r = '...') => { return str.length > size ? str.slice(0, size - r.length) + r : str; }; export const defaultAvatar = (value?: { firstName?: string; lastName?: string; }) => { let text = 'Avatar'; if (value?.firstName && value?.lastName) { text = `${getFirstLetters(value.firstName)}${getFirstLetters( value.lastName )}`.toUpperCase(); } return `https://placehold.co/400x400/EEE/31343C?text=${text}`; }; export const defaultLogo = (str = '') => { return `https://placehold.co/400x400/EEE/31343C?text=${ str.charAt(0).toUpperCase() || 'Logo' }`; }; /** * Formats a name string by capitalizing the first letter of each word and lowercasing the rest. * @param {string} str - The name string to be formatted. * @returns {string} - The formatted name string. */ export const formatHumanName = (str: string): string => { if (!str) { return ''; } const nameArr = str.trim().split(/\s+/); const formattedArr = nameArr.map((name) => { return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase(); }); return formattedArr.join(' '); }; export function getFirstCharactersOfWords(sentence: string, n: number): string { return sentence .split(' ') .map((word) => word.substring(0, n)) .join(''); } type RandomType = (typeof RANDOM_TYPE)[keyof typeof RANDOM_TYPE]; const ALL_CHARACTERS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz-'; const ALPHANUMERIC = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const NUMERIC = '0123456789'; const UPPERCASE_CHARACTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; const LOWERCASE_CHARACTERS = 'abcdefghijklmnopqrstuvwxyz'; const ALL_CASE_CHARACTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; export const RANDOM_TYPE = { ALPHANUMERIC: 1, NUMERIC: 2, UPPERCASE_CHARACTERS: 3, LOWERCASE_CHARACTERS: 4, ALL_CASE_CHARACTERS: 5, ALL_CHARACTERS: 6, }; export function random(type: RandomType, length: number): string { let possible = ''; switch (type) { case RANDOM_TYPE.ALPHANUMERIC: possible = ALPHANUMERIC; break; case RANDOM_TYPE.NUMERIC: possible = NUMERIC; break; case RANDOM_TYPE.UPPERCASE_CHARACTERS: possible = UPPERCASE_CHARACTERS; break; case RANDOM_TYPE.LOWERCASE_CHARACTERS: possible = LOWERCASE_CHARACTERS; break; case RANDOM_TYPE.ALL_CASE_CHARACTERS: possible = ALL_CASE_CHARACTERS; break; case RANDOM_TYPE.ALL_CHARACTERS: possible = ALL_CHARACTERS; break; default: break; } return customAlphabet(possible, length)(); } export function randomAnyString(length: number = 16): string { return random(RANDOM_TYPE.ALL_CHARACTERS, length); } export function randomAlphaNumeric(length: number = 32): string { return random(RANDOM_TYPE.ALPHANUMERIC, length); } export function randomSerialString(): string { return customAlphabet(UPPERCASE_CHARACTERS, 16)() .match(/.{1,4}/g)! .join('-'); } export function randomOTP(length: number = 6): string { return customAlphabet(NUMERIC, length)(); } export function formatMoney(amount: number, currencyCode: string): string { return `${numeral(amount).format('0,0.00[000000]')} ${currencyCode}`; } export function formatNumber( amount: Numeral, currencyCode: string = '', formatType = '' ) { return `${numeral(amount).format(formatType)} ${currencyCode}`; } export function formatPercent(value: number): string { return `${numeral(value).format('0,0.00')} %`; } export function htmlEncode(rawStr: string): string { return rawStr.replace(/[\u00A0-\u9999<>&]/g, (i) => { return `&#${i.charCodeAt(0)};`; }); } export function firstLetter(str: string = ''): string { return removeLastComma(str.trim().split(' ')[0]); } export const isObject = (ele: any): boolean => { try { JSON.parse(ele); return true; } catch (e) { return false; } }; export const isArray = (ele: any): boolean => { try { isObject(ele); return Array.isArray(JSON.parse(ele)); } catch (e) { return false; } }; export const toTitleCaseFromCamel = (str: string): string => str .replace(/([A-Z])/g, ' $1') .replace(/(?:^|\s)\S/g, (a) => a.toUpperCase()) .trim(); export const toTitleCase = (str: string): string => str.toLowerCase().replace(/(?:^|\s)\S/g, (a) => a.toUpperCase()); export const toCamelCase = (str: string): string => str .replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => index === 0 ? word.toLowerCase() : word.toUpperCase() ) .replace(/\s+/g, ''); export const toSnakeCase = (str: string): string => str .replace(/\s+/g, '_') .replace(/([A-Z])/g, '_$1') .toLowerCase(); export const trimStr = (str: string = ''): string => { if (!str) { return str; } return str.trim(); }; export const objToString = (obj: any): string => { if (!obj) { return JSON.stringify({}); } if (typeof obj === 'string') { return obj; } if (Object.keys(obj).length === 0) { return JSON.stringify(obj); } try { const result = JSON.stringify(obj); if (result === '{}') { return `${obj}`; } return result; } catch (e) { return `${obj}`; } }; export const parseTemplate = ( rawTemplate: string = '', params: Record ): string => { let parsedTemplate = rawTemplate; Object.keys(params).forEach((key) => { parsedTemplate = parsedTemplate.replace(`{{${key}}}`, params[key]); }); return parsedTemplate; }; export const randomIdStr = (): string => nanoid(); export const normalizeObject = (obj: any): any => { if (!obj) { return obj; } const normalizedObj: any = Array.isArray(obj) ? [] : {}; Object.entries(obj).forEach(([key, value]) => { if (typeof value === 'string') { const normalizedValue = value.replace(/\s+/g, ' ').trim(); normalizedObj[key] = normalizedValue; } else if (typeof value === 'object' && value !== null) { normalizedObj[key] = normalizeObject(value); } else { normalizedObj[key] = value; } }); return normalizedObj; }; export const normalizeArrObject = (arr: any[]): any[] => { if (!Array.isArray(arr)) { return arr; } const normalizedArr: Array = []; arr.forEach((item) => { normalizedArr.push(normalizeObject(item)); }); return normalizedArr; }; export const removeLastComma = (str = '') => str.replace(/, *$/, ''); export const toUpperCase = (str: string = ''): string => str ? str.toUpperCase() : ''; export const isValidLangCode = (code = '') => iso6391.validate(code); export const isEmail = (email: string): boolean => { return EMAIL_REGEX.test(email); }; export const isUsername = (username: string): boolean => { return USERNAME_REGEX.test(username); }; export function getFirstCharactersOfEachWords( inputString: string, length?: number ): string { const inputStringArr = inputString.split(' '); let maxCharacters = inputStringArr.length; if (length && maxCharacters > length) { maxCharacters = length; } let result = ''; for (let i = 0; i < maxCharacters; i += 1) { result += inputStringArr[i].charAt(0); } return result; } export function isVersionGreaterThanOrEqual(v1: string, v2: string) { return compareVersions(v1, v2) >= 0; } export function isValidVersion(v: string) { return validateVersion(v); }