ibantools-germany
Version:
IBAN Validator and Generator for German Bank Accounts
148 lines (145 loc) • 5.48 kB
JavaScript
;
/**
* 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;