phoneshield 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +430 -0
  3. package/dist/au.d.ts +7 -0
  4. package/dist/au.js +4 -0
  5. package/dist/au.js.map +1 -0
  6. package/dist/ca.d.ts +7 -0
  7. package/dist/ca.js +4 -0
  8. package/dist/ca.js.map +1 -0
  9. package/dist/chunk-5TMYOORT.js +40 -0
  10. package/dist/chunk-5TMYOORT.js.map +1 -0
  11. package/dist/chunk-7S4ACFFA.js +45 -0
  12. package/dist/chunk-7S4ACFFA.js.map +1 -0
  13. package/dist/chunk-DCA72IND.js +47 -0
  14. package/dist/chunk-DCA72IND.js.map +1 -0
  15. package/dist/chunk-KG5T34UR.js +196 -0
  16. package/dist/chunk-KG5T34UR.js.map +1 -0
  17. package/dist/chunk-NEZI6CET.js +38 -0
  18. package/dist/chunk-NEZI6CET.js.map +1 -0
  19. package/dist/chunk-R4Y2UNHW.js +40 -0
  20. package/dist/chunk-R4Y2UNHW.js.map +1 -0
  21. package/dist/chunk-UHUCGGQT.js +47 -0
  22. package/dist/chunk-UHUCGGQT.js.map +1 -0
  23. package/dist/chunk-ZHU56JDV.js +38 -0
  24. package/dist/chunk-ZHU56JDV.js.map +1 -0
  25. package/dist/chunk-ZN7XDKND.js +40 -0
  26. package/dist/chunk-ZN7XDKND.js.map +1 -0
  27. package/dist/de.d.ts +7 -0
  28. package/dist/de.js +4 -0
  29. package/dist/de.js.map +1 -0
  30. package/dist/fr.d.ts +7 -0
  31. package/dist/fr.js +4 -0
  32. package/dist/fr.js.map +1 -0
  33. package/dist/in.d.ts +7 -0
  34. package/dist/in.js +4 -0
  35. package/dist/in.js.map +1 -0
  36. package/dist/index.d.ts +41 -0
  37. package/dist/index.js +112 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/jp.d.ts +7 -0
  40. package/dist/jp.js +4 -0
  41. package/dist/jp.js.map +1 -0
  42. package/dist/react.js +570 -0
  43. package/dist/react.js.map +1 -0
  44. package/dist/types-CbWYeYFP.d.ts +31 -0
  45. package/dist/uk.d.ts +7 -0
  46. package/dist/uk.js +4 -0
  47. package/dist/uk.js.map +1 -0
  48. package/dist/us.d.ts +7 -0
  49. package/dist/us.js +4 -0
  50. package/dist/us.js.map +1 -0
  51. package/package.json +97 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 PhoneShield
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,430 @@
1
+ # PhoneShield
2
+
3
+ A lightning-fast, privacy-first phone intelligence engine. A smarter, tree-shakable alternative to `libphonenumber-js` and `numverify` — works everywhere JavaScript runs: **Node.js, browsers, React, Vue, Svelte, plain HTML**.
4
+
5
+ ## Features
6
+
7
+ - **< 5KB per country** — ESM-first, tree-shakable. Import only what you need.
8
+ - **Framework-agnostic** — Core engine has zero dependencies. Use it in Node, Deno, Bun, or any frontend framework.
9
+ - **Hybrid validation** — Local regex + length checks, no network calls required.
10
+ - **"Did You Mean?"** — Suggests corrections when a number is off by 1–2 digits.
11
+ - **Intelligence schema** — Returns `isValid`, E.164 `format`, `country`, `lineType`, and `riskScore`.
12
+ - **Privacy-first** — SHA-256 hashing for zero-knowledge spam database lookups.
13
+ - **Real-time formatting** — Built-in stateful formatter with debounce (framework-agnostic).
14
+ - **Optional React hook** — `usePhoneShield` available via `phoneshield/react` (React is never required).
15
+ - **TypeScript native** — Full type safety and IntelliSense out of the box.
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install phoneshield
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ### Country-Specific Validation (Tree-Shakable)
26
+
27
+ Import only the country you need — each entry point pulls in just that country's metadata:
28
+
29
+ ```typescript
30
+ import { validateUS } from 'phoneshield/us';
31
+
32
+ const result = validateUS('(202) 555-1234');
33
+ // {
34
+ // isValid: true,
35
+ // format: '+12025551234',
36
+ // country: 'US',
37
+ // lineType: 'Mobile',
38
+ // riskScore: 0.0
39
+ // }
40
+ ```
41
+
42
+ ### Multi-Country
43
+
44
+ ```typescript
45
+ import { validateUS } from 'phoneshield/us';
46
+ import { validateUK } from 'phoneshield/uk';
47
+ import { validateFR } from 'phoneshield/fr';
48
+ import { validateIN } from 'phoneshield/in';
49
+
50
+ validateUS('2025551234');
51
+ validateUK('7400123456');
52
+ validateFR('612345678');
53
+ validateIN('9876543210');
54
+ ```
55
+
56
+ ### Generic Validation (Any Country)
57
+
58
+ ```typescript
59
+ import { validate, getMetadata } from 'phoneshield';
60
+
61
+ const metadata = getMetadata('DE');
62
+ const result = validate('15112345678', metadata, {
63
+ enableSuggestions: true,
64
+ });
65
+ ```
66
+
67
+ ## Supported Countries
68
+
69
+ | Code | Country | Dial Code | Import Path |
70
+ | ---- | ------- | --------- | ----------- |
71
+ | US | United States | +1 | `phoneshield/us` |
72
+ | CA | Canada | +1 | `phoneshield/ca` |
73
+ | UK | United Kingdom | +44 | `phoneshield/uk` |
74
+ | AU | Australia | +61 | `phoneshield/au` |
75
+ | DE | Germany | +49 | `phoneshield/de` |
76
+ | FR | France | +33 | `phoneshield/fr` |
77
+ | JP | Japan | +81 | `phoneshield/jp` |
78
+ | IN | India | +91 | `phoneshield/in` |
79
+
80
+ ## Validation Result Schema
81
+
82
+ Every validation call returns a `ValidationResult`:
83
+
84
+ ```typescript
85
+ interface ValidationResult {
86
+ isValid: boolean; // Pass/fail
87
+ format: string | null; // E.164 format (e.g. "+12025551234")
88
+ country: CountryCode | null; // "US", "UK", "FR", etc.
89
+ lineType: LineType; // "Mobile" | "Landline" | "VoIP" | "TollFree" | "Premium" | "Unknown"
90
+ riskScore: number; // 0.0 (safe) to 1.0 (high risk)
91
+ suggestion?: string; // "Did you mean (202) 555-1234?"
92
+ errors?: string[]; // Human-readable error messages
93
+ }
94
+ ```
95
+
96
+ ## "Did You Mean?" Engine
97
+
98
+ When a number is off by 1–2 digits, PhoneShield suggests the closest valid number:
99
+
100
+ ```typescript
101
+ import { validateUS } from 'phoneshield/us';
102
+
103
+ const result = validateUS('202555123'); // 9 digits instead of 10
104
+ console.log(result.isValid); // false
105
+ console.log(result.suggestion); // "(202) 555-1234"
106
+ ```
107
+
108
+ ## Risk Scoring
109
+
110
+ PhoneShield scores numbers from `0.0` (safe) to `1.0` (high risk) based on:
111
+
112
+ - **Invalid format/length** — +0.5
113
+ - **Premium numbers** (e.g. 900) — +0.3
114
+ - **VoIP numbers** — +0.2
115
+ - **Unknown line type** — +0.25
116
+ - **Repeating digits** (e.g. 5555555) — +0.15
117
+ - **Sequential patterns** (e.g. 123456) — +0.1
118
+ - **Suspicious prefixes** (000, 999) — +0.2
119
+
120
+ ```typescript
121
+ import { validateUS } from 'phoneshield/us';
122
+
123
+ const result = validateUS('9001234567');
124
+ console.log(result.riskScore); // 0.3 (Premium number)
125
+ console.log(result.lineType); // "Premium"
126
+ ```
127
+
128
+ ## Line Type Detection
129
+
130
+ ```typescript
131
+ import { validateUS } from 'phoneshield/us';
132
+
133
+ validateUS('2025551234').lineType; // "Mobile" or "Landline"
134
+ validateUS('8005551234').lineType; // "TollFree"
135
+ validateUS('9005551234').lineType; // "Premium"
136
+ ```
137
+
138
+ ## Privacy-First Hashing
139
+
140
+ Generate SHA-256 hashes to query spam databases without exposing the actual number:
141
+
142
+ ```typescript
143
+ import { hashPhoneNumber } from 'phoneshield';
144
+
145
+ const hash = await hashPhoneNumber('+12025551234');
146
+ // "a3f2b8c1..." — send this to your spam API, not the raw number
147
+ ```
148
+
149
+ Uses the Web Crypto API (browser + Node 18+). No external dependencies.
150
+
151
+ ## Real-Time Formatting (Framework-Agnostic)
152
+
153
+ The `createPhoneFormatter()` engine works in **any** JavaScript environment — no React, no framework needed:
154
+
155
+ ```typescript
156
+ import { createPhoneFormatter } from 'phoneshield';
157
+
158
+ const formatter = createPhoneFormatter('US', {
159
+ debounceMs: 300,
160
+ enableSuggestions: true,
161
+ onStateChange: (state) => {
162
+ console.log(state.formattedValue); // "(202) 555-1234"
163
+ console.log(state.validation); // ValidationResult or null
164
+ console.log(state.isValidating); // true/false
165
+ },
166
+ });
167
+
168
+ // Feed input as the user types
169
+ formatter.handleInput('2');
170
+ formatter.handleInput('20');
171
+ formatter.handleInput('202');
172
+ formatter.handleInput('2025551234');
173
+
174
+ // Read state at any time
175
+ const state = formatter.getState();
176
+
177
+ // Clean up
178
+ formatter.clear();
179
+ formatter.destroy();
180
+ ```
181
+
182
+ ### Usage with Vue
183
+
184
+ ```typescript
185
+ import { ref, onMounted, onUnmounted } from 'vue';
186
+ import { createPhoneFormatter } from 'phoneshield';
187
+
188
+ const formattedValue = ref('');
189
+ const validation = ref(null);
190
+
191
+ let formatter;
192
+
193
+ onMounted(() => {
194
+ formatter = createPhoneFormatter('FR', {
195
+ debounceMs: 250,
196
+ onStateChange: (state) => {
197
+ formattedValue.value = state.formattedValue;
198
+ validation.value = state.validation;
199
+ },
200
+ });
201
+ });
202
+
203
+ onUnmounted(() => formatter?.destroy());
204
+
205
+ function onInput(e) {
206
+ formatter?.handleInput(e.target.value);
207
+ }
208
+ ```
209
+
210
+ ### Usage with Svelte
211
+
212
+ ```typescript
213
+ import { createPhoneFormatter } from 'phoneshield';
214
+ import { onDestroy } from 'svelte';
215
+
216
+ let formattedValue = '';
217
+ let validation = null;
218
+
219
+ const formatter = createPhoneFormatter('DE', {
220
+ onStateChange: (state) => {
221
+ formattedValue = state.formattedValue;
222
+ validation = state.validation;
223
+ },
224
+ });
225
+
226
+ onDestroy(() => formatter.destroy());
227
+
228
+ function handleInput(e) {
229
+ formatter.handleInput(e.target.value);
230
+ }
231
+ ```
232
+
233
+ ### Usage in Node.js / Backend
234
+
235
+ ```typescript
236
+ import { validateUS } from 'phoneshield/us';
237
+ import { hashPhoneNumber } from 'phoneshield';
238
+
239
+ // Validate incoming phone number
240
+ const result = validateUS(req.body.phone);
241
+
242
+ if (!result.isValid) {
243
+ return res.status(400).json({ errors: result.errors });
244
+ }
245
+
246
+ // Store only the hash
247
+ const hash = await hashPhoneNumber(result.format);
248
+ await db.users.update({ phoneHash: hash });
249
+ ```
250
+
251
+ ## React Hook (Optional)
252
+
253
+ Install React as usual — it's an **optional** peer dependency. Import from the dedicated subpath:
254
+
255
+ ```typescript
256
+ import { usePhoneShield } from 'phoneshield/react';
257
+
258
+ function PhoneInput() {
259
+ const {
260
+ formattedValue,
261
+ validation,
262
+ isValidating,
263
+ handleChange,
264
+ clear,
265
+ } = usePhoneShield('US', { debounceMs: 300, enableSuggestions: true });
266
+
267
+ return (
268
+ <div>
269
+ <input
270
+ type="tel"
271
+ value={formattedValue}
272
+ onChange={(e) => handleChange(e.target.value)}
273
+ placeholder="(555) 123-4567"
274
+ />
275
+
276
+ {isValidating && <span>Validating...</span>}
277
+
278
+ {validation && (
279
+ <div>
280
+ <p>Valid: {validation.isValid ? 'Yes' : 'No'}</p>
281
+ <p>Type: {validation.lineType}</p>
282
+ <p>Risk: {(validation.riskScore * 100).toFixed(0)}%</p>
283
+ {validation.suggestion && (
284
+ <p>Did you mean: {validation.suggestion}?</p>
285
+ )}
286
+ </div>
287
+ )}
288
+
289
+ <button onClick={clear}>Clear</button>
290
+ </div>
291
+ );
292
+ }
293
+ ```
294
+
295
+ ## Formatting Utilities
296
+
297
+ ```typescript
298
+ import { normalizePhoneNumber, formatPhoneNumber, toE164 } from 'phoneshield';
299
+ import { US_METADATA } from 'phoneshield/us';
300
+
301
+ normalizePhoneNumber('(202) 555-1234');
302
+ // "2025551234"
303
+
304
+ formatPhoneNumber('2025551234', US_METADATA);
305
+ // "(202) 555-1234"
306
+
307
+ toE164('2025551234', US_METADATA);
308
+ // "+12025551234"
309
+ ```
310
+
311
+ ## Custom Country Metadata
312
+
313
+ Add your own country by implementing the `CountryMetadata` interface:
314
+
315
+ ```typescript
316
+ import { CountryMetadata, validate } from 'phoneshield';
317
+
318
+ const MY_METADATA: CountryMetadata = {
319
+ countryCode: 'MY' as any,
320
+ dialCode: '+60',
321
+ patterns: {
322
+ mobile: [/^1[0-46-9]\d{7,8}$/],
323
+ landline: [/^[3-9]\d{7}$/],
324
+ voip: [],
325
+ tollFree: [/^1800\d{6}$/],
326
+ premium: [],
327
+ },
328
+ lengths: [9, 10],
329
+ format: (digits) =>
330
+ digits.length === 10
331
+ ? `${digits.slice(0, 3)}-${digits.slice(3, 6)} ${digits.slice(6)}`
332
+ : digits,
333
+ };
334
+
335
+ const result = validate('123456789', MY_METADATA);
336
+ ```
337
+
338
+ ## API Reference
339
+
340
+ ### Core
341
+
342
+ | Function | Description |
343
+ | -------- | ----------- |
344
+ | `validate(input, metadata, options?)` | Full validation with intelligence schema |
345
+ | `validateUS(phone, options?)` | US-specific (tree-shakable) |
346
+ | `validateUK(phone, options?)` | UK-specific |
347
+ | `validateCA(phone, options?)` | Canada-specific |
348
+ | `validateAU(phone, options?)` | Australia-specific |
349
+ | `validateDE(phone, options?)` | Germany-specific |
350
+ | `validateFR(phone, options?)` | France-specific |
351
+ | `validateJP(phone, options?)` | Japan-specific |
352
+ | `validateIN(phone, options?)` | India-specific |
353
+ | `getMetadata(country)` | Get metadata for a country code |
354
+
355
+ ### Formatting
356
+
357
+ | Function | Description |
358
+ | -------- | ----------- |
359
+ | `normalizePhoneNumber(input)` | Strip all non-digit characters |
360
+ | `formatPhoneNumber(digits, metadata)` | Format to local display format |
361
+ | `toE164(digits, metadata)` | Format to E.164 international format |
362
+
363
+ ### Real-Time Formatter
364
+
365
+ | Function | Description |
366
+ | -------- | ----------- |
367
+ | `createPhoneFormatter(country?, options?)` | Create a stateful formatter instance |
368
+
369
+ Returns a `PhoneFormatter` with:
370
+
371
+ - `handleInput(input)` — Process new input
372
+ - `getState()` — Get current `{ value, formattedValue, validation, isValidating }`
373
+ - `clear()` — Reset state
374
+ - `destroy()` — Clean up timers
375
+
376
+ ### Privacy
377
+
378
+ | Function | Description |
379
+ | -------- | ----------- |
380
+ | `hashPhoneNumber(phone)` | SHA-256 hash (async, returns hex string) |
381
+ | `createZKProof(phone)` | Alias for `hashPhoneNumber` |
382
+
383
+ ### React (Optional)
384
+
385
+ ```typescript
386
+ import { usePhoneShield } from 'phoneshield/react';
387
+ ```
388
+
389
+ | Hook | Description |
390
+ | ---- | ----------- |
391
+ | `usePhoneShield(country?, options?)` | Real-time formatting + validation hook |
392
+
393
+ Returns `{ value, formattedValue, validation, isValidating, handleChange, clear }`.
394
+
395
+ ## Options
396
+
397
+ ```typescript
398
+ interface PhoneShieldOptions {
399
+ defaultCountry?: CountryCode; // Fallback country
400
+ strictMode?: boolean; // Stricter pattern matching
401
+ enableSuggestions?: boolean; // Enable "Did You Mean?" (default: true)
402
+ }
403
+ ```
404
+
405
+ For `createPhoneFormatter` and `usePhoneShield`, you can also pass:
406
+
407
+ - `debounceMs` — Debounce delay in ms (default: `300`)
408
+
409
+ ## Bundle Size
410
+
411
+ | Import | Size |
412
+ | ------ | ---- |
413
+ | `phoneshield/us` | ~1.2 KB |
414
+ | `phoneshield/fr` | ~1.0 KB |
415
+ | Any single country | < 2 KB |
416
+ | `phoneshield` (all countries) | ~3.5 KB |
417
+ | `phoneshield/react` | ~15 KB (includes core) |
418
+
419
+ Measured with `tsup` tree-shaking enabled. Actual sizes depend on your bundler.
420
+
421
+ ## Compatibility
422
+
423
+ - **Node.js** 18+ (uses `crypto.subtle` for hashing)
424
+ - **Browsers**: Chrome 37+, Firefox 34+, Safari 11+, Edge 79+
425
+ - **Deno**, **Bun** — works out of the box
426
+ - **React** 17+ (optional, for `phoneshield/react` only)
427
+
428
+ ## License
429
+
430
+ MIT
package/dist/au.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { C as CountryMetadata, P as PhoneShieldOptions, V as ValidationResult } from './types-CbWYeYFP.js';
2
+
3
+ declare const AU_METADATA: CountryMetadata;
4
+
5
+ declare function validateAU(phoneNumber: string, options?: PhoneShieldOptions): ValidationResult;
6
+
7
+ export { AU_METADATA, validateAU };
package/dist/au.js ADDED
@@ -0,0 +1,4 @@
1
+ export { AU_METADATA, validateAU } from './chunk-DCA72IND.js';
2
+ import './chunk-KG5T34UR.js';
3
+ //# sourceMappingURL=au.js.map
4
+ //# sourceMappingURL=au.js.map
package/dist/au.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"au.js"}
package/dist/ca.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { C as CountryMetadata, P as PhoneShieldOptions, V as ValidationResult } from './types-CbWYeYFP.js';
2
+
3
+ declare const CA_METADATA: CountryMetadata;
4
+
5
+ declare function validateCA(phoneNumber: string, options?: PhoneShieldOptions): ValidationResult;
6
+
7
+ export { CA_METADATA, validateCA };
package/dist/ca.js ADDED
@@ -0,0 +1,4 @@
1
+ export { CA_METADATA, validateCA } from './chunk-ZHU56JDV.js';
2
+ import './chunk-KG5T34UR.js';
3
+ //# sourceMappingURL=ca.js.map
4
+ //# sourceMappingURL=ca.js.map
package/dist/ca.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"ca.js"}
@@ -0,0 +1,40 @@
1
+ import { validate } from './chunk-KG5T34UR.js';
2
+
3
+ // src/phoneshield/metadata/fr.ts
4
+ var FR_METADATA = {
5
+ countryCode: "FR",
6
+ dialCode: "+33",
7
+ patterns: {
8
+ mobile: [
9
+ /^[67]\d{8}$/
10
+ ],
11
+ landline: [
12
+ /^[1-5]\d{8}$/
13
+ ],
14
+ voip: [
15
+ /^9\d{8}$/
16
+ ],
17
+ tollFree: [
18
+ /^80[0-5]\d{6}$/
19
+ ],
20
+ premium: [
21
+ /^8[129]\d{7}$/
22
+ ]
23
+ },
24
+ lengths: [9],
25
+ format: (digits) => {
26
+ if (digits.length === 9) {
27
+ return `${digits.slice(0, 1)} ${digits.slice(1, 3)} ${digits.slice(3, 5)} ${digits.slice(5, 7)} ${digits.slice(7)}`;
28
+ }
29
+ return digits;
30
+ }
31
+ };
32
+
33
+ // src/phoneshield/fr.ts
34
+ function validateFR(phoneNumber, options) {
35
+ return validate(phoneNumber, FR_METADATA, options);
36
+ }
37
+
38
+ export { FR_METADATA, validateFR };
39
+ //# sourceMappingURL=chunk-5TMYOORT.js.map
40
+ //# sourceMappingURL=chunk-5TMYOORT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/phoneshield/metadata/fr.ts","../src/phoneshield/fr.ts"],"names":[],"mappings":";;;AAEO,IAAM,WAAA,GAA+B;AAAA,EAC1C,WAAA,EAAa,IAAA;AAAA,EACb,QAAA,EAAU,KAAA;AAAA,EACV,QAAA,EAAU;AAAA,IACR,MAAA,EAAQ;AAAA,MACN;AAAA,KACF;AAAA,IACA,QAAA,EAAU;AAAA,MACR;AAAA,KACF;AAAA,IACA,IAAA,EAAM;AAAA,MACJ;AAAA,KACF;AAAA,IACA,QAAA,EAAU;AAAA,MACR;AAAA,KACF;AAAA,IACA,OAAA,EAAS;AAAA,MACP;AAAA;AACF,GACF;AAAA,EACA,OAAA,EAAS,CAAC,CAAC,CAAA;AAAA,EACX,MAAA,EAAQ,CAAC,MAAA,KAAmB;AAC1B,IAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,MAAA,OAAO,CAAA,EAAG,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AAAA,IACnH;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AACF;;;ACzBO,SAAS,UAAA,CACd,aACA,OAAA,EACkB;AAClB,EAAA,OAAO,QAAA,CAAS,WAAA,EAAa,WAAA,EAAa,OAAO,CAAA;AACnD","file":"chunk-5TMYOORT.js","sourcesContent":["import { CountryMetadata } from '../types';\n\nexport const FR_METADATA: CountryMetadata = {\n countryCode: 'FR',\n dialCode: '+33',\n patterns: {\n mobile: [\n /^[67]\\d{8}$/,\n ],\n landline: [\n /^[1-5]\\d{8}$/,\n ],\n voip: [\n /^9\\d{8}$/,\n ],\n tollFree: [\n /^80[0-5]\\d{6}$/,\n ],\n premium: [\n /^8[129]\\d{7}$/,\n ],\n },\n lengths: [9],\n format: (digits: string) => {\n if (digits.length === 9) {\n return `${digits.slice(0, 1)} ${digits.slice(1, 3)} ${digits.slice(3, 5)} ${digits.slice(5, 7)} ${digits.slice(7)}`;\n }\n return digits;\n },\n};\n","import { ValidationResult, PhoneShieldOptions } from './types';\nimport { FR_METADATA } from './metadata/fr';\nimport { validate } from './core/validator';\n\nexport function validateFR(\n phoneNumber: string,\n options?: PhoneShieldOptions\n): ValidationResult {\n return validate(phoneNumber, FR_METADATA, options);\n}\n\nexport { FR_METADATA };\n"]}
@@ -0,0 +1,45 @@
1
+ import { validate } from './chunk-KG5T34UR.js';
2
+
3
+ // src/phoneshield/metadata/de.ts
4
+ var DE_METADATA = {
5
+ countryCode: "DE",
6
+ dialCode: "+49",
7
+ patterns: {
8
+ mobile: [
9
+ /^1(?:5[0-25-9]|6[023]|7[0-9])\d{7,8}$/
10
+ ],
11
+ landline: [
12
+ /^(?:2\d|3[2-9]|4[1-8]|5[1-9]|6[1-8]|7[1-9]|8[1-9]|9[1-9])\d{5,11}$/
13
+ ],
14
+ voip: [
15
+ /^32\d{9}$/
16
+ ],
17
+ tollFree: [
18
+ /^800\d{7}$/
19
+ ],
20
+ premium: [
21
+ /^900\d{7}$/,
22
+ /^137\d{7}$/
23
+ ]
24
+ },
25
+ lengths: [7, 8, 9, 10, 11, 12],
26
+ format: (digits) => {
27
+ if (digits.length >= 10 && digits.startsWith("1")) {
28
+ return `${digits.slice(0, 4)} ${digits.slice(4)}`;
29
+ }
30
+ if (digits.length >= 7) {
31
+ const areaLen = digits.length <= 8 ? 2 : digits.length <= 10 ? 3 : 4;
32
+ return `${digits.slice(0, areaLen)} ${digits.slice(areaLen)}`;
33
+ }
34
+ return digits;
35
+ }
36
+ };
37
+
38
+ // src/phoneshield/de.ts
39
+ function validateDE(phoneNumber, options) {
40
+ return validate(phoneNumber, DE_METADATA, options);
41
+ }
42
+
43
+ export { DE_METADATA, validateDE };
44
+ //# sourceMappingURL=chunk-7S4ACFFA.js.map
45
+ //# sourceMappingURL=chunk-7S4ACFFA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/phoneshield/metadata/de.ts","../src/phoneshield/de.ts"],"names":[],"mappings":";;;AAEO,IAAM,WAAA,GAA+B;AAAA,EAC1C,WAAA,EAAa,IAAA;AAAA,EACb,QAAA,EAAU,KAAA;AAAA,EACV,QAAA,EAAU;AAAA,IACR,MAAA,EAAQ;AAAA,MACN;AAAA,KACF;AAAA,IACA,QAAA,EAAU;AAAA,MACR;AAAA,KACF;AAAA,IACA,IAAA,EAAM;AAAA,MACJ;AAAA,KACF;AAAA,IACA,QAAA,EAAU;AAAA,MACR;AAAA,KACF;AAAA,IACA,OAAA,EAAS;AAAA,MACP,YAAA;AAAA,MACA;AAAA;AACF,GACF;AAAA,EACA,SAAS,CAAC,CAAA,EAAG,GAAG,CAAA,EAAG,EAAA,EAAI,IAAI,EAAE,CAAA;AAAA,EAC7B,MAAA,EAAQ,CAAC,MAAA,KAAmB;AAC1B,IAAA,IAAI,OAAO,MAAA,IAAU,EAAA,IAAM,MAAA,CAAO,UAAA,CAAW,GAAG,CAAA,EAAG;AACjD,MAAA,OAAO,CAAA,EAAG,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AAAA,IACjD;AACA,IAAA,IAAI,MAAA,CAAO,UAAU,CAAA,EAAG;AACtB,MAAA,MAAM,OAAA,GAAU,OAAO,MAAA,IAAU,CAAA,GAAI,IAAI,MAAA,CAAO,MAAA,IAAU,KAAK,CAAA,GAAI,CAAA;AACnE,MAAA,OAAO,CAAA,EAAG,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,OAAO,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,KAAA,CAAM,OAAO,CAAC,CAAA,CAAA;AAAA,IAC7D;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AACF;;;AC9BO,SAAS,UAAA,CACd,aACA,OAAA,EACkB;AAClB,EAAA,OAAO,QAAA,CAAS,WAAA,EAAa,WAAA,EAAa,OAAO,CAAA;AACnD","file":"chunk-7S4ACFFA.js","sourcesContent":["import { CountryMetadata } from '../types';\n\nexport const DE_METADATA: CountryMetadata = {\n countryCode: 'DE',\n dialCode: '+49',\n patterns: {\n mobile: [\n /^1(?:5[0-25-9]|6[023]|7[0-9])\\d{7,8}$/,\n ],\n landline: [\n /^(?:2\\d|3[2-9]|4[1-8]|5[1-9]|6[1-8]|7[1-9]|8[1-9]|9[1-9])\\d{5,11}$/,\n ],\n voip: [\n /^32\\d{9}$/,\n ],\n tollFree: [\n /^800\\d{7}$/,\n ],\n premium: [\n /^900\\d{7}$/,\n /^137\\d{7}$/,\n ],\n },\n lengths: [7, 8, 9, 10, 11, 12],\n format: (digits: string) => {\n if (digits.length >= 10 && digits.startsWith('1')) {\n return `${digits.slice(0, 4)} ${digits.slice(4)}`;\n }\n if (digits.length >= 7) {\n const areaLen = digits.length <= 8 ? 2 : digits.length <= 10 ? 3 : 4;\n return `${digits.slice(0, areaLen)} ${digits.slice(areaLen)}`;\n }\n return digits;\n },\n};\n","import { ValidationResult, PhoneShieldOptions } from './types';\nimport { DE_METADATA } from './metadata/de';\nimport { validate } from './core/validator';\n\nexport function validateDE(\n phoneNumber: string,\n options?: PhoneShieldOptions\n): ValidationResult {\n return validate(phoneNumber, DE_METADATA, options);\n}\n\nexport { DE_METADATA };\n"]}
@@ -0,0 +1,47 @@
1
+ import { validate } from './chunk-KG5T34UR.js';
2
+
3
+ // src/phoneshield/metadata/au.ts
4
+ var AU_METADATA = {
5
+ countryCode: "AU",
6
+ dialCode: "+61",
7
+ patterns: {
8
+ mobile: [
9
+ /^4\d{8}$/
10
+ ],
11
+ landline: [
12
+ /^[2378]\d{8}$/
13
+ ],
14
+ voip: [
15
+ /^550\d{6}$/
16
+ ],
17
+ tollFree: [
18
+ /^1800\d{6}$/,
19
+ /^1300\d{6}$/
20
+ ],
21
+ premium: [
22
+ /^19\d{7,8}$/
23
+ ]
24
+ },
25
+ lengths: [9, 10],
26
+ format: (digits) => {
27
+ if (digits.length === 9 && digits.startsWith("4")) {
28
+ return `${digits.slice(0, 4)} ${digits.slice(4, 7)} ${digits.slice(7)}`;
29
+ }
30
+ if (digits.length === 9) {
31
+ return `(0${digits.slice(0, 1)}) ${digits.slice(1, 5)} ${digits.slice(5)}`;
32
+ }
33
+ if (digits.length === 10) {
34
+ return `${digits.slice(0, 4)} ${digits.slice(4, 7)} ${digits.slice(7)}`;
35
+ }
36
+ return digits;
37
+ }
38
+ };
39
+
40
+ // src/phoneshield/au.ts
41
+ function validateAU(phoneNumber, options) {
42
+ return validate(phoneNumber, AU_METADATA, options);
43
+ }
44
+
45
+ export { AU_METADATA, validateAU };
46
+ //# sourceMappingURL=chunk-DCA72IND.js.map
47
+ //# sourceMappingURL=chunk-DCA72IND.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/phoneshield/metadata/au.ts","../src/phoneshield/au.ts"],"names":[],"mappings":";;;AAEO,IAAM,WAAA,GAA+B;AAAA,EAC1C,WAAA,EAAa,IAAA;AAAA,EACb,QAAA,EAAU,KAAA;AAAA,EACV,QAAA,EAAU;AAAA,IACR,MAAA,EAAQ;AAAA,MACN;AAAA,KACF;AAAA,IACA,QAAA,EAAU;AAAA,MACR;AAAA,KACF;AAAA,IACA,IAAA,EAAM;AAAA,MACJ;AAAA,KACF;AAAA,IACA,QAAA,EAAU;AAAA,MACR,aAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA,OAAA,EAAS;AAAA,MACP;AAAA;AACF,GACF;AAAA,EACA,OAAA,EAAS,CAAC,CAAA,EAAG,EAAE,CAAA;AAAA,EACf,MAAA,EAAQ,CAAC,MAAA,KAAmB;AAC1B,IAAA,IAAI,OAAO,MAAA,KAAW,CAAA,IAAK,MAAA,CAAO,UAAA,CAAW,GAAG,CAAA,EAAG;AACjD,MAAA,OAAO,GAAG,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AAAA,IACvE;AACA,IAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,MAAA,OAAO,KAAK,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AAAA,IAC1E;AACA,IAAA,IAAI,MAAA,CAAO,WAAW,EAAA,EAAI;AACxB,MAAA,OAAO,GAAG,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AAAA,IACvE;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AACF;;;AChCO,SAAS,UAAA,CACd,aACA,OAAA,EACkB;AAClB,EAAA,OAAO,QAAA,CAAS,WAAA,EAAa,WAAA,EAAa,OAAO,CAAA;AACnD","file":"chunk-DCA72IND.js","sourcesContent":["import { CountryMetadata } from '../types';\n\nexport const AU_METADATA: CountryMetadata = {\n countryCode: 'AU',\n dialCode: '+61',\n patterns: {\n mobile: [\n /^4\\d{8}$/,\n ],\n landline: [\n /^[2378]\\d{8}$/,\n ],\n voip: [\n /^550\\d{6}$/,\n ],\n tollFree: [\n /^1800\\d{6}$/,\n /^1300\\d{6}$/,\n ],\n premium: [\n /^19\\d{7,8}$/,\n ],\n },\n lengths: [9, 10],\n format: (digits: string) => {\n if (digits.length === 9 && digits.startsWith('4')) {\n return `${digits.slice(0, 4)} ${digits.slice(4, 7)} ${digits.slice(7)}`;\n }\n if (digits.length === 9) {\n return `(0${digits.slice(0, 1)}) ${digits.slice(1, 5)} ${digits.slice(5)}`;\n }\n if (digits.length === 10) {\n return `${digits.slice(0, 4)} ${digits.slice(4, 7)} ${digits.slice(7)}`;\n }\n return digits;\n },\n};\n","import { ValidationResult, PhoneShieldOptions } from './types';\nimport { AU_METADATA } from './metadata/au';\nimport { validate } from './core/validator';\n\nexport function validateAU(\n phoneNumber: string,\n options?: PhoneShieldOptions\n): ValidationResult {\n return validate(phoneNumber, AU_METADATA, options);\n}\n\nexport { AU_METADATA };\n"]}