@yext/phonenumber-util 0.3.0 → 0.3.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.
@@ -1,5 +1,8 @@
1
1
  name: Run pull request checks
2
2
 
3
+ permissions:
4
+ contents: read
5
+
3
6
  on:
4
7
  pull_request:
5
8
  branches: ["main"]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yext/phonenumber-util",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "author": "bajohnson@hearsaycorp.com",
5
5
  "license": "BSD-3-Clause",
6
6
  "description": "Utility for extracting and validating phone numbers",
@@ -25,16 +25,16 @@
25
25
  "make-badges": "istanbul-badges-readme"
26
26
  },
27
27
  "devDependencies": {
28
- "@eslint/js": "^9.28.0",
29
- "@vitest/coverage-v8": "^3.2.3",
30
- "eslint": "^9.28.0",
28
+ "@eslint/js": "^9.31.0",
29
+ "@vitest/coverage-v8": "^3.2.4",
30
+ "eslint": "^9.31.0",
31
31
  "generate-license-file": "4.0.0",
32
- "globals": "^16.2.0",
32
+ "globals": "^16.3.0",
33
33
  "husky": "^9.1.7",
34
34
  "istanbul-badges-readme": "^1.9.0",
35
- "lint-staged": "^16.1.0",
36
- "prettier": "^3.5.3",
37
- "vitest": "^3.2.3"
35
+ "lint-staged": "^16.1.2",
36
+ "prettier": "^3.6.2",
37
+ "vitest": "^3.2.4"
38
38
  },
39
39
  "eslintConfig": {},
