e164-compact
v0.1.1
Published
Zero-dependency E.164 storage helpers: normalize, strict parse, national length checks, multi-locale country picker data (TypeScript, ESM+CJS).
Maintainers
Readme
e164-compact
Zero runtime dependencies. Helpers for compact E.164 storage (+ + country calling code + national digits without a leading national zero), syntax checks aligned with common international practice, national length checks against embedded coarse ranges (with optional hand-tuned overrides), and picker data with English default labels plus bundled partial translations (Arabic, French, Spanish, German, Portuguese, Urdu, Hindi, Turkish, Russian).
If your GitHub repo URL differs from /e164-compact, update repository / homepage in package.json and the badge URLs above so npm and CI badges stay accurate.
Why this package
| Need | e164-compact | Heavier full-feature phone stacks |
| ------------------- | ------------------------------------------------- | ---------------------------------------------- |
| Install size / tree | Small, no runtime deps | Often large metadata + parsing logic |
| Goal | Normalize + validate shape/length for storage | Full carrier/type rules, formatting everywhere |
| Data in repo | Plain src/data/*.ts you can PR | Often generated blobs or vendored copies |
Use this when you want a predictable normalization path for APIs and databases, optional strict errors for bad input, and country picker rows without pulling a full phone-number engine.
Install
npm
npm install e164-compactpnpm
pnpm add e164-compactYarn
yarn add e164-compactUntil published, link from a monorepo sibling:
"e164-compact": "file:../e164-compact"Quick start
import {
normalizeE164,
tryNormalizeE164,
isNationalLengthValidStrict,
} from "e164-compact";
// Lenient (UX): always returns a string starting with +
const stored = normalizeE164("00971 50 123 4567");
// Strict (APIs): ok / error
const strict = tryNormalizeE164("00971 50 123 4567");
if (strict.ok && isNationalLengthValidStrict(strict.value)) {
// persist strict.value
}Validation helper (no extra packages)
import { tryNormalizeE164, isNationalLengthValidStrict } from "e164-compact";
export function assertStorageE164(raw: string): string {
const n = tryNormalizeE164(raw);
if (!n.ok) throw new Error(n.error);
if (!isNationalLengthValidStrict(n.value)) {
throw new Error("National number length out of range for this country code");
}
return n.value;
}Wire this into your own form or API layer however you prefer.
Bundle footprint
Published tarball includes dist/ (ESM + CJS + types) and NOTICE. There is no separate runtime dependency tree. Measure unpacked size under node_modules/e164-compact/dist after install if you need exact bytes.
API overview
| Export | Description |
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| normalizeE164(input) | Lenient storage form; strips leading national zero after CC. If no known calling code matches, returns + + stripped digits. |
| tryNormalizeE164(input) | Strict: ok / error — fails on unknown calling code or empty national after strip. |
| parseE164Parts(value) | { countryCallingCode, nationalNumber }. Lenient: non-+ or unknown prefix uses fallback 971. |
| tryParseE164Parts(value) | Strict: requires +, known CC, non-empty national. |
| buildE164(cc, nationalDigits) | Build +cc + national. |
| isE164Syntax(value) | + + 1…15 digits, first digit after + is 1–9. |
| isNationalLengthValid(value) | National length vs bounds (lenient parse). |
| isNationalLengthValidStrict(value) | Same with strict parse. |
| getNationalLengthBounds(cc) | { min, max } for form messages. |
| formatE164ForDisplay(value, opts?) | Spacing for display only. |
| filterSupportedCountries(countries, query) | Match code, label, or cca2. |
| localizeSupportedCountryLabels(countries, byCca2) | Set label from cca2 → name map. |
| withLocalePickerLabels(countries, map) | Alias of localizeSupportedCountryLabels. |
| withArabicPickerLabels(countries) | Applies bundled Arabic map. |
| SUPPORTED_COUNTRIES | { code, label, cca2 }[] — default English label. |
| COUNTRY_LABELS_BY_LOCALE | ar, fr, es, de, pt, ur, hi, tr, ru → partial cca2 maps. |
| COUNTRY_LABELS_AR, …_FR, …_ES, … | Individual partial maps (same as values in COUNTRY_LABELS_BY_LOCALE). |
| CALLING_CODE_PREFIXES | 206 unique CC digit prefixes, longest first. |
| NATIONAL_LENGTH_BOUNDS | Embedded coarse ranges merged with MANUAL_NATIONAL_LENGTH_OVERRIDES. |
| MANUAL_NATIONAL_LENGTH_OVERRIDES | Stricter overrides where you need them (e.g. GCC). |
| DEFAULT_NATIONAL_LENGTH_BOUNDS | Fallback { min: 7, max: 12 }. |
Locales
- English is the default on
SUPPORTED_COUNTRIES[].label. - Other languages are partial: some territories may be missing in a given map; missing keys keep the English row unchanged.
- Hindi (
hi) may be sparse in the bundled map; supply your own map vialocalizeSupportedCountryLabelsif needed.
Example:
import {
SUPPORTED_COUNTRIES,
withLocalePickerLabels,
COUNTRY_LABELS_BY_LOCALE,
} from "e164-compact";
const frRows = withLocalePickerLabels(
SUPPORTED_COUNTRIES,
COUNTRY_LABELS_BY_LOCALE.fr as Record<string, string>,
);Lenient vs strict
parseE164Parts/normalizeE164favor forgiving form UX.tryParseE164Parts/tryNormalizeE164suit APIs and validation where silent guessing is undesirable.
Troubleshooting
tryNormalizeE164fails on valid-looking numbers — The library only accepts known ITU-style calling-code prefixes from embedded data. Updatesrc/data/itu-calling-data.tsif a prefix is missing.isNationalLengthValidStrictis false — Length tables are coarse; tunesrc/manual-national-overrides.tsorsrc/data/national-length-bounds.tsfor your region.- Wrong country after paste — Lenient APIs may infer CC from digits; use strict APIs for unambiguous validation.
Contributing / updating data
All dialing prefixes, picker rows, length tables, and locale maps live under src/data/ as normal source files. Updates are done by editing those modules and opening a PR (see CONTRIBUTING.md). Hand-tuned national length overrides remain in src/manual-national-overrides.ts.
Changelog
See CHANGELOG.md.
License
MIT. See NOTICE for third-party data attribution required by upstream licenses.
