UNPKG

ibantools-germany

Version:

IBAN Validator and Generator for German Bank Accounts

148 lines (145 loc) 5.48 kB
"use strict"; /** * ibantools-germany * Copyright (C) 2022-2024 Markus Baumer <markus@baumer.dev> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.lettersToDigits = exports.modulo97 = exports.diffNextHalfDecade = exports.moduloDifference = exports.weightDigitsRTL = exports.weightDigits = exports.getUnitsFromNumbers = exports.getUnitFromNumber = exports.calculateCrossSums = exports.calculateCrossSum = exports.calculateSum = exports.getDigits = exports.paddedAccountNumber = void 0; /** * Fill the account number with zeros from the left to get a 10 digits string */ const paddedAccountNumber = (number) => { if (number.length > 10) { throw new Error("Account number must not be longer than 10 digits."); } return number.padStart(10, "0"); }; exports.paddedAccountNumber = paddedAccountNumber; /** * Get an array of digits for a number or string * * Example: 0118999 will return [0, 1, 1, 8, 9 ,9 ,9] */ const getDigits = (numberOrString) => { const string = typeof numberOrString === "string" ? numberOrString : numberOrString.toString(); return string.split("").map((digitString) => Number(digitString)); }; exports.getDigits = getDigits; /** * Get the sum of all numbers * * Example: [1,2,3] will return 6 */ const calculateSum = (numbers) => numbers.reduce((accumulated, number) => accumulated + number, 0); exports.calculateSum = calculateSum; /** * Get cross sum of number * * Example: 17 will return 8, 146 will return 11 */ const calculateCrossSum = (number) => (0, exports.calculateSum)((0, exports.getDigits)(number)); exports.calculateCrossSum = calculateCrossSum; /** * Get cross sum of each number * * Example: [17, 146] will return [8, 11] */ const calculateCrossSums = (numbers) => numbers.map((number) => (0, exports.calculateCrossSum)(number)); exports.calculateCrossSums = calculateCrossSums; /** * Get unit column of number * * Example: 94 will return 4, 236 will return 6 */ const getUnitFromNumber = (number) => (0, exports.getDigits)(number).slice(-1)[0]; exports.getUnitFromNumber = getUnitFromNumber; /** * Get unit column of numbers * * Example: [94, 83] will return [4, 3] */ const getUnitsFromNumbers = (numbers) => numbers.map((number) => (0, exports.getUnitFromNumber)(number)); exports.getUnitsFromNumbers = getUnitsFromNumbers; /** * Return an array of digits weighted. This can either be by * multiplying the digits with the weight (default) or adding * the weight to the digits or by multiplying and then adding * the weight. * * Example: digits [1, 2 , 3 , 4] with weights [1, 2, 1, 2] * will return * [1, 4, 3, 8] with type MULTIPLY * [2, 6, 4, 10] with type MULTIPLY_ADD */ const weightDigits = (digits, weights, weightType = "MULTIPLY") => { if (weights.length < digits.length) { throw new Error("Number of weights must be greater or equal the number of digits."); } return digits.map((digit, index) => { if (weightType === "MULTIPLY_ADD") { return digit * weights[index] + weights[index]; } return digit * weights[index]; }); }; exports.weightDigits = weightDigits; /** * Does the same as weightDigits() but uses the weight (left to right) * on the digits (right to left) */ const weightDigitsRTL = (digits, weights, weightType = "MULTIPLY") => (0, exports.weightDigits)([...digits].reverse(), weights, weightType); exports.weightDigitsRTL = weightDigitsRTL; /** * Calculates the modulo (remainder of division) and subtracts it from * the minuend, returns difference and remainder. * * Example: Value 12 with divisor 10 and minuend 11 will return 9 (remainder of 12/10 = 2; 11-2 = 9) */ const moduloDifference = (value, divisor, minuend) => { const remainder = value % divisor; return { difference: minuend - remainder, remainder }; }; exports.moduloDifference = moduloDifference; /** * Get the difference to next half decade (5, 15, 25...). * * Example: Value 12 result is 3, value 6 is 9 */ const diffNextHalfDecade = (value) => { if (value % 10 <= 5) { return 5 - (value % 10); } return 10 - ((value % 10) % 5); }; exports.diffNextHalfDecade = diffNextHalfDecade; /** * Checksum calculation method for IBAN */ const modulo97 = (value) => { let checksum = Number(value.slice(0, 2)); let fragment; for (let offset = 2; offset < value.length; offset += 7) { fragment = `${checksum}${value.substring(offset, offset + 7)}`; checksum = parseInt(fragment, 10) % 97; } return checksum; }; exports.modulo97 = modulo97; /** * Convert letters to digits (ASCII code minus 55) */ const lettersToDigits = (string) => string.replace(/[a-z]/gi, (letter) => String(letter.charCodeAt(0) - 55)); exports.lettersToDigits = lettersToDigits;