first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
# `validation/phone`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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
```ts
import { isValidE164 } from "@suaveplan/sms/validation/phone";
isValidE164("+15551234567"); // true
isValidE164("15551234567"); // false (no leading +)
isValidE164("+0123456789"); // false (first digit is 0)
```
## Usage: Advanced
```ts
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.