Files
skills/docs/communication/messaging/sms/src/validation/phone.md
2026-05-29 08:20:56 +01:00

2.2 KiB

validation/phone

(no submodules)

Purpose

validation/phone is the strict-E.164 phone number validator used by every public input boundary in @suaveplan/sms. The validator implements the ITU-T E.164 grammar verbatim — a single leading +, a first digit in [1-9], then one to fourteen trailing decimal digits — and exposes both the regex constant and the predicate so callers can compose either against their own pipelines.

The module is intentionally tiny: a single regex and a single boolean function. Centralising the rule here keeps the spec a single source of truth — the service, the Zod schemas, and the test fixtures all use the same predicate.

Features

  • E164_REGEX — exported regex constant for downstream composition.
  • isValidE164(value) — boolean predicate, returns true only for syntactically valid E.164 numbers.
  • Strict format: rejects bare digits without leading +, rejects + alone, rejects +0…, rejects letters, rejects numbers longer than 15 total digits.

Usage: Basic

import { isValidE164 } from "@suaveplan/sms/validation/phone";

isValidE164("+15551234567"); // true
isValidE164("15551234567"); // false (no leading +)
isValidE164("+0123456789"); // false (first digit is 0)

Usage: Advanced

import { E164_REGEX } from "@suaveplan/sms/validation/phone";
import z from "zod";

const PhoneSchema = z
    .string()
    .regex(E164_REGEX, "must be an E.164 phone number")
    .transform((value) => value.toUpperCase());

API Reference

  • const E164_REGEX: RegExp — ^\+[1-9]\d{1,14}$ (frozen by TypeScript's const semantics).
  • function isValidE164(value: string): boolean — returns E164_REGEX.test(value).

Implementation Notes

The validator does NOT consult a country-code prefix table: it checks only the syntactic shape required by E.164. Higher-layer validation (carrier routing, prefix-to-country mapping, toll-free / premium-rate filters) lives in @suaveplan/sms-providers per-provider adapters because the rule set varies by carrier. Keeping the syntactic predicate cheap means a hot path through SmsService.send can call isValidE164 once per send without measurable overhead.