npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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).

Readme

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.