{"version":3,"file":"index.modern.mjs","sources":["../src/constants.ts","../src/utils.ts","../src/index.ts"],"sourcesContent":["import type {\n  BankData,\n  BankChecksums,\n  PartsObject,\n  PartIndexes,\n  PartMaxLengths,\n} from \"./models\";\n\nconst partConstants: PartsObject = {\n  id: \"id\",\n  branch: \"branch\",\n  base: \"base\",\n  suffix: \"suffix\",\n};\n\nconst partIndexes: PartIndexes = {\n  id: 0,\n  branch: 1,\n  base: 2,\n  suffix: 3,\n};\n\nconst partMaxLengths: PartMaxLengths = {\n  id: 2,\n  branch: 4,\n  base: 8,\n  suffix: 4,\n};\n\n// The ranges used for branches are inclusive\nconst bankData: BankData[] = [\n  {\n    key: \"AB\",\n    branches: {\n      \"01\": [\n        [1, 999],\n        [1100, 1199],\n        [1800, 1899],\n        [6150, 6150],\n      ],\n\n      \"02\": [\n        [1, 999],\n        [1200, 1299],\n        [2025, 2055],\n      ],\n\n      \"03\": [\n        [1, 999],\n        [1300, 1399],\n        [1500, 1599],\n        [1700, 1799],\n        [1900, 1999],\n        [7350, 7399],\n      ],\n\n      \"04\": [[2014, 2024]], // Lower bound from https://www.paymentsnz.co.nz/resources/industry-registers/bank-branch-register/\n\n      \"05\": [[8884, 8889]], // China Construction Bank, see https://www.paymentsnz.co.nz/resources/industry-registers/bank-branch-register/\n\n      \"06\": [\n        [1, 999],\n        [1400, 1499],\n      ],\n\n      10: [[5165, 5169]],\n\n      11: [\n        [5000, 6499],\n        [6600, 8999],\n      ],\n\n      12: [\n        [3000, 3299],\n        [3400, 3499],\n        [3600, 3699],\n      ],\n\n      13: [[4900, 4999]],\n\n      14: [[4700, 4799]],\n\n      15: [[3900, 3999]],\n\n      16: [[4400, 4499]],\n\n      17: [[3300, 3399]],\n\n      18: [[3500, 3599]],\n\n      19: [[4600, 4649]],\n\n      20: [[4100, 4199]],\n\n      21: [[4800, 4899]],\n\n      22: [[4000, 4049]],\n\n      23: [[3700, 3799]],\n\n      24: [[4300, 4349]],\n\n      27: [[3800, 3849]],\n\n      30: [[2900, 2949]],\n\n      35: [[2400, 2499]],\n\n      38: [[9000, 9499]],\n\n      88: [[8800, 8805]], // Bank of China, see https://www.paymentsnz.co.nz/resources/industry-registers/bank-branch-register/\n    },\n  },\n\n  {\n    key: \"D\",\n    branches: {\n      \"08\": [[6500, 6599]],\n    },\n  },\n\n  {\n    key: \"F\",\n    branches: {\n      25: [[2500, 2599]],\n    },\n  },\n\n  {\n    key: \"X\",\n    branches: {\n      31: [[2800, 2849]],\n    },\n  },\n];\n\nconst bankChecksums: BankChecksums = {\n  A: {\n    weighting: [0, 0, 6, 3, 7, 9, 0, 0, 10, 5, 8, 4, 2, 1, 0, 0, 0, 0],\n    modulo: 11,\n  },\n\n  B: {\n    weighting: [0, 0, 0, 0, 0, 0, 0, 0, 10, 5, 8, 4, 2, 1, 0, 0, 0, 0],\n    modulo: 11,\n  },\n\n  C: {\n    weighting: [3, 7, 0, 0, 0, 0, 9, 1, 10, 5, 3, 4, 2, 1, 0, 0, 0, 0],\n    modulo: 11,\n  },\n\n  D: {\n    weighting: [0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0],\n    modulo: 11,\n  },\n\n  E: {\n    weighting: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, 3, 2, 0, 0, 0, 1],\n    modulo: 11,\n    specialCase: true,\n  },\n\n  F: {\n    weighting: [0, 0, 0, 0, 0, 0, 0, 1, 7, 3, 1, 7, 3, 1, 0, 0, 0, 0],\n    modulo: 10,\n  },\n\n  G: {\n    weighting: [0, 0, 0, 0, 0, 0, 0, 1, 3, 7, 1, 3, 7, 1, 0, 3, 7, 1],\n    modulo: 10,\n    specialCase: true,\n  },\n\n  X: {\n    weighting: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n    modulo: 1,\n  },\n};\n\nexport { partConstants, partIndexes, partMaxLengths, bankData, bankChecksums };\n","import { partMaxLengths } from \"./constants\";\nimport type { PartMaxLengths } from \"./models\";\n\nconst isString = (x: unknown): x is string => x === x + \"\";\n\nconst isNumbersOnly = (x: string | undefined): boolean =>\n  !!x && /^[0-9]+$/.test(x);\n\nconst padLeft = (input: string | number, length: number, token = \"0\"): string =>\n  Array(length - String(input).length + 1).join(token) + input;\n\nconst inRange = (start: number, value: number, end: number): boolean =>\n  value >= start && value <= end;\n\nconst inRanges = (\n  value: number,\n  ranges: Array<[number, number]> = []\n): boolean => {\n  return ranges.reduce((bool, range) => {\n    const [start, end] = range;\n\n    return bool || inRange(start, value, end);\n  }, false);\n};\n\nconst sumChars = (int: number): number => {\n  return (int + \"\").split(\"\").reduce((acc, num) => {\n    return acc + parseInt(num, 10);\n  }, 0);\n};\n\nconst getPaddedAccountArray = (partsObj: Record<string, string>): string[] => {\n  return Object.keys(partsObj).reduce((a, k) => {\n    const key = k as keyof PartMaxLengths;\n    const paddedValue = padLeft(partsObj[k], partMaxLengths[key]);\n    const splitValues = paddedValue.split(\"\");\n\n    return a.concat(splitValues);\n  }, [] as string[]);\n};\n\nexport {\n  isString,\n  isNumbersOnly,\n  padLeft,\n  inRange,\n  inRanges,\n  sumChars,\n  getPaddedAccountArray,\n};\n","import {\n  partConstants,\n  partIndexes,\n  partMaxLengths,\n  bankData,\n  bankChecksums,\n} from \"./constants\";\n\nimport type { BankChecksum, BankData, PartsObject } from \"./models\";\n\nimport {\n  isString,\n  isNumbersOnly,\n  padLeft,\n  inRanges,\n  sumChars,\n  getPaddedAccountArray,\n} from \"./utils\";\n\nfunction isPartsObject(obj: unknown = {}): obj is PartsObject {\n  if (typeof obj !== \"object\" || obj === null) return false;\n  const inputsKeys = Object.keys(obj);\n  const requiredKeys = Object.keys(partConstants);\n  const filteredKeys = requiredKeys.filter((k) => inputsKeys.includes(k));\n\n  return requiredKeys.length === filteredKeys.length;\n}\n\nconst bankAccountValidator = {\n  getId(input: string | PartsObject): string {\n    return this.getPartsObject(input).id;\n  },\n  getBranch(input: string | PartsObject): string {\n    return this.getPartsObject(input).branch;\n  },\n  getBase(input: string | PartsObject): string {\n    return this.getPartsObject(input).base;\n  },\n  getSuffix(input: string | PartsObject): string {\n    return this.getPartsObject(input).suffix;\n  },\n\n  splitString(str = \"\"): string[] {\n    const parts = isString(str) ? str.split(/[^0-9]/) : [];\n\n    // If the input string had no delimiters, and its length is\n    // long enough, manually forge an array.\n    if (parts.length === 1) {\n      parts[0] = str.slice(0, 2);\n      parts[1] = str.slice(2, 5);\n      parts[2] = str.slice(5, 12);\n      parts[3] = str.slice(12);\n    }\n\n    return parts.filter((i) => i.length);\n  },\n\n  getPartsObject(input: string | PartsObject): PartsObject {\n    if (isPartsObject(input)) {\n      return input;\n    }\n\n    if (!isString(input)) {\n      return {} as PartsObject;\n    }\n\n    const parts = this.splitString(input);\n\n    return {\n      id: parts[partIndexes.id],\n      branch: parts[partIndexes.branch],\n      base: parts[partIndexes.base],\n      suffix: parts[partIndexes.suffix],\n    };\n  },\n\n  partsObjectValid(obj: Partial<PartsObject> = {}): boolean {\n    const keys = Object.keys(obj);\n\n    if (keys.length !== 4) {\n      return false;\n    }\n\n    return keys.reduce((isValid, key) => {\n      const value = obj[key as keyof PartsObject];\n      const onlyNumbers = isNumbersOnly(value);\n      const withinMaxLength =\n        isString(value) &&\n        value.length <= partMaxLengths[key as keyof PartsObject];\n      const valueValid = onlyNumbers && withinMaxLength;\n\n      return isValid && valueValid;\n    }, true);\n  },\n\n  validate(input: string | PartsObject): boolean {\n    const partsObject = this.getPartsObject(input);\n\n    if (!this.partsObjectValid(partsObject)) {\n      return false;\n    }\n\n    const { id, branch, base } = partsObject;\n\n    const bankDataEntry = this.getBankData(id, branch);\n\n    if (!bankDataEntry) {\n      return false;\n    }\n\n    const algorithm = this.getChecksum(bankDataEntry, base);\n\n    if (!algorithm) {\n      return false;\n    }\n\n    const { weighting, modulo, specialCase } = algorithm;\n\n    const earlyExit = !specialCase;\n\n    const result = getPaddedAccountArray(partsObject).reduce(\n      (result, num, idx) => {\n        const multiplied = parseInt(num, 10) * weighting[idx];\n\n        if (earlyExit || multiplied < 10) {\n          return result + multiplied;\n        }\n\n        const summed = sumChars(multiplied);\n        const summedTwice = sumChars(summed);\n        const final = summed < 10 ? summed : summedTwice;\n\n        return result + final;\n      },\n      0\n    );\n\n    // Final modulo test\n    return result % modulo === 0;\n  },\n\n  getBankData(id: string, branch: string): BankData | undefined {\n    const paddedId = padLeft(id, partMaxLengths.id);\n\n    return bankData.find((r) => {\n      r.branches;\n      const ranges = r.branches[paddedId];\n\n      return ranges && inRanges(parseInt(branch, 10), ranges);\n    });\n  },\n\n  getChecksum(bankData: BankData, base: string): BankChecksum | undefined {\n    let { key } = bankData;\n\n    if (key === \"AB\") {\n      key = parseInt(base, 10) < 990000 ? \"A\" : \"B\";\n    }\n\n    return bankChecksums[key];\n  },\n};\n\nexport default bankAccountValidator;\n"],"names":["partConstants","id","branch","base","suffix","partMaxLengths","bankData","key","branches","bankChecksums","A","weighting","modulo","B","C","D","E","specialCase","F","G","X","isString","x","padLeft","input","length","token","Array","String","join","sumChars","int","split","reduce","acc","num","parseInt","bankAccountValidator","getId","getPartsObject","getBranch","this","getBase","getSuffix","splitString","str","parts","slice","filter","i","obj","inputsKeys","Object","keys","requiredKeys","filteredKeys","k","includes","isPartsObject","partsObjectValid","isValid","value","onlyNumbers","test","withinMaxLength","valueValid","validate","partsObject","bankDataEntry","getBankData","algorithm","getChecksum","earlyExit","partsObj","a","splitValues","concat","result","idx","multiplied","summed","summedTwice","final","paddedId","find","r","ranges","inRanges","bool","range","start","end","inRange"],"mappings":"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"}