UNPKG

polish-validators

Version:

A set of validator functions that check common polish numbers.

215 lines (214 loc) 9.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getFullBankNameFromIban = exports.getBankNameFromIban = exports.getCountryIbanDataFromIban = exports.isIbanInvalid = exports.isIbanValid = void 0; const _utils_1 = require("./_utils"); const iban_bank_name_tree_1 = require("./iban-bank-name-tree"); const iban_bank_names_1 = require("./iban-bank-names"); const iban_bank_names_full_1 = require("./iban-bank-names-full"); const IBAN_COUNTRY_DATA = { AL: { country: 'Albania', length: 28 }, AD: { country: 'Andora', length: 24 }, AT: { country: 'Austria', length: 20 }, AZ: { country: 'Azerbejdżan', length: 28 }, BH: { country: 'Bahrajn', length: 22 }, BY: { country: 'Białoruś', length: 28 }, BE: { country: 'Belgia', length: 16 }, BA: { country: 'Bośnia i Hercegowina', length: 20 }, BR: { country: 'Brazylia', length: 29 }, BG: { country: 'Bułgaria', length: 22 }, BI: { country: 'Burundi', length: 27 }, CR: { country: 'Kostaryka', length: 22 }, HR: { country: 'Chorwacja', length: 21 }, CY: { country: 'Cypr', length: 28 }, CZ: { country: 'Czechy', length: 24 }, DK: { country: 'Dania', length: 18 }, DJ: { country: 'Dżibuti', length: 27 }, DO: { country: 'Dominikana', length: 28 }, EG: { country: 'Egipt', length: 29 }, SV: { country: 'Salwador', length: 28 }, EE: { country: 'Estonia', length: 20 }, FK: { country: 'Falklandy', length: 18 }, FO: { country: 'Wyspy Owcze', length: 18 }, FI: { country: 'Finlandia', length: 18 }, FR: { country: 'Francja', length: 27 }, GE: { country: 'Gruzja', length: 22 }, DE: { country: 'Niemcy', length: 22 }, GI: { country: 'Gibraltar', length: 23 }, GR: { country: 'Grecja', length: 27 }, GL: { country: 'Grenlandia', length: 18 }, GT: { country: 'Gwatemala', length: 28 }, VA: { country: 'Watykan', length: 22 }, HU: { country: 'Węgry', length: 28 }, IS: { country: 'Islandia', length: 26 }, IQ: { country: 'Irak', length: 23 }, IE: { country: 'Irlandia', length: 22 }, IL: { country: 'Izrael', length: 23 }, IT: { country: 'Włochy', length: 27 }, JO: { country: 'Jordania', length: 30 }, KZ: { country: 'Kazachstan', length: 20 }, XK: { country: 'Kosowo', length: 20 }, KW: { country: 'Kuwejt', length: 30 }, LV: { country: 'Łotwa', length: 21 }, LB: { country: 'Liban', length: 28 }, LY: { country: 'Libia', length: 25 }, LI: { country: 'Liechtenstein', length: 21 }, LT: { country: 'Litwa', length: 20 }, LU: { country: 'Luksemburg', length: 20 }, MT: { country: 'Malta', length: 31 }, MR: { country: 'Mauretania', length: 27 }, MU: { country: 'Mauritius', length: 30 }, MD: { country: 'Mołdawia', length: 24 }, MC: { country: 'Monako', length: 27 }, MN: { country: 'Mongolia', length: 20 }, ME: { country: 'Czarnogóra', length: 22 }, NL: { country: 'Holandia', length: 18 }, NI: { country: 'Nikaragua', length: 28 }, MK: { country: 'Macedonia Północna', length: 19 }, NO: { country: 'Norwegia', length: 15 }, PK: { country: 'Pakistan', length: 24 }, PS: { country: 'Palestyna', length: 29 }, PL: { country: 'Polska', length: 28 }, PT: { country: 'Portugalia', length: 25 }, QA: { country: 'Katar', length: 29 }, RO: { country: 'Rumunia', length: 24 }, RU: { country: 'Rosja', length: 33 }, LC: { country: 'Saint Lucia', length: 32 }, SM: { country: 'San Marino', length: 27 }, ST: { country: 'Wyspy Świętego Tomasza i Książęca', length: 25 }, SA: { country: 'Arabia Saudyjska', length: 24 }, RS: { country: 'Serbia', length: 22 }, SC: { country: 'Seszele', length: 31 }, SK: { country: 'Słowacja', length: 24 }, SI: { country: 'Słowenia', length: 19 }, SO: { country: 'Somalia', length: 23 }, ES: { country: 'Hiszpania', length: 24 }, SD: { country: 'Sudan', length: 18 }, OM: { country: 'Oman', length: 23 }, SE: { country: 'Szwecja', length: 24 }, CH: { country: 'Szwajcaria', length: 21 }, TL: { country: 'Timor Wschodni', length: 23 }, TN: { country: 'Tunezja', length: 24 }, TR: { country: 'Turcja', length: 26 }, UA: { country: 'Ukraina', length: 29 }, AE: { country: 'Zjednoczone Emiraty Arabskie', length: 23 }, GB: { country: 'Wielka Brytania', length: 22 }, VG: { country: 'Brytyjskie Wyspy Dziewicze', length: 24 }, YE: { country: 'Jemen', length: 30 }, }; const IBAN_REGEX = /^([A-Z]{2})?(\d{2})(\d{4})(\d{7,24})$/i; const IBAN_BANK_DATA_REGEX = /^(?:PL)?\d{2}(\d{3,4})/i; function _modulo(number, mod) { let result = 0; for (let i = 0; i < number.length; i++) { result = parseInt(result.toString() + number[i]) % mod; } return result; } /** * Validates an International Bank Account Number (IBAN). The function checks for * proper length, format, and passes the IBAN checksum requirements. In the case of * IBANs starting with `PL` (or with no country code), the 3rd-5th digits are validated * against a list of Polish banks. Any whitespace is ignored, but other characters will * result in the IBAN being invalid. * * @param {string} iban - The IBAN number as a string, with or without spaces. * @returns {boolean} `true` if the IBAN is valid; `false` otherwise. */ function isIbanValid(iban) { iban = (0, _utils_1.removeWhitespace)(iban).toUpperCase(); // Validate the structure using the regex. const match = iban.match(IBAN_REGEX); if (!match) { return false; } // Destructure the regex match, defaulting to 'PL' if the country code is missing. const [, countryCode = 'PL', controlSum, bankNameNumber, rest] = match; // Check the overall length for the given country. if (!IBAN_COUNTRY_DATA[countryCode] || controlSum.length + bankNameNumber.length + rest.length + 2 !== IBAN_COUNTRY_DATA[countryCode].length) { return false; } // For Polish IBANs, verify that the bank code is in our known list. if (countryCode === 'PL' && !iban_bank_name_tree_1.BankNameTree.existsCode(bankNameNumber)) { return false; } // Rearrange the IBAN: move the first 4 characters (country code and control sum) // to the end. The BBAN (bankNameNumber + rest) comes first. const rearranged = bankNameNumber + rest + (countryCode.charCodeAt(0) - 55).toString() + (countryCode.charCodeAt(1) - 55).toString() + controlSum; const checkSum = _modulo(rearranged, 97); return checkSum === 1; } exports.isIbanValid = isIbanValid; /** * Returns true if the IBAN is invalid; false otherwise. * * @param {string} iban - The IBAN number as a string. * @returns {boolean} */ const isIbanInvalid = (iban) => !isIbanValid(iban); exports.isIbanInvalid = isIbanInvalid; /** * Extracts country-specific information from the IBAN. * * @param {string} iban - The IBAN number as a string. * @returns {{ country: string; length: number } | null} An object containing the country name * and IBAN length for the given IBAN, or `null` if not valid. */ function getCountryIbanDataFromIban(iban) { iban = (0, _utils_1.removeWhitespace)(iban).toUpperCase(); if (iban.length < 2) { return null; } const countryCode = iban.slice(0, 2); return IBAN_COUNTRY_DATA[countryCode] ?? null; } exports.getCountryIbanDataFromIban = getCountryIbanDataFromIban; /** * Fetches the bank name based on the IBAN, specifically for Polish IBANs. * If a non-Polish IBAN is supplied, it will always return `null`. * * @param {string} iban - The IBAN number as a string. * @returns {string | null} The bank name as a string, or `null` if not available. */ function getBankNameFromIban(iban) { iban = (0, _utils_1.removeWhitespace)(iban).toUpperCase(); const match = iban.match(IBAN_BANK_DATA_REGEX); if (!match) { return null; } const bankCode = match[1]; const bankNameIndex = iban_bank_name_tree_1.BankNameTree.getIndex(bankCode); if (!bankNameIndex) { return null; } return iban_bank_names_1.BANK_NAME_LIST[bankNameIndex] ?? null; } exports.getBankNameFromIban = getBankNameFromIban; /** * Fetches the full bank name based on the IBAN, specifically for Polish IBANs. * If a non-Polish IBAN is supplied, it will always return `null`. * * @param {string} iban - The IBAN number as a string. * @returns {string | null} The full bank name as a string, or `null` if not available. */ function getFullBankNameFromIban(iban) { iban = (0, _utils_1.removeWhitespace)(iban).toUpperCase(); if (!iban.startsWith('PL')) { return null; } const match = iban.match(IBAN_BANK_DATA_REGEX); if (!match) { return null; } const bankCode = match[1]; const bankNameIndex = iban_bank_name_tree_1.BankNameTree.getIndex(bankCode); if (!bankNameIndex) { return null; } return iban_bank_names_full_1.FULL_BANK_NAME_LIST[bankNameIndex] ?? null; } exports.getFullBankNameFromIban = getFullBankNameFromIban;