40
40
  "lint-staged": {
@@ -6,6 +6,10 @@ import {
6
6
  findTimeFromAreaCode,
7
7
  findRegionFromRegionCode,
8
8
  } from '../geo.js';
9
+ import { AREA_CODE_LIST } from '../areaCodeList.js';
10
+ import { AREA_CODES, REGION_CODES } from '../phoneCodes.js';
11
+ import { PHONE_FORMATS } from '../phoneFormats.js';
12
+
9
13
  import { describe, it, expect } from 'vitest';
10
14
 
11
15
  const invalidPhone = {
@@ -184,6 +188,74 @@ const canadianPhone = {
184
188
  },
185
189
  };
186
190
 
191
+ describe('Validate that every allow-list area code has matching geo and time info', () => {
192
+ it('should ensure every area code in AREA_CODE_LIST has a matching region code in AREA_CODES', () => {
193
+ AREA_CODE_LIST.forEach((areaCode) => {
194
+ const areaCodeInfo = AREA_CODES[areaCode];
195
+
196
+ if (!areaCodeInfo) {
197
+ console.warn(
198
+ `Area code ${areaCode} does not have a matching AREA_CODES entry.`,
199
+ );
200
+ }
201
+
202
+ expect(areaCodeInfo).toBeDefined();
203
+ expect(areaCodeInfo).not.toBeNull();
204
+ });
205
+
206
+ Object.keys(AREA_CODES).forEach((areaCode) => {
207
+ const exists = AREA_CODE_LIST.includes(areaCode);
208
+
209
+ if (!exists) {
210
+ console.warn(
211
+ `Area code ${areaCode} does not have a matching AREA_CODE_LIST entry.`,
212
+ );
213
+ }
214
+
215
+ expect(exists).toBe(true);
216
+ });
217
+ });
218
+
219
+ it('should ensure every area code in AREA_CODE_LIST has a matching timezone', () => {
220
+ AREA_CODE_LIST.forEach((areaCode) => {
221
+ const timezone = findTimeFromAreaCode(
222
+ areaCode,
223
+ new Date('2024-07-15T08:00:00'),
224
+ );
225
+ expect(timezone).toBeDefined();
226
+ expect(timezone).not.toBeNull();
227
+ });
228
+ });
229
+
230
+ it('should ensure every region code in REGION_CODES has a matching phone format', () => {
231
+ Object.keys(REGION_CODES).forEach((regionCode) => {
232
+ const phoneFormat = PHONE_FORMATS[regionCode];
233
+
234
+ if (!phoneFormat) {
235
+ console.warn(
236
+ `Region code ${regionCode} does not have a matching PHONE_FORMATS entry.`,
237
+ );
238
+ }
239
+
240
+ expect(phoneFormat).toBeDefined();
241
+ expect(phoneFormat).not.toBeNull();
242
+ });
243
+
244
+ Object.keys(PHONE_FORMATS).forEach((regionCode) => {
245
+ const regionInfo = REGION_CODES[regionCode];
246
+
247
+ if (!regionInfo) {
248
+ console.warn(
249
+ `Region code ${regionCode} does not have a matching REGION_CODES entry.`,
250
+ );
251
+ }
252
+
253
+ expect(regionInfo).toBeDefined();
254
+ expect(regionInfo).not.toBeNull();
255
+ });
256
+ });
257
+ });
258
+
187
259
  describe('Daylight Savings', () => {
188
260
  it('should correctly be determined if the time given is or is not within daylight savings time', () => {
189
261
  const daylightSavings = new Date('2024-07-15T12:00:00');
@@ -38,6 +38,7 @@ export const AREA_CODE_LIST = [
38
38
  '242',
39
39
  '246',
40
40
  '248',
41
+ '249',
41
42
  '250',
42
43
  '251',
43
44
  '252',
@@ -46,6 +47,7 @@ export const AREA_CODE_LIST = [
46
47
  '256',
47
48
  '260',
48
49
  '262',
50
+ '263',
49
51
  '264',
50
52
  '267',
51
53
  '268',
@@ -98,15 +100,18 @@ export const AREA_CODE_LIST = [
98
100
  '350',
99
101
  '351',
100
102
  '352',
103
+ '354',
101
104
  '357',
102
105
  '360',
103
106
  '361',
104
107
  '363',
105
108
  '364',
106
109
  '365',
110
+ '367',
107
111
  '368',
108
112
  '369',
109
113
  '380',
114
+ '382',
110
115
  '385',
111
116
  '386',
112
117
  '387',
@@ -150,11 +155,13 @@ export const AREA_CODE_LIST = [
150
155
  '458',
151
156
  '463',
152
157
  '464',
158
+ '468',
153
159
  '469',
154
160
  '470',
155
161
  '471',
156
162
  '472',
157
163
  '473',
164
+ '474',
158
165
  '475',
159
166
  '478',
160
167
  '479',
@@ -236,6 +243,7 @@ export const AREA_CODE_LIST = [
236
243
  '580',
237
244
  '581',
238
245
  '582',
246
+ '584',
239
247
  '585',
240
248
  '586',
241
249
  '587',
@@ -301,6 +309,7 @@ export const AREA_CODE_LIST = [
301
309
  '680',
302
310
  '681',
303
311
  '682',
312
+ '683',
304
313
  '684',
305
314
  '686',
306
315
  '688',
@@ -343,6 +352,7 @@ export const AREA_CODE_LIST = [
343
352
  '743',
344
353
  '747',
345
354
  '748',
355
+ '753',
346
356
  '754',
347
357
  '757',
348
358
  '758',
package/src/base.js CHANGED
@@ -322,8 +322,8 @@ export const findNumbersInString = (text) => {
322
322
  if (
323
323
  number.replace(new RegExp(`[${VALID_PUNCTUATION}]`, 'g'), '').length >= 6
324
324
  ) {
325
- const index = text.indexOf(number);
326
- const lastIndex = index + number.length;
325
+ const index = match.index;
326
+ const lastIndex = regex.lastIndex;
327
327
  const phoneParts = getPhoneParts(number);
328
328
 
329
329
  // Presumed phone numbers may be invalidated by omission of formattedNumber from getPhoneParts.
@@ -18,4 +18,6 @@ export const AREA_CODES_WITH_MULTIPLE_DAYLIGHT_SAVINGS = {
18
18
  672: 'British Columbia',
19
19
  778: 'British Columbia',
20
20
  306: 'Saskatchewan',
21
+ 474: 'Saskatchewan',
22
+ 639: 'Saskatchewan',
21
23
  };
package/src/phoneCodes.js CHANGED
@@ -568,6 +568,7 @@ export const AREA_CODES = {
568
568
  778: { name: 'British Columbia', code: 'BC', region: CANADA },
569
569
  204: { name: 'Manitoba', code: 'MB', region: CANADA },
570
570
  431: { name: 'Manitoba', code: 'MB', region: CANADA },
571
+ 584: { name: 'Manitoba', code: 'MB', region: CANADA },
571
572
  506: { name: 'New Brunswick', code: 'NB', region: CANADA },
572
573
  709: { name: 'Newfoundland and Labrador', code: 'NL', region: CANADA },
573
574
  782: {
@@ -581,30 +582,39 @@ export const AREA_CODES = {
581
582
  region: CANADA,
582
583
  },
583
584
  226: { name: 'Ontario', code: 'ON', region: CANADA },
585
+ 249: { name: 'Ontario', code: 'ON', region: CANADA },
584
586
  289: { name: 'Ontario', code: 'ON', region: CANADA },
585
587
  343: { name: 'Ontario', code: 'ON', region: CANADA },
586
588
  365: { name: 'Ontario', code: 'ON', region: CANADA },
589
+ 382: { name: 'Ontario', code: 'ON', region: CANADA },
587
590
  416: { name: 'Ontario', code: 'ON', region: CANADA },
588
591
  437: { name: 'Ontario', code: 'ON', region: CANADA },
589
592
  519: { name: 'Ontario', code: 'ON', region: CANADA },
590
593
  548: { name: 'Ontario', code: 'ON', region: CANADA },
591
594
  613: { name: 'Ontario', code: 'ON', region: CANADA },
592
595
  647: { name: 'Ontario', code: 'ON', region: CANADA },
596
+ 683: { name: 'Ontario', code: 'ON', region: CANADA },
593
597
  705: { name: 'Ontario', code: 'ON', region: CANADA },
598
+ 753: { name: 'Ontario', code: 'ON', region: CANADA },
594
599
  742: { name: 'Ontario', code: 'ON', region: CANADA },
595
600
  807: { name: 'Ontario', code: 'ON', region: CANADA },
596
601
  942: { name: 'Ontario', code: 'ON', region: CANADA },
597
602
  905: { name: 'Ontario', code: 'ON', region: CANADA },
603
+ 263: { name: 'Quebec', code: 'QC', region: CANADA },
604
+ 354: { name: 'Quebec', code: 'QC', region: CANADA },
605
+ 367: { name: 'Quebec', code: 'QC', region: CANADA },
598
606
  387: { name: 'Quebec', code: 'QC', region: CANADA },
599
607
  418: { name: 'Quebec', code: 'QC', region: CANADA },
600
608
  438: { name: 'Quebec', code: 'QC', region: CANADA },
601
609
  450: { name: 'Quebec', code: 'QC', region: CANADA },
610
+ 468: { name: 'Quebec', code: 'QC', region: CANADA },
602
611
  514: { name: 'Quebec', code: 'QC', region: CANADA },
603
612
  579: { name: 'Quebec', code: 'QC', region: CANADA },
604
613
  581: { name: 'Quebec', code: 'QC', region: CANADA },
605
614
  819: { name: 'Quebec', code: 'QC', region: CANADA },
606
615
  873: { name: 'Quebec', code: 'QC', region: CANADA },
607
616
  306: { name: 'Saskatchewan', code: 'SK', region: CANADA },
617
+ 474: { name: 'Saskatchewan', code: 'SK', region: CANADA },
608
618
  639: { name: 'Saskatchewan', code: 'SK', region: CANADA },
609
619
  867: {
610
620
  name: 'Yukon, Northwest Territories, and Nunavut',
@@ -708,6 +718,7 @@ export const REGION_CODES = {
708
718
  679: { name: 'Fiji', code: 'FJ', flag: '🇫🇯' },
709
719
  358: { name: 'Finland', code: 'FI', flag: '🇫🇮' },
710
720
  33: { name: 'France', code: 'FR', flag: '🇫🇷' },
721
+ 594: { name: 'French Guiana', code: 'GF', flag: '🇬🇫' },
711
722
  689: { name: 'French Polynesia', code: 'PF', flag: '🇵🇫' },
712
723
  241: { name: 'Gabon', code: 'GA', flag: '🇬🇦' },
713
724
  220: { name: 'Gambia', code: 'GM', flag: '🇬🇲' },
@@ -761,6 +772,7 @@ export const REGION_CODES = {
761
772
  223: { name: 'Mali', code: 'ML', flag: '🇲🇱' },
762
773
  356: { name: 'Malta', code: 'MT', flag: '🇲🇹' },
763
774
  692: { name: 'Marshall Islands', code: 'MH', flag: '🇲🇭' },
775
+ 596: { name: 'Martinique', code: 'MQ', flag: '🇲🇶' },
764
776
  222: { name: 'Mauritania', code: 'MR', flag: '🇲🇷' },
765
777
  230: { name: 'Mauritius', code: 'MU', flag: '🇲🇺' },
766
778
  262: { name: 'Mayotte, Reunion', code: 'YT/RE', flag: '🇾🇹/🇷🇪' },
@@ -145,7 +145,6 @@ export const PHONE_FORMATS = {
145
145
  269: '+xxx xxx xx xx', // Comoros
146
146
  290: '+xxx xxxx', // Saint Helena
147
147
  291: '+xxx x xxx xxx', // Eritrea
148
- 295: '+xxx xxx xxxx', // San Marino
149
148
  297: '+xxx xxx xxxx', // Aruba
150
149
  298: '+xxx xxx xxx', // Faroe Islands
151
150
  299: '+xxx xx xx xx', // Greenland
package/src/timezones.js CHANGED
@@ -118,6 +118,11 @@ export const STATES_WITH_MULTIPLE_TIMEZONES = {
118
118
  458: ['-08:00', '-07:00'],
119
119
  541: ['-08:00', '-07:00'],
120
120
  },
121
+ Saskatchewan: {
122
+ 306: ['-07:00', '-06:00', '-05:00'],
123
+ 474: ['-07:00', '-06:00', '-05:00'],
124
+ 639: ['-07:00', '-06:00', '-05:00'],
125
+ },
121
126
  'South Dakota': {
122
127
  605: ['-06:00', '-07:00'],
123
128
  },
@@ -142,7 +147,9 @@ export const STATES_WITH_MULTIPLE_TIMEZONES = {
142
147
  807: ['-05:00', '-06:00'],
143
148
  },
144
149
  Quebec: {
150
+ 367: ['-04:00'],
145
151
  418: ['-04:00'],
152
+ 581: ['-04:00'],
146
153
  },
147
154
  'Newfoundland and Labrador': {
148
155
  709: ['-03:30', '-04:00'],