Skip to content

hasansmadix/e164-compact

Repository files navigation

e164-compact

CI npm version license

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-compact

pnpm

pnpm add e164-compact

Yarn

yarn add e164-compact

Until 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 via localizeSupportedCountryLabels if 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 / normalizeE164 favor forgiving form UX.
  • tryParseE164Parts / tryNormalizeE164 suit APIs and validation where silent guessing is undesirable.

Troubleshooting

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.

About

Zero-dependency E.164 storage helpers: normalize, strict parse, national length checks, multi-locale country picker data (TypeScript, ESM+CJS).

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors