Skip to Content
LuhnAPI Reference

Ahead of the release

npm install @evanion/luhn gives you 3.0.0. These pages document main, which has changes that release does not.

API reference

createLuhn(options?)

function createLuhn(options?: LuhnOptions): Luhn;

Validates the dictionary and returns a frozen Luhn.

OptionTypeDefault
dictionarystringDEFAULT_DICTIONARY
caseInsensitivebooleantrue when dictionary is omitted, false when it is given

Throws InvalidDictionaryError when the dictionary fails one of the five constraints.

The returned object

interface Luhn { readonly dictionary: string; readonly n: number; readonly caseInsensitive: boolean; readonly uniformOverBytes: boolean; generate(input: string): GenerateResult; validate(input: string): ValidateResult; }
MemberMeaning
dictionarythe alphabet, as supplied
nthe modulus: code points in the dictionary
caseInsensitivewhether input is folded to lowercase before lookup
uniformOverByteswhether n divides 256, so byte % n draws uniformly
generatecomputes the check character
validatechecks a string whose last dictionary character is the check

Object.freezed, so luhn.dictionary = x throws a TypeError in a module rather than being accepted and ignored.

generate(input)

interface GenerateResult { phrase: string; // input with non-dictionary code points removed checksum: string; // the check character filtered: number; // how many code points were dropped }

Throws EmptyInputError when no code point of input is in the dictionary.

phrase does not include checksum — the check character did not exist when the phrase was read.

validate(input)

interface ValidateResult { phrase: string; // input with non-dictionary code points removed isValid: boolean; filtered: number; }

Never throws. isValid is false for fewer than two surviving code points.

phrase here does include the check character, because that is what was validated.

Constants

ExportValue
LuhncreateLuhn(), frozen — the default instance
DEFAULT_DICTIONARY'0123456789abcdefghijklmnopqrstuvwxyz' — 36 characters
ALTERNATING_CASE_DICTIONARY62 characters: 0-9 then Aa Bb … Zz, case-sensitive

Luhn names the interface in type space and the default instance in value space, so const luhn: Luhn = Luhn resolves both.

Types

LuhnOptions, GenerateResult, ValidateResult, InvalidDictionaryReason, and the Luhn interface above.

type InvalidDictionaryReason = 'not-a-string' | 'too-short' | 'odd-length' | 'duplicate' | 'case-pairs';

Errors

LuhnError

Base class for everything the library throws. Catch it to handle any failure without naming the subclasses.

The name is package-specific rather than a generic ValidationError, so it cannot collide with the one @evanion/urn exports in a consumer’s import list. The two hierarchies are unrelated and share no base.

InvalidDictionaryError extends LuhnError

Raised by createLuhn. One class carrying a reason rather than one class per constraint, so a caller that only wants to know whether a dictionary is acceptable writes one catch arm.

PropertyMeaning
reasonwhich constraint failed
dictionarythe dictionary as supplied
offendingthe code points the constraint named; empty for the whole-dictionary ones
try { createLuhn({ dictionary: 'aabbccdd' }); } catch (error) { if (error instanceof InvalidDictionaryError) { error.reason; // 'duplicate' error.offending; // ['a', 'b', 'c', 'd'] } }

For case-pairs, offending holds each pair joined into one string — 'Aa', 'Bb'. For not-a-string, too-short and odd-length it is empty, because those are properties of the dictionary as a whole.

EmptyInputError extends LuhnError

Raised by generate when nothing survived the filter. It is the only error either operation can raise — every other constraint was settled at construction.

Last updated on