New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

uk-modulus-check

Package Overview
Dependencies
Maintainers
0
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

uk-modulus-check - npm Package Compare versions

Comparing version 1.0.14 to 1.0.15

dist/data/data/scsubtab.json

38

dist/ExceptionRules.js
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyPostTotalExceptionRules = exports.applyOverwriteExceptionRules = exports.applyWeightValueExceptionRules = exports.applyAccountDetailExceptionRules = void 0;
const fs_1 = require("fs");
const enums_1 = require("./enums");
const loadSubstitutionMap = () => (0, fs_1.readFileSync)(`${__dirname}/data/scsubtab.txt`, 'utf8')
.split('\r\n')
.map((line) => line.split(/\s+/))
.reduce((acc, [key, value]) => (Object.assign(Object.assign({}, acc), { [key]: value })), {});
const scsubtab_json_1 = __importDefault(require("./data/scsubtab.json"));
const applyLengthAdjustments = (sortCode, accountNumber) => {

@@ -27,7 +26,6 @@ let [adjustedSortCode, adjustedAccountNumber] = [sortCode, accountNumber];

};
const applyExceptionAdjustments = (sortCode, accountNumber, modulusWeightException) => {
let [adjustedSortCode, adjustedAccountNumber] = [sortCode, accountNumber];
let substitutionMap = loadSubstitutionMap();
if (modulusWeightException === 5 && substitutionMap[sortCode]) {
adjustedSortCode = substitutionMap[sortCode];
const applyExceptionAdjustments = (sortCode, modulusWeightException) => {
let adjustedSortCode = sortCode;
if (modulusWeightException === 5 && scsubtab_json_1.default[sortCode]) {
adjustedSortCode = scsubtab_json_1.default[sortCode];
}

@@ -40,8 +38,8 @@ else if (modulusWeightException === 8) {

}
return { sortCode: adjustedSortCode, accountNumber: adjustedAccountNumber };
return adjustedSortCode;
};
const applyAccountDetailExceptionRules = (sortCode, accountNumber, modulusWeightException) => {
const { sortCode: lengthAdjustedSortCode, accountNumber: lengthAdjustedAccountNumber, } = applyLengthAdjustments(sortCode, accountNumber);
const { sortCode: exceptionAdjustedSortCode, accountNumber: exceptionAdjustedAccountNumber, } = applyExceptionAdjustments(lengthAdjustedSortCode, lengthAdjustedAccountNumber, modulusWeightException);
return exceptionAdjustedSortCode + exceptionAdjustedAccountNumber;
const exceptionAdjustedSortCode = applyExceptionAdjustments(lengthAdjustedSortCode, modulusWeightException);
return exceptionAdjustedSortCode + lengthAdjustedAccountNumber;
};

@@ -74,10 +72,5 @@ exports.applyAccountDetailExceptionRules = applyAccountDetailExceptionRules;

const applyOverwriteExceptionRules = (modulusWeight, accountDetails) => {
const a = accountDetails[enums_1.AccountDetailIndex.A];
const g = accountDetails[enums_1.AccountDetailIndex.G];
const h = accountDetails[enums_1.AccountDetailIndex.H];
// exception 3 is a special case where the first digit of the account number must be 1 or 9
if (modulusWeight.exception === 3 && ['1', '9'].includes(a)) {
const { [enums_1.AccountDetailIndex.A]: a, [enums_1.AccountDetailIndex.G]: g, [enums_1.AccountDetailIndex.H]: h, } = accountDetails;
if (modulusWeight.exception === 3 && ['1', '9'].includes(a))
return { modifiedAccountDetails: accountDetails, overwriteResult: true };
}
// exception 6 is a special case where the first digit of the account number must be between 4 and 10 and the 7th and 8th digits must be the same
if (modulusWeight.exception === 6 &&

@@ -108,5 +101,4 @@ parseInt(a, 10) >= 4 &&

if (exception == 4) {
const remainder = total % 11;
const checkDigit = parseInt(accountDetails.substring(accountDetails.length - 2), 10);
if (remainder === checkDigit) {
if (total % 11 ===
parseInt(accountDetails.substring(accountDetails.length - 2), 10)) {
overwriteResult2 = true;

@@ -113,0 +105,0 @@ }

import { ModulusWeight } from './interfaces';
export default class ModulusChecker {
private modulusWeighstArray;
private unseenSortCodeBehaviour;
constructor(unseenSortCodeBehaviour?: boolean);
private loadModulusWeightsArray;
modulusCheck: (modulusWeight: ModulusWeight, sortCode: string, accountNumber: string) => boolean;
validate(sortCode: string, accountNumber: string): boolean;
}
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const enums_1 = require("./enums");
const ExceptionRules_1 = require("./ExceptionRules");
const valacdos_json_1 = __importDefault(require("./data/valacdos.json"));
class ModulusChecker {
constructor(unseenSortCodeBehaviour = true) {
this.unseenSortCodeBehaviour = true;
constructor() {
this.modulusCheck = (modulusWeight, sortCode, accountNumber) => {

@@ -17,5 +19,4 @@ // by default, the account details are the sort code followed by the account number

const { modifiedAccountDetails, overwriteResult } = (0, ExceptionRules_1.applyOverwriteExceptionRules)(modulusWeight, accountDetails);
if (overwriteResult !== null) {
if (overwriteResult !== null)
return overwriteResult;
}
// multiply each digit of the account details by the corresponding weight value

@@ -39,56 +40,35 @@ const multiplicationResultArray = modifiedAccountDetails

}
// there are acceptions that are applied after the total has been calculated
// there are exceptions that are applied after the total has been calculated
// these can either adjust the total, or require a non-standard modulus check
const { adjustedTotal, overwriteResult2 } = (0, ExceptionRules_1.applyPostTotalExceptionRules)(modulusWeight.exception, total, accountDetails);
if (overwriteResult2 !== null) {
if (overwriteResult2 !== null)
return overwriteResult2;
}
if (modulusWeight.check_type === enums_1.CheckType.MOD11) {
return adjustedTotal % 11 === 0;
}
else {
return adjustedTotal % 10 === 0;
}
const checkTypeValue = modulusWeight.check_type === enums_1.CheckType.MOD11 ? 11 : 10;
return adjustedTotal % checkTypeValue === 0;
};
this.modulusWeighstArray = this.loadModulusWeightsArray();
this.unseenSortCodeBehaviour = unseenSortCodeBehaviour;
}
loadModulusWeightsArray() {
return (0, fs_1.readFileSync)(`${__dirname}/data/valacdos-v7-90.txt`, 'utf8')
.split('\r\n')
.map((line) => {
const data = line.split(/\s+/);
return {
start: parseInt(data[0], 10),
end: parseInt(data[1], 10),
check_type: data[2],
exception: parseInt(data[17], 10) || null,
weights: data.slice(3, 17).map((weight) => parseInt(weight, 10)),
};
});
}
validate(sortCode, accountNumber) {
// sort code must be 6 digits and account number must be between 6 and 10 digits
if (accountNumber.length < 6 ||
accountNumber.length > 10 ||
sortCode.length !== 6) {
// sort code must be 6 digits, account number must be between 6 and 10 digits
if (accountNumber.length <= 6 ||
accountNumber.length >= 10 ||
sortCode.length !== 6)
return false;
}
// check if there are any non-numeric characters in the sort code or account number
if (!/^\d+$/.test(sortCode + accountNumber)) {
// sort code and account number must be numeric
if (!/^\d+$/.test(sortCode + accountNumber))
return false;
}
const matchingModulusWeights = this.modulusWeighstArray.filter((weight) => parseInt(sortCode, 10) >= weight.start &&
// find the modulus weight that matches the sort code
const matchingModulusWeights = valacdos_json_1.default.filter((weight) => weight.start &&
weight.end &&
parseInt(sortCode, 10) >= weight.start &&
parseInt(sortCode, 10) <= weight.end);
// there must be at least one matching modulus weight, otherwise return the default behaviour
if (!matchingModulusWeights.length) {
return this.unseenSortCodeBehaviour;
}
// return true if any of the matching modulus weights pass the modulus
// this includes the case where there are multiple matching modulus weights
return matchingModulusWeights
.map((weight) => this.modulusCheck(weight, sortCode, accountNumber))
.some((result) => result);
// if there are no matching modulus weights, the sort code is not recognised
// return true, since Vocalink data doesn't seem to have 100% coverage
if (!matchingModulusWeights.length)
return true;
// if any of the matching modulus weights pass the modulus, the account number is valid
// note, this is slightly conservative, and might return true for some invalid account numbers
// find the actual spec. quite confusing on these cases
return matchingModulusWeights.some((weight) => this.modulusCheck(weight, sortCode, accountNumber));
}
}
exports.default = ModulusChecker;
import { CheckType } from './enums';
export interface ModulusWeight {
start: number;
end: number;
check_type: CheckType;
start: number | null;
end: number | null;
check_type?: CheckType;
exception: number | null;

@@ -7,0 +7,0 @@ weights: number[];

{
"name": "uk-modulus-check",
"version": "1.0.14",
"version": "1.0.15",
"main": "dist/index.js",

@@ -17,3 +17,4 @@ "types": "dist/index.d.ts",

"test": "jest",
"format": "prettier --write 'src/**/*.{ts,js,json,md}'"
"format": "prettier --write 'src/**/*.{ts,js,json,md}'",
"publish": "npm run build && npm publish"
},

@@ -20,0 +21,0 @@ "keywords": [

@@ -61,2 +61,7 @@ import ModulusChecker from '../src';

test('should return true for a sort code not on the spec range', () => {
const isValid = checker.validate('000000', '12345678');
expect(isValid).toBe(true);
});
// Vocalink spec tests

@@ -63,0 +68,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc