@evanion/luhn
@evanion/luhn 3.0.0 and its patch releases up to 3.0.2, the version on npm. Values on this page were produced by running the source at f9b1d93, a later commit than the 3.0.0 tag, and are not re-executed.
Prevent database pollution and user frustration with an industry-standard check-character system.
A customer reads an order code back over the phone, and one digit comes out wrong. Without a check character, your system performs a database lookup and returns “Order not found.” The user is frustrated, and the staff doesn’t know if the code was mistyped or if the order truly doesn’t exist.
@evanion/luhn solves this by appending a single check character to your codes. This allows your application to validate the code’s integrity locally before your database is ever asked.
The Problem: The “Silent Typo”
In most systems, an ID is just a string. If a user types order-2026-0043 instead of order-2026-0042, the system treats it as a perfectly valid request for a non-existent resource.
This leads to:
- Wasted Resources: Every mistyped ID triggers an unnecessary database query.
- Poor User Experience: The user receives a “Not Found” error and has no way of knowing they simply mistyped a single character.
- Support Overhead: Staff must manually verify the order, as they cannot tell the difference between a typo and a missing record.
The Solution: The Luhn Algorithm
@evanion/luhn implements the Luhn algorithm—the same system used by credit cards globally—to detect transcription errors. It computes a single character based on the rest of the code; if any character is changed or almost any two neighbours are swapped, the checksum will no longer match.
For example, the order number order-2026-0042 results in a check character of l. The final code becomes order-2026-0042-l.
import { } from '@evanion/luhn';
.('order-2026-0042-l').; // -> true
.('order-2026-0043-l').; // -> false
.('order-2026-0024-l').; // -> falseIf a user types order-2026-0043-l (one digit changed) or order-2026-0024-l (two digits swapped), Luhn.validate immediately returns isValid: false. The request is rejected before it ever reaches your database.
How it Works: The Luhn Sum
The check character is calculated through a process called the Luhn sum:
- Phrase Extraction: Every character outside the chosen dictionary is dropped, and uppercase is folded to lowercase.
ORDER 2026 0042becomesorder20260042. - Index Mapping: Each character is replaced by its index in the dictionary (e.g.,
o24). - The Doubling Step: Starting with the rightmost character, every other index is doubled. If the result exceeds the dictionary size, its digits (in the dictionary’s base) are added together.
- Summation: All values are added together to create the Luhn sum.
- Final Character: The check character is the one whose index brings the total sum to the nearest multiple of the dictionary size.
Core Capabilities
| Goal | Tool |
|---|---|
| Add a check character to a code | Luhn.generate(code).checksum |
| Validate a code’s integrity | Luhn.validate(code).isValid |
| Support flexible input | Both calls ignore case and separators (non-dictionary chars) |
| Custom alphabets | createLuhn({ dictionary }) builds a custom instance |
| Credit card validation | createLuhn({ dictionary: '0123456789' }) |
What a Check Character Catches (and What it Doesn’t)
@evanion/luhn is a tool for error detection, not security.
It catches:
- Every single-character substitution: If one character is replaced by another, the checksum will fail.
- Almost every adjacent swap: If two neighboring characters are swapped, it is caught (except for a swap of the dictionary’s first and last characters, e.g.,
0andz).
It does NOT:
- Prove existence: A random string can pass the Luhn check (1 in 36 chance). You still need a database to verify the code was actually issued.
- Provide authentication: The algorithm is public. Anyone can compute a valid check character for any string.
- Choose the ID: This library only provides the checksum. Use
@evanion/tokenif you need to generate random, human-readable IDs.
Install and Issue Your First Code
Now that you understand how the Luhn sum prevents “silent typos,” you can implement it in your project. Getting started shows you how to install the package and write a function that appends check characters to your order numbers.