@yext/phonenumber-util 0.2.0 β 0.2.1
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.
- package/.husky/pre-commit +3 -1
- package/README.md +3 -1
- package/package.json +5 -2
- package/src/__tests__/base.test.js +11 -2
- package/src/__tests__/geo.test.js +24 -0
- package/src/base.js +12 -14
- package/src/geo.js +2 -1
- package/vitest.config.js +3 -0
package/.husky/pre-commit
CHANGED
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
Utility for extracting and validating phone numbers. Extracts an array of phone numbers from an inputted string, validates that these numbers appear genuine and provide data about those phone numbers.
|
|
2
2
|
|
|
3
|
+
[](https://opensource.org/licenses/BSD-3-Clause)    
|
|
4
|
+
|
|
3
5
|
### Scripts
|
|
4
6
|
|
|
5
7
|
#### Install dependencies
|
|
@@ -196,7 +198,7 @@ Example output for Arizona:
|
|
|
196
198
|
|
|
197
199
|
```javascript
|
|
198
200
|
import { findTimeFromAreaCode } from '@yext/phonenumber-util/geo';
|
|
199
|
-
findTimeFromAreaCode('250');
|
|
201
|
+
findTimeFromAreaCode('250', date); // A date object is optional, defaulting to the current time.
|
|
200
202
|
```
|
|
201
203
|
|
|
202
204
|
Example output for British Columbia:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yext/phonenumber-util",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"author": "bajohnson@hearsaycorp.com",
|
|
5
5
|
"license": "BSD-3-Clause",
|
|
6
6
|
"description": "Utility for extracting and validating phone numbers",
|
|
@@ -21,14 +21,17 @@
|
|
|
21
21
|
"format": "prettier --write **/*.js **/__tests__/*.js",
|
|
22
22
|
"test": "TZ=America/Los_Angeles vitest",
|
|
23
23
|
"build": "node -e \"console.log('No build script for vanilla JS')\"",
|
|
24
|
-
"prepare": "husky"
|
|
24
|
+
"prepare": "husky",
|
|
25
|
+
"make-badges": "istanbul-badges-readme"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"@eslint/js": "^9.7.0",
|
|
28
29
|
"@vitest/coverage-v8": "^2.1.1",
|
|
29
30
|
"eslint": "^9.7.0",
|
|
31
|
+
"generate-license-file": "^3.5.1",
|
|
30
32
|
"globals": "^15.8.0",
|
|
31
33
|
"husky": "^9.1.5",
|
|
34
|
+
"istanbul-badges-readme": "^1.9.0",
|
|
32
35
|
"lint-staged": "^15.2.10",
|
|
33
36
|
"prettier": "^3.3.3",
|
|
34
37
|
"vitest": "^2.1.1"
|
|
@@ -220,20 +220,29 @@ describe('Phone number pretty formatting', () => {
|
|
|
220
220
|
format: findPhoneFormat({ regionCode: '57', e164: '+573211234567' }),
|
|
221
221
|
},
|
|
222
222
|
germany: {
|
|
223
|
-
e164: '+
|
|
223
|
+
e164: '+4917087654321',
|
|
224
224
|
regionCode: '49',
|
|
225
225
|
format: findPhoneFormat({ regionCode: '49', e164: '+4917087654321' }),
|
|
226
226
|
},
|
|
227
227
|
germanyAlt: {
|
|
228
|
-
e164: '+
|
|
228
|
+
e164: '+491708765432',
|
|
229
229
|
regionCode: '49',
|
|
230
230
|
format: findPhoneFormat({ regionCode: '49', e164: '+491708765432' }),
|
|
231
231
|
},
|
|
232
|
+
norwayUnexpected: {
|
|
233
|
+
e164: '+47174087654',
|
|
234
|
+
regionCode: '47',
|
|
235
|
+
format: findPhoneFormat({ regionCode: '47', e164: '+471740876543' }),
|
|
236
|
+
},
|
|
232
237
|
};
|
|
233
238
|
|
|
234
239
|
expect(formatPhoneNumber(testNumbers.nullCase)).toBe(null);
|
|
235
240
|
expect(formatPhoneNumber(testNumbers.us)).toBe('(310) 349-6200');
|
|
236
241
|
expect(formatPhoneNumber(testNumbers.colombia)).toBe('+57 321 123 4567');
|
|
237
242
|
expect(formatPhoneNumber(testNumbers.germanyAlt)).toBe('+49 17 08765432');
|
|
243
|
+
// This looks like a Norwegian number, but doesn't match a known format. In this case, we'll return a sanitized generic format.
|
|
244
|
+
expect(formatPhoneNumber(testNumbers.norwayUnexpected)).toBe(
|
|
245
|
+
'+47174087654',
|
|
246
|
+
);
|
|
238
247
|
});
|
|
239
248
|
});
|
|
@@ -37,6 +37,27 @@ const seattlePhone = {
|
|
|
37
37
|
},
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
+
const portlandPhone = {
|
|
41
|
+
areaCodeHasMultipleTimezones: false,
|
|
42
|
+
daylightSavings: true,
|
|
43
|
+
estimatedTime: false,
|
|
44
|
+
isQuietHours: false,
|
|
45
|
+
isTCPAQuietHours: false,
|
|
46
|
+
localTime24Hour: '08:00:00',
|
|
47
|
+
localTimeReadable: '8:00:00 AM',
|
|
48
|
+
stateHasMultipleTimezones: true,
|
|
49
|
+
timezoneOffset: '-07:00',
|
|
50
|
+
state: {
|
|
51
|
+
name: 'Oregon',
|
|
52
|
+
code: 'OR',
|
|
53
|
+
},
|
|
54
|
+
region: {
|
|
55
|
+
name: 'United States',
|
|
56
|
+
code: 'US',
|
|
57
|
+
flag: 'πΊπΈ',
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
40
61
|
const arizonaPhoneJul = {
|
|
41
62
|
areaCodeHasMultipleTimezones: false,
|
|
42
63
|
daylightSavings: true,
|
|
@@ -250,6 +271,9 @@ describe('Provides general time information for the given phone number (US and C
|
|
|
250
271
|
expect(
|
|
251
272
|
findTimeFromAreaCode('206', new Date('2024-07-15T08:00:00')),
|
|
252
273
|
).toEqual(seattlePhone);
|
|
274
|
+
expect(
|
|
275
|
+
findTimeFromAreaCode('503', new Date('2024-07-15T08:00:00')),
|
|
276
|
+
).toEqual(portlandPhone);
|
|
253
277
|
expect(
|
|
254
278
|
findTimeFromAreaCode('928', new Date('2024-07-15T08:00:00')),
|
|
255
279
|
).toEqual(arizonaPhoneJul);
|
package/src/base.js
CHANGED
|
@@ -234,18 +234,6 @@ export const getPhoneParts = (phoneNumber) => {
|
|
|
234
234
|
phoneParts.e164 = formatPhoneNumberForE164(phoneParts);
|
|
235
235
|
phoneParts.format = findPhoneFormat(phoneParts);
|
|
236
236
|
phoneParts.formattedNumber = formatPhoneNumber(phoneParts);
|
|
237
|
-
|
|
238
|
-
// If there are left over x's, the formatting ran into something unexpected.
|
|
239
|
-
// This may be ok depending on the region and their phone number formats.
|
|
240
|
-
// But it does mean we don't want to display this number.
|
|
241
|
-
if (
|
|
242
|
-
phoneParts.formattedNumber &&
|
|
243
|
-
phoneParts.formattedNumber.indexOf('x') !== -1
|
|
244
|
-
) {
|
|
245
|
-
// Since `rawNumber` isn't sanitized, we'll use a simple format that we
|
|
246
|
-
// are assured to be safe.
|
|
247
|
-
phoneParts.formattedNumber = strippedPhoneNumber;
|
|
248
|
-
}
|
|
249
237
|
}
|
|
250
238
|
|
|
251
239
|
return phoneParts;
|
|
@@ -353,16 +341,26 @@ export const findPhoneFormat = ({ regionCode, e164 }) => {
|
|
|
353
341
|
* @param {Object} params - The parameters for formatting the phone number.
|
|
354
342
|
* @param {string} params.format - The desired format for the phone number. Example: `(xxx) xxx-xxxx`.
|
|
355
343
|
* @param {string} params.e164 - The E.164 formatted phone number to format. Example: `+12065551234`.
|
|
344
|
+
* @param {string} params.regionCode - The region code of the phone number. Example, the US would be "1".
|
|
356
345
|
* @returns {string|null} The formatted phone number, or null if the E.164 number or format is not provided.
|
|
357
346
|
*/
|
|
358
|
-
export const formatPhoneNumber = ({ format, e164 }) => {
|
|
347
|
+
export const formatPhoneNumber = ({ format, e164, regionCode }) => {
|
|
359
348
|
let formattedNumber = '';
|
|
360
349
|
|
|
361
350
|
if (e164 && format) {
|
|
362
351
|
// Remove the leading '+' and let the format handle it.
|
|
363
|
-
const strippedPhone = e164.replace(
|
|
352
|
+
const strippedPhone = e164.replace(/\+/g, '');
|
|
364
353
|
let phoneIndex = strippedPhone.length - 1;
|
|
365
354
|
|
|
355
|
+
// The US / NANP rarely includes region code prefix when sharing numbers. Other regions often do, so we'll have a special condition to allow ignoring of the region code for region 1.
|
|
356
|
+
// For other regions, we'll return the stripped number to safely display the presumed good number that may be in a safe but not-ideal format.
|
|
357
|
+
if (
|
|
358
|
+
regionCode !== '1' &&
|
|
359
|
+
strippedPhone.length !== format.split('x').length - 1
|
|
360
|
+
) {
|
|
361
|
+
return e164;
|
|
362
|
+
}
|
|
363
|
+
|
|
366
364
|
// Traverse backward so we can omit country code in some formats (like US).
|
|
367
365
|
for (let i = format.length; i >= 0; i--) {
|
|
368
366
|
if (format[i]) {
|
package/src/geo.js
CHANGED
|
@@ -186,7 +186,8 @@ export function findTimeFromAreaCode(areaCode, date = new Date()) {
|
|
|
186
186
|
returnTime.areaCodeHasMultipleTimezones = false;
|
|
187
187
|
}
|
|
188
188
|
} else {
|
|
189
|
-
returnTime.stateHasMultipleTimezones =
|
|
189
|
+
returnTime.stateHasMultipleTimezones =
|
|
190
|
+
!!STATES_WITH_MULTIPLE_TIMEZONES[stateName];
|
|
190
191
|
returnTime.areaCodeHasMultipleTimezones = false;
|
|
191
192
|
localOffset = STATE_TIMEZONES[stateName];
|
|
192
193
|
}
|