-
Notifications
You must be signed in to change notification settings - Fork 42
refactor: extract alphabetToNumber helper, optimize SSN blacklist lookup #157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,7 +17,7 @@ import * as exceptions from '../exceptions'; | |
| import { strings } from '../util'; | ||
| import { Validator, ValidateReturn } from '../types'; | ||
|
|
||
| const invalidSSN = [ | ||
| const invalidSSNSet = new Set([ | ||
| '111111111', | ||
| '222222222', | ||
| '333333333', | ||
|
|
@@ -27,7 +27,6 @@ const invalidSSN = [ | |
| '888888888', | ||
| '999999999', | ||
| '123123123', | ||
| '999999999', | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While removing the duplicate |
||
| // Used in Advertising and known "invalid" | ||
| '002281852', | ||
| '042103580', | ||
|
|
@@ -51,7 +50,7 @@ const invalidSSN = [ | |
| '457555462', | ||
| '468288779', | ||
| '549241889', | ||
| ]; | ||
| ]); | ||
|
|
||
| function clean(input: string): ReturnType<typeof strings.cleanUnicode> { | ||
| return strings.cleanUnicode(input, '- '); | ||
|
|
@@ -94,7 +93,7 @@ const impl: Validator = { | |
| if (!strings.isdigits(value)) { | ||
| return { isValid: false, error: new exceptions.InvalidComponent() }; | ||
| } | ||
| if (invalidSSN.includes(value)) { | ||
| if (invalidSSNSet.has(value)) { | ||
| return { isValid: false, error: new exceptions.InvalidComponent() }; | ||
| } | ||
| if (/^(000|666|9)\d+/.test(value)) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -80,7 +80,6 @@ export function luhnChecksumValidate( | |||||||||||||||||
|
|
||||||||||||||||||
| const sum = value | ||||||||||||||||||
| .split('') | ||||||||||||||||||
| // .reverse() | ||||||||||||||||||
| .map(v => alphabet.indexOf(v)) | ||||||||||||||||||
| .reduce((acc, val, idx) => { | ||||||||||||||||||
| let v = val; | ||||||||||||||||||
|
|
@@ -213,32 +212,36 @@ function modulo(dividentIn: string, divisor: number) { | |||||||||||||||||
| return parseInt(divident, 10) % divisor; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| /** | ||||||||||||||||||
| * Convert a string using alphanumeric alphabet to its numeric representation. | ||||||||||||||||||
| * Returns null if any character is not in the alphabet. | ||||||||||||||||||
| */ | ||||||||||||||||||
| function alphabetToNumber( | ||||||||||||||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this feels needless. |
||||||||||||||||||
| value: string, | ||||||||||||||||||
| alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', | ||||||||||||||||||
| ): string | null { | ||||||||||||||||||
|
Comment on lines
+219
to
+222
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the PR description mentions that this helper is intended to be reused by other functions/modules that need alphanumeric-to-numeric conversion, it should be exported so that other files can import it.
Suggested change
|
||||||||||||||||||
| let result = ''; | ||||||||||||||||||
| for (const c of value) { | ||||||||||||||||||
| const idx = alphabet.indexOf(c); | ||||||||||||||||||
| if (idx === -1) { | ||||||||||||||||||
| return null; | ||||||||||||||||||
| } | ||||||||||||||||||
| result += String(idx); | ||||||||||||||||||
| } | ||||||||||||||||||
| return result; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| /** | ||||||||||||||||||
| * The ISO 7064 Mod 97, 10 algorithm. | ||||||||||||||||||
| * | ||||||||||||||||||
| * The Mod 97, 10 algorithm evaluates the whole number as an integer which is | ||||||||||||||||||
| * valid if the number modulo 97 is 1. As such it has two check digits. | ||||||||||||||||||
| */ | ||||||||||||||||||
| export function mod97base10Validate(value: string, expect = 1): boolean { | ||||||||||||||||||
| const alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; | ||||||||||||||||||
| let fail = false; | ||||||||||||||||||
|
|
||||||||||||||||||
| const bigValue = value | ||||||||||||||||||
| .split('') | ||||||||||||||||||
| .map(c => { | ||||||||||||||||||
| const idx = alphabet.indexOf(c); | ||||||||||||||||||
| if (idx === -1) { | ||||||||||||||||||
| fail = true; | ||||||||||||||||||
| return ''; | ||||||||||||||||||
| } | ||||||||||||||||||
| return String(idx); | ||||||||||||||||||
| }) | ||||||||||||||||||
| .join(''); | ||||||||||||||||||
|
|
||||||||||||||||||
| if (fail) { | ||||||||||||||||||
| const bigValue = alphabetToNumber(value); | ||||||||||||||||||
| if (bigValue === null) { | ||||||||||||||||||
| return false; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| return modulo(bigValue, 97) === expect; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will note that if this is a performance optimization, that object keys are the fastest with a
if (value in invalidSSN) {as the check will out performSet().