@alfalab/utils
Advanced tools
Comparing version 1.17.0-rc.1 to 1.17.1
@@ -1,556 +0,19 @@ | ||
import { currency, countries } from '@alfalab/data'; | ||
import isPlainObject from 'lodash/isPlainObject'; | ||
import transform from 'lodash/transform'; | ||
/** | ||
* Возвращает последние цифры номера счёта в формате `··XXXX` | ||
* @param accountNumber - Номер счёта. | ||
* @param additionalParams - Дополнительные параметры. | ||
* @param additionalParams.countOfResultDigits - Количество оставшихся цифр. По умолчанию 4. | ||
*/ | ||
function cropAccountNumber(accountNumber, { countOfResultDigits = 4 } = {}) { | ||
if (!accountNumber) { | ||
return accountNumber; | ||
} | ||
return `\u00B7\u00B7${accountNumber.slice(-countOfResultDigits)}`; | ||
} | ||
const ACCOUNT_SPLIT_REGEX = /^(\d{5})(\d{3})(\d)(\d{4})(\d{7})$/; | ||
const ACCOUNT_FORMAT = '$1 $2 $3 $4 $5'; | ||
/** | ||
* Возвращает отформатированное значение счёта. | ||
* Разделяет пробелами число на группы. | ||
* XXXXX XXX X XXXX XXXXXXX | ||
* | ||
* @param value Номер счёта. | ||
*/ | ||
function formatAccount(value) { | ||
if (!value) { | ||
return ''; | ||
} | ||
return value.replace(ACCOUNT_SPLIT_REGEX, ACCOUNT_FORMAT); | ||
} | ||
/** | ||
* Возвращает знак валюты по ISO коду. | ||
* | ||
* @param currencyCode Код валюты. | ||
*/ | ||
const getCurrencySymbol = (currencyCode) => currency.CURRENCY_SYMBOLS[currencyCode]; | ||
/** | ||
* Дробит мажорную часть суммы на части по указанному символу. | ||
* | ||
* @param amount Сумма для разбивки на части | ||
* @param partSize Размер частей суммы | ||
* @param splitter Символ, разбивающий части суммы | ||
* @param splitFrom Длина суммы, начиная с которой необходимо осуществлять разбивку. По-умолчанию длина | ||
* равняется пяти по требованию гайдлайнов: https://design.alfabank.ru/patterns/amount. Пример: 2900 - не разбивается, | ||
* 29 000 - разбивается. | ||
*/ | ||
const splitAmount = (amount, partSize = 3, splitter, splitFrom = 5) => { | ||
const splittingRegExp = `\\B(?=(\\d{${partSize}})+(?!\\d))`; | ||
// Если длина суммы меньше требуемой, не форматируем сумму | ||
if (amount.length < splitFrom) { | ||
return amount; | ||
} | ||
return amount.replace(new RegExp(splittingRegExp, 'g'), splitter); | ||
}; | ||
const AMOUNT_MAJOR_PART_SIZE = 3; | ||
const AMOUNT_SPLIT_CODE_FROM = 4; | ||
// Reference: https://jkorpela.fi/dashes.html | ||
const NEGATIVE_SYMBOLS = { | ||
/** Unicode: U+2212. An arithmetic operator */ | ||
'minus-sign': '−', | ||
/** Unicode: U+002D. The Ascii hyphen. Used in inputs */ | ||
'hyphen-minus': '-', | ||
}; | ||
const THINSP = String.fromCharCode(8201); //   | ||
const MMSP = String.fromCharCode(8287); // средний математический пробел | ||
const AMOUNT_MAJOR_MINOR_PARTS_SEPARATOR = ','; | ||
/** | ||
* Возвращает код для валюты взависимости от формата | ||
*/ | ||
const getCurrencyCodeWithFormat = (currency, codeFormat) => { | ||
if (!currency) { | ||
return ''; | ||
} | ||
return codeFormat === 'symbolic' | ||
? getCurrencySymbol(currency) | ||
: currency; | ||
}; | ||
/** | ||
* Возвращает разделитель для кода валюты взависимости от формата | ||
*/ | ||
const getCurrencySeparator = (codeFormat) => (codeFormat === 'symbolic' ? THINSP : MMSP); | ||
/** | ||
* Форматирует значение вместе с кодом валюты | ||
*/ | ||
const formatWithCurrency = (value, currencyCode, separator) => [value, currencyCode].filter(Boolean).join(separator); | ||
/** | ||
* Форматирует значение суммы | ||
* согласно гайдлайну https://design.alfabank.ru/patterns/amount | ||
*/ | ||
const formatAmount = ({ value, currency, minority, view, negativeSymbol = 'minus-sign', codeFormat = 'symbolic', }) => { | ||
const currencySymbol = getCurrencyCodeWithFormat(currency, codeFormat); | ||
const currencySeparator = getCurrencySeparator(codeFormat); | ||
if (value === null) { | ||
return { | ||
majorPart: '', | ||
minorPart: '', | ||
formatted: '', | ||
currencySymbol, | ||
currencySeparator, | ||
formattedWithCurrency: formatWithCurrency(value, currencySymbol, currencySeparator), | ||
}; | ||
} | ||
// eslint-disable-next-line no-param-reassign | ||
minority = minority === 0 ? 1 : minority; // because Math.log(0) => -Infinity | ||
const fractionDigits = Math.log(minority) * Math.LOG10E; | ||
const valueAbsStr = (Math.abs(value) / minority).toFixed(fractionDigits); | ||
const [majorPart] = valueAbsStr.split('.'); | ||
let [, minorPart] = valueAbsStr.split('.'); | ||
if (view === 'default' && value % minority === 0) { | ||
minorPart = ''; | ||
} | ||
const majorPartSplitted = splitAmount(majorPart, AMOUNT_MAJOR_PART_SIZE, MMSP, AMOUNT_SPLIT_CODE_FROM); | ||
const majorPartFormatted = value < 0 ? NEGATIVE_SYMBOLS[negativeSymbol] + majorPartSplitted : majorPartSplitted; | ||
const formattedValueStr = minorPart | ||
? majorPartFormatted + AMOUNT_MAJOR_MINOR_PARTS_SEPARATOR + minorPart | ||
: majorPartFormatted; | ||
return { | ||
majorPart: majorPartFormatted, | ||
minorPart, | ||
currencySymbol, | ||
formatted: formattedValueStr, | ||
currencySeparator, | ||
formattedWithCurrency: formatWithCurrency(formattedValueStr, currencySymbol, currencySeparator), | ||
}; | ||
}; | ||
var Locale; | ||
(function (Locale) { | ||
Locale["RU"] = "ru"; | ||
Locale["EN"] = "en"; | ||
})(Locale || (Locale = {})); | ||
const UNITS_COUNT = 4; | ||
const SIZE_UNITS = { | ||
[Locale.RU]: ['Б', 'КБ', 'МБ', 'ГБ'], | ||
[Locale.EN]: ['B', 'KB', 'MB', 'GB'], | ||
}; | ||
const humanizeNumberPartOfFileSize = (value, factor) => { | ||
const maxFactor = UNITS_COUNT - 1; | ||
if (value > 99 && factor === maxFactor) | ||
return '99+'; | ||
return `${Number(value.toFixed(2))}`; | ||
}; | ||
const parseFileSize = (fileSize) => { | ||
const parsedFileSize = Number(fileSize); | ||
if (Number.isNaN(parsedFileSize)) | ||
return 0; | ||
return parsedFileSize; | ||
}; | ||
/** | ||
* Возвращает отформатированное значение размера файла. | ||
* Разделяет пробелом число и единицу измерения. | ||
* | ||
* Примеры: | ||
* 976.56 KB, | ||
* 1000 B, | ||
* 93.13 GB, | ||
* 99+ GB - Если файл превышает 99 GB, | ||
* 0 B - Если приходит строка, которую невозможно привести к числу | ||
*/ | ||
const formatFileSize = (fileSize, locale = Locale.EN) => { | ||
const maxFactor = UNITS_COUNT - 1; | ||
let humanSize = parseFileSize(fileSize); | ||
let factor = 0; | ||
while (humanSize >= 1024 && factor < maxFactor) { | ||
humanSize /= 1024; | ||
factor += 1; | ||
} | ||
return `${humanizeNumberPartOfFileSize(humanSize, factor)} ${SIZE_UNITS[locale][factor]}`; | ||
}; | ||
/** | ||
* Удаляет форматирование номера телефона | ||
* @param phone Отформатированный номер телефона с кодом страны | ||
* @returns Номер телефона в формате 71112223344/88002223344 | ||
*/ | ||
const getRawPhoneNumber = (phone) => phone.replace(/\D+/g, ''); | ||
/** | ||
* Форматирует номер телефона | ||
* @param phone Номер телефона в любом формате с кодом страны | ||
* @returns Номер телефона в формате +7 111 222-33-44/8 800 222-33-44 | ||
*/ | ||
const formatPhoneNumber = (phone) => { | ||
const rawPhone = getRawPhoneNumber(phone); | ||
const formattedPhone = rawPhone.replace(/(\d)(\d{3})(\d{3})(\d{2})(\d{2})/, `$1 $2 $3-$4-$5`); | ||
return formattedPhone[0] === '7' ? '+'.concat(formattedPhone) : formattedPhone; | ||
}; | ||
/** | ||
* Маскирует номер телефона. | ||
* Номер должен быть уже отформатирован. | ||
* TODO: сделать, чтобы number можно было принимать любой (отформатированный/неотформатированный) | ||
* | ||
* @param {String} number Отформатированный номер телефона | ||
* @returns {String} | ||
*/ | ||
function maskPhoneNumber(number) { | ||
const first = number.substr(0, 2); | ||
const last = number.substr(number.length - 5, number.length); | ||
return `${first} ··· ··· ${last}`; | ||
} | ||
const phoneNumber = { | ||
format: formatPhoneNumber, | ||
getRaw: getRawPhoneNumber, | ||
mask: maskPhoneNumber, | ||
}; | ||
function getAllCurrencyCodes() { | ||
return Object.keys(currency.CURRENCY_SYMBOLS); | ||
} | ||
const formatCountry = ([_, name, iso2, dialCode, priority, areaCodes]) => ({ | ||
name, | ||
iso2, | ||
dialCode, | ||
priority, | ||
areaCodes: areaCodes !== null && areaCodes !== void 0 ? areaCodes : null, | ||
}); | ||
const getCountries = () => countries.map(formatCountry).sort((a, b) => a.name.localeCompare(b.name)); | ||
const getCountriesHash = () => countries.reduce((acc, country) => { | ||
const iso2 = country[2]; | ||
acc[iso2] = formatCountry(country); | ||
return acc; | ||
}, {}); | ||
/** | ||
* Возвращает `true`, если элемент переполнен | ||
* @param element HTML-элемент | ||
*/ | ||
function isOverflown(element) { | ||
return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth; | ||
} | ||
/** | ||
* Возвращает слово в необходимой форме, зависимой от значения `count`. | ||
* | ||
* @example | ||
* pluralize(1, 'день', 'дня', 'дней'); // день | ||
* pluralize(2, 'день', 'дня', 'дней'); // дня | ||
* pluralize(5, 'день', 'дня', 'дней'); // дней | ||
* | ||
* @param {number} count - Число. | ||
* @param {string} nominative - Слово в именительном падеже единственного числа | ||
* @param {string} genitive - Слово в родительном падеже единственного числа | ||
* @param {string} plural - Слово во множественном числе | ||
* | ||
* @returns {string} | ||
*/ | ||
const pluralize = (count, nominative, genitive, plural) => { | ||
const normalizedNumber = count % 100; | ||
if (normalizedNumber >= 11 && normalizedNumber <= 19) { | ||
return plural; | ||
} | ||
const remainder = normalizedNumber % 10; | ||
switch (remainder) { | ||
case 1: | ||
return nominative; | ||
case 2: | ||
case 3: | ||
case 4: | ||
return genitive; | ||
default: | ||
return plural; | ||
} | ||
}; | ||
/** | ||
* Приводит секунды к формату `hh:mm:ss` и возвращает объект с ними. | ||
*/ | ||
function secondsToTime(seconds) { | ||
const h = Math.floor(seconds / 60 / 60); | ||
const m = Math.floor(seconds / 60) % 60; | ||
const s = seconds - h * 3600 - m * 60; | ||
return { | ||
hours: `${numPad('00', h)}`, | ||
minutes: `${numPad('00', m)}`, | ||
seconds: `${numPad('00', s)}`, | ||
}; | ||
} | ||
function numPad(pad, num) { | ||
return typeof num === 'undefined' ? pad : (pad + num).slice(-pad.length); | ||
} | ||
/** | ||
* Возвращает true/false при проверке номера валидности карты по алгоритму Луна | ||
*/ | ||
const isValidCardNumber = (setValue) => { | ||
let ch = 0; | ||
const num = setValue.replace(/\D/g, ''); | ||
if (num === '') | ||
return false; | ||
for (let i = 0; i < num.length; i++) { | ||
let n = parseInt(num[i], 10); | ||
ch += 0 === i % 2 && (n *= 2) > 9 ? n - 9 : n; | ||
} | ||
return ch % 10 === 0; | ||
}; | ||
const EMAIL_PARTS_SEPARATOR = '@'; | ||
const DOMAIN_PARTS_SEPARATOR = '.'; | ||
const MAX_ACCOUNT_LENGTH = 64; | ||
const MAX_ADDRES_LENGTH = 255; | ||
const MAX_DOMAIN_LENGTH = 63; | ||
const EMAIL_REGEX = /^[-!#$%&'*+\/0-9=?A-Z^_a-z`{|}~](\.?[-!#$%&'*+\/0-9=?A-Z^_a-z`{|}~])*@[a-zA-Z0-9](-*\.?[a-zA-Z0-9])*\.[a-zA-Z](-?[a-zA-Z0-9])+$/; | ||
/** | ||
* Возвращает true для валидного email, иначе false | ||
* | ||
* @param email Строка содержащая email | ||
*/ | ||
function isValidEmail(email) { | ||
if (!email) | ||
return false; | ||
const emailParts = email.split(EMAIL_PARTS_SEPARATOR); | ||
if (emailParts.length !== 2) | ||
return false; | ||
const [account, address] = emailParts; | ||
const accountTooLong = account.length > MAX_ACCOUNT_LENGTH; | ||
const addressTooLong = address.length > MAX_ADDRES_LENGTH; | ||
if (accountTooLong || addressTooLong) | ||
return false; | ||
const domainParts = address.split(DOMAIN_PARTS_SEPARATOR); | ||
const domainTooLong = domainParts.some((part) => part.length > MAX_DOMAIN_LENGTH); | ||
if (domainTooLong) | ||
return false; | ||
return EMAIL_REGEX.test(email); | ||
} | ||
// prettier-ignore | ||
const keyboardsLayouts = { | ||
en: [ | ||
// нижний регистр | ||
/* mac */ '§', /* win */ '`', | ||
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', | ||
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '\\', | ||
'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', | ||
// нижний регистр через shift | ||
/* mac */ '±', /* win */ '~', | ||
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', | ||
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '|', | ||
'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', | ||
'@', | ||
], | ||
ru: [ | ||
// нижний регистр | ||
'ё', 'ё', | ||
'й', 'ц', 'у', 'к', 'е', 'н', 'г', 'ш', 'щ', 'з', 'х', 'ъ', | ||
'ф', 'ы', 'в', 'а', 'п', 'р', 'о', 'л', 'д', 'ж', 'э', 'ё', | ||
'я', 'ч', 'с', 'м', 'и', 'т', 'ь', 'б', 'ю', '/', | ||
// нижний регистр через shift | ||
'Ё', 'Ё', | ||
'Й', 'Ц', 'У', 'К', 'Е', 'Н', 'Г', 'Ш', 'Щ', 'З', 'Х', 'Ъ', | ||
'Ф', 'Ы', 'В', 'А', 'П', 'Р', 'О', 'Л', 'Д', 'Ж', 'Э', 'Ё', | ||
'Я', 'Ч', 'С', 'М', 'И', 'Т', 'Ь', 'Б', 'Ю', '?', | ||
'"', | ||
], | ||
}; | ||
/** regex для раскладок клавиатуры */ | ||
const keyboardLanguages = { | ||
en: /[a-z[\]{};:'"\\|,.<>?§±`~]/i, | ||
ru: /[а-яё"/?]/i, | ||
}; | ||
/** | ||
* Проверяет строку на совпадение с раскладкой клавиатуры. | ||
*/ | ||
function isKeyboardLayout(string, keyboardAlias) { | ||
if (!string.length) | ||
return false; | ||
// your keyboard | ||
const keyboardLanguage = keyboardLanguages[keyboardAlias]; | ||
// недопустимая раскладка клавиатуры | ||
if (!keyboardLanguage) | ||
return false; | ||
let index = 0; | ||
let isValid = false; | ||
while (index < string.length) { | ||
const letter = string[index]; | ||
if (keyboardLanguage.test(letter)) { | ||
isValid = true; | ||
return true; | ||
} | ||
index += 1; | ||
} | ||
return isValid; | ||
} | ||
/** | ||
* Конвертирует символы из одной раскладки в другую. | ||
*/ | ||
function keyboardSwitcher(characters = '', from = 'en', to = 'ru') { | ||
// incoming text string | ||
const textToConvert = characters; | ||
// if characters is empty stop working | ||
if (!textToConvert || !textToConvert.length) | ||
return ''; | ||
// if incoming text and current keyboard not equal | ||
if (!isKeyboardLayout(textToConvert, from)) { | ||
return characters; | ||
} | ||
// current keyboard layout | ||
const locale = keyboardsLayouts[from]; | ||
// convert characters to this keyboard layout | ||
const localeOn = keyboardsLayouts[to]; | ||
let convertedText = ''; | ||
let index = 0; | ||
while (index < textToConvert.length) { | ||
const letter = textToConvert[index]; | ||
const letterIndex = locale.indexOf(letter); | ||
convertedText += localeOn[letterIndex]; | ||
index += 1; | ||
} | ||
return convertedText; | ||
} | ||
function switchToKeyboard(characters, keyboardAlias) { | ||
const textToConvert = characters; | ||
if (!textToConvert.length) | ||
return ''; | ||
const keyboards = Object.keys(keyboardLanguages); | ||
let index = 0; | ||
let convertedText = ''; | ||
while (index < textToConvert.length) { | ||
const letter = textToConvert[index]; | ||
let locale = ''; | ||
keyboards.map((keyboardKey) => { | ||
const isKeyboardIncludesLetter = isKeyboardLayout(letter, keyboardKey); | ||
if (isKeyboardIncludesLetter && keyboardKey !== keyboardAlias) { | ||
locale = keyboardKey; | ||
return ''; | ||
} | ||
return ''; | ||
}); | ||
const returnedLetter = locale === keyboardAlias ? letter : keyboardSwitcher(letter, locale, keyboardAlias); | ||
convertedText += returnedLetter; | ||
index += 1; | ||
} | ||
return convertedText; | ||
} | ||
/** | ||
* Автоматически переводит английскую раскладку на русскую при вводе пользователем. | ||
*/ | ||
const formatToRussian = (value = '', isCapitalize = false) => { | ||
if (!value) | ||
return ''; | ||
// check user keyboard and if it need convert to russian | ||
const enteredValue = switchToKeyboard(value, 'ru'); | ||
return (isCapitalize ? enteredValue[0].toUpperCase() + enteredValue.substr(1) : enteredValue) | ||
.replace(/[^\sа-яё-]/gi, '') | ||
.replace(/\s{2,}/g, ' '); | ||
}; | ||
/** | ||
* Возвращает TRUE, если проскролено до низа страницы | ||
*/ | ||
function hasScrolledToBottomOfPage() { | ||
const { documentElement } = document; | ||
const offset = documentElement.scrollTop + window.innerHeight; | ||
const height = documentElement.offsetHeight; | ||
return offset >= height; | ||
} | ||
/* eslint-disable no-param-reassign */ | ||
const NUMBER_REGEX = /^\d+$/; | ||
const SKIP_NODE_NAMES = ['', null, undefined]; | ||
const nodeNamesToPath = (nodeNames) => nodeNames.reduce((pathAcc, nodeName) => { | ||
if (!SKIP_NODE_NAMES.includes(nodeName)) { | ||
if (nodeName === '*' || NUMBER_REGEX.test(`${nodeName}`)) { | ||
pathAcc += '[*]'; | ||
} | ||
else { | ||
if (pathAcc) { | ||
pathAcc += '.'; | ||
} | ||
pathAcc += nodeName; | ||
} | ||
} | ||
return pathAcc; | ||
}, ''); | ||
const INVALID_FILTER_CONFIG_VALUES = ['', null, undefined, true, false]; | ||
const VALID_REPLACE_CONFIG_TYPES = ['string', 'number', 'boolean', 'function']; | ||
const isReplacer = (replacer) => replacer === null || VALID_REPLACE_CONFIG_TYPES.includes(typeof replacer); | ||
const prepareConfig = ({ replace: replaceConfig = {}, filter: filterConfig = [], }) => { | ||
const filteredReplaceConfig = Object.keys(replaceConfig).reduce((res, replaceConfigKey) => { | ||
const replacer = replaceConfig[replaceConfigKey]; | ||
if (isReplacer(replacer)) { | ||
res[replaceConfigKey] = replacer; | ||
} | ||
return res; | ||
}, {}); | ||
const filteredFilterConfigObject = filterConfig.reduce((res, path) => { | ||
if (INVALID_FILTER_CONFIG_VALUES.includes(path)) { | ||
return res; | ||
} | ||
return Object.assign(Object.assign({}, res), { [path]: true }); | ||
}, {}); | ||
const paths = [ | ||
...Object.keys(filteredFilterConfigObject), | ||
...Object.keys(filteredReplaceConfig), | ||
]; | ||
if (paths.length) { | ||
return { | ||
replaceConfig: filteredReplaceConfig, | ||
filterConfig: filteredFilterConfigObject, | ||
}; | ||
} | ||
throw new TypeError('required replace or filter in transformConfig'); | ||
}; | ||
const getReplaceValue = (value, replacer) => { | ||
if (isReplacer(replacer)) { | ||
return typeof replacer === 'function' ? replacer(value) : replacer; | ||
} | ||
return value; | ||
}; | ||
/* eslint-disable no-param-reassign */ | ||
// eslint-disable-next-line @typescript-eslint/naming-convention, no-underscore-dangle | ||
const _transformData = (data, { filterConfig, replaceConfig }, parentPath = '') => transform(data, (result, value, key) => { | ||
const currentPath = nodeNamesToPath([parentPath, key]); | ||
// Recurse into arrays and objects. | ||
if (Array.isArray(value) || isPlainObject(value)) { | ||
value = _transformData(value, { | ||
filterConfig, | ||
replaceConfig, | ||
}, currentPath); | ||
} | ||
if (filterConfig[currentPath]) { | ||
return; | ||
} | ||
const newValue = getReplaceValue(value, replaceConfig[currentPath]); | ||
if (Array.isArray(result)) { | ||
result.push(newValue); | ||
return; | ||
} | ||
result[key] = newValue; | ||
}); | ||
/** | ||
* Преобразование полей объекта на основе конфига | ||
* | ||
* @param data {Object|Array} данные для преобразования | ||
* @param config {TransformConfig} конфиг с функциями преобразования и путей для фильтра | ||
*/ | ||
const transformData = (data, config) => _transformData(data, prepareConfig(config)); | ||
const transformDataUtils = { | ||
getReplaceValue, | ||
isReplacer, | ||
nodeNamesToPath, | ||
prepareConfig, | ||
}; | ||
export { AMOUNT_MAJOR_MINOR_PARTS_SEPARATOR, Locale, MMSP, NEGATIVE_SYMBOLS, THINSP, cropAccountNumber, formatAccount, formatAmount, formatFileSize, formatToRussian, getAllCurrencyCodes, getCountries, getCountriesHash, getCurrencySymbol, hasScrolledToBottomOfPage, isKeyboardLayout, isOverflown, isValidCardNumber, isValidEmail, keyboardLanguages, keyboardSwitcher, keyboardsLayouts, phoneNumber, pluralize, secondsToTime, splitAmount, switchToKeyboard, transformData, transformDataUtils }; | ||
export { cropAccountNumber } from './crop-account-number/util.js'; | ||
export { formatAccount } from './format-account/util.js'; | ||
export { AMOUNT_MAJOR_MINOR_PARTS_SEPARATOR, MMSP, NEGATIVE_SYMBOLS, THINSP, formatAmount } from './format-amount/util.js'; | ||
export { formatFileSize } from './format-file-size/util.js'; | ||
export { Locale } from './format-file-size/locale.js'; | ||
export { phoneNumber } from './format-phone/index.js'; | ||
export { getAllCurrencyCodes } from './get-all-currency-codes/util.js'; | ||
export { getCountries, getCountriesHash } from './get-countries/util.js'; | ||
export { getCurrencySymbol } from './get-currency-symbol/util.js'; | ||
export { isOverflown } from './is-overflown/util.js'; | ||
export { pluralize } from './pluralize/util.js'; | ||
export { secondsToTime } from './seconds-to-time/util.js'; | ||
export { splitAmount } from './split-amount/util.js'; | ||
export { isValidCardNumber } from './is-valid-card-number/util.js'; | ||
export { isValidEmail } from './is-valid-email/util.js'; | ||
export { formatToRussian, isKeyboardLayout, keyboardLanguages, keyboardSwitcher, keyboardsLayouts, switchToKeyboard } from './keyboard-switcher/util.js'; | ||
export { hasScrolledToBottomOfPage } from './has-scrolled-to-bottom-of-page/util.js'; | ||
export { transformDataUtils } from './transform-data/index.js'; | ||
export { transformData } from './transform-data/util.js'; |
{ | ||
"name": "@alfalab/utils", | ||
"version": "1.17.0-rc.1", | ||
"version": "1.17.1", | ||
"description": "common utils", | ||
@@ -13,6 +13,7 @@ "sideEffects": false, | ||
"scripts": { | ||
"build": "yarn build:ts:es5 && yarn build:ts:es6 && yarn build:dts", | ||
"build": "yarn build:ts:es5 && yarn build:ts:es6 && yarn build:dts && yarn size", | ||
"build:ts:es5": "rollup --config './rollup.config.js'", | ||
"build:ts:es6": "rollup --config './rollup.config.esm.js'", | ||
"build:dts": "dts-bundle-generator --no-banner --config dts.json" | ||
"build:dts": "dts-bundle-generator --no-banner --no-check --config dts.json", | ||
"size": "yarn size-limit --json 2>&1 | grep -v '^$ ' > size-stat.json" | ||
}, | ||
@@ -23,9 +24,7 @@ "keywords": [], | ||
"dependencies": { | ||
"@alfalab/data": "^1.8.0", | ||
"lodash": "4.17.21" | ||
"@alfalab/data": "^1.9.1", | ||
"lodash": "^4.17.21" | ||
}, | ||
"devDependencies": { | ||
"@types/lodash": "4.14.182", | ||
"dts-bundle-generator": "^6.12.0", | ||
"rollup": "^2.38.0" | ||
"@types/lodash": "4.14.182" | ||
}, | ||
@@ -35,3 +34,3 @@ "publishConfig": { | ||
}, | ||
"gitHead": "10dd0711fab88c3173da9cd72abe50194559d021" | ||
"gitHead": "f02f9ff4bc3da6e3428324247da85f2b2f91a5e7" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
73816
1
31
1609
1
0
Updated@alfalab/data@^1.9.1
Updatedlodash@^4.17.21