polish-validators
Version:
A set of validator functions that check common polish numbers.
215 lines (214 loc) • 9.33 kB
JavaScript
"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;