core-services-sdk 1.3.11 → 1.3.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "core-services-sdk",
3
- "version": "1.3.11",
3
+ "version": "1.3.13",
4
4
  "main": "src/index.js",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -1,12 +1,40 @@
1
- // src/core/phone-validate.js
2
- // Validate & normalize using google-libphonenumber
1
+ // normalize-phone-number.js
2
+ // Works with both CJS and ESM builds of google-libphonenumber
3
3
 
4
- import { PhoneNumberUtil, PhoneNumberFormat } from 'google-libphonenumber'
4
+ import * as raw from 'google-libphonenumber'
5
5
 
6
- const phoneUtil = PhoneNumberUtil.getInstance()
6
+ /** Resolve libphonenumber regardless of interop shape */
7
+ function getLib() {
8
+ // Prefer direct (CJS-style or ESM w/ named), else default
9
+ // e.g. raw.PhoneNumberUtil OR raw.default.PhoneNumberUtil
10
+ // eslint-disable-next-line no-unused-vars
11
+ /** @type {any} */
12
+ const anyRaw = raw
13
+ const lib = anyRaw.PhoneNumberUtil ? anyRaw : anyRaw.default ?? anyRaw
14
+
15
+ if (!lib || !lib.PhoneNumberUtil || !lib.PhoneNumberFormat) {
16
+ throw new Error('google-libphonenumber failed to load (exports not found)')
17
+ }
18
+ return lib
19
+ }
20
+
21
+ let _util // lazy singleton
22
+
23
+ function phoneUtil() {
24
+ if (!_util) {
25
+ const { PhoneNumberUtil } = getLib()
26
+ _util = PhoneNumberUtil.getInstance()
27
+ }
28
+ return _util
29
+ }
30
+
31
+ function formats() {
32
+ const { PhoneNumberFormat } = getLib()
33
+ return PhoneNumberFormat
34
+ }
7
35
 
8
36
  /**
9
- * Trim and remove invisible RTL markers that can sneak in from copy/paste.
37
+ * Trim and remove invisible RTL markers.
10
38
  * @param {string} input
11
39
  * @returns {string}
12
40
  */
@@ -18,53 +46,57 @@ function clean(input) {
18
46
 
19
47
  /**
20
48
  * Convert a parsed libphonenumber object into a normalized result.
21
- * @param {import('google-libphonenumber').PhoneNumber} parsed
49
+ * @param {any} parsed
22
50
  * @returns {{e164:string,national:string,international:string,regionCode:string|undefined,type:number}}
23
51
  */
24
52
  function toResult(parsed) {
53
+ const PNF = formats()
54
+ const util = phoneUtil()
25
55
  return {
26
- e164: phoneUtil.format(parsed, PhoneNumberFormat.E164),
27
- national: phoneUtil.format(parsed, PhoneNumberFormat.NATIONAL),
28
- international: phoneUtil.format(parsed, PhoneNumberFormat.INTERNATIONAL),
29
- regionCode: phoneUtil.getRegionCodeForNumber(parsed),
30
- type: phoneUtil.getNumberType(parsed),
56
+ e164: util.format(parsed, PNF.E164),
57
+ national: util.format(parsed, PNF.NATIONAL),
58
+ international: util.format(parsed, PNF.INTERNATIONAL),
59
+ regionCode: util.getRegionCodeForNumber(parsed),
60
+ type: util.getNumberType(parsed),
31
61
  }
32
62
  }
33
63
 
34
64
  /**
35
65
  * Parse & validate an international number (must start with '+').
36
- * Throws on invalid input.
37
- *
38
- * @param {string} input - International number, e.g. "+972541234567"
66
+ * @param {string} input
39
67
  * @returns {{e164:string,national:string,international:string,regionCode:string|undefined,type:number}}
40
68
  * @throws {Error} If the number is invalid
41
69
  */
42
70
  export function normalizePhoneOrThrowIntl(input) {
43
71
  try {
44
- const parsed = phoneUtil.parseAndKeepRawInput(clean(input))
45
- if (!phoneUtil.isValidNumber(parsed)) throw new Error('x')
72
+ const util = phoneUtil()
73
+ const parsed = util.parseAndKeepRawInput(clean(input))
74
+ if (!util.isValidNumber(parsed)) throw new Error('x')
46
75
  return toResult(parsed)
47
- } catch {
48
- throw new Error('Invalid phone number')
76
+ } catch (e) {
77
+ const err = new Error('Invalid phone number')
78
+ err.cause = e
79
+ throw err
49
80
  }
50
81
  }
51
82
 
52
83
  /**
53
84
  * Parse & validate a national number using a region hint.
54
- * Throws on invalid input.
55
- *
56
- * @param {string} input - National number, e.g. "054-123-4567"
57
- * @param {string} defaultRegion - ISO region like "IL" or "US"
85
+ * @param {string} input
86
+ * @param {string} defaultRegion
58
87
  * @returns {{e164:string,national:string,international:string,regionCode:string|undefined,type:number}}
59
88
  * @throws {Error} If the number is invalid
60
89
  */
61
90
  export function normalizePhoneOrThrowWithRegion(input, defaultRegion) {
62
91
  try {
63
- const parsed = phoneUtil.parseAndKeepRawInput(clean(input), defaultRegion)
64
- if (!phoneUtil.isValidNumber(parsed)) throw new Error('x')
92
+ const util = phoneUtil()
93
+ const parsed = util.parseAndKeepRawInput(clean(input), defaultRegion)
94
+ if (!util.isValidNumber(parsed)) throw new Error('x')
65
95
  return toResult(parsed)
66
- } catch {
67
- throw new Error('Invalid phone number')
96
+ } catch (e) {
97
+ const err = new Error('Invalid phone number')
98
+ err.cause = e
99
+ throw err
68
100
  }
69
101
  }
70
102
 
@@ -72,8 +104,6 @@ export function normalizePhoneOrThrowWithRegion(input, defaultRegion) {
72
104
  * Smart normalization:
73
105
  * - If input starts with '+', parse as international.
74
106
  * - Otherwise require a defaultRegion and parse as national.
75
- * Throws on invalid input or when defaultRegion is missing for non-international numbers.
76
- *
77
107
  * @param {string} input
78
108
  * @param {{ defaultRegion?: string }} [opts]
79
109
  * @returns {{e164:string,national:string,international:string,regionCode:string|undefined,type:number}}
@@ -86,7 +116,6 @@ export function normalizePhoneOrThrow(input, opts = {}) {
86
116
  }
87
117
  const { defaultRegion } = opts
88
118
  if (!defaultRegion) {
89
- // keep this one specific; your test relies on a different message here
90
119
  throw new Error('defaultRegion is required for non-international numbers')
91
120
  }
92
121
  return normalizePhoneOrThrowWithRegion(cleaned, defaultRegion)
@@ -22,94 +22,95 @@ function exampleForRegion(region) {
22
22
  region,
23
23
  }
24
24
  }
25
+ describe('phone normalization', () => {
26
+ describe('phone normalization helpers', () => {
27
+ it('normalizePhoneOrThrowIntl: parses a valid international number (US)', () => {
28
+ const us = exampleForRegion('US')
29
+ const out = normalizePhoneOrThrowIntl(us.e164)
30
+ expect(out.e164).toBe(us.e164)
31
+ expect(out.regionCode).toBe('US')
32
+ expect(out.international).toMatch(/^\+1\b/)
33
+ })
25
34
 
26
- describe('phone normalization helpers', () => {
27
- it('normalizePhoneOrThrowIntl: parses a valid international number (US)', () => {
28
- const us = exampleForRegion('US')
29
- const out = normalizePhoneOrThrowIntl(us.e164)
30
- expect(out.e164).toBe(us.e164)
31
- expect(out.regionCode).toBe('US')
32
- expect(out.international).toMatch(/^\+1\b/)
33
- })
34
-
35
- it('normalizePhoneOrThrowWithRegion: parses a national number with region (IL)', () => {
36
- const il = exampleForRegion('IL')
37
- // introduce some separators/spaces to mimic user input
38
- const dirty = ` ${il.national.replace(/\s/g, '-')} `
39
- const out = normalizePhoneOrThrowWithRegion(dirty, 'IL')
40
- expect(out.e164).toBe(il.e164)
41
- expect(out.regionCode).toBe('IL')
42
- expect(out.international).toMatch(/^\+972/)
43
- })
35
+ it('normalizePhoneOrThrowWithRegion: parses a national number with region (IL)', () => {
36
+ const il = exampleForRegion('IL')
37
+ // introduce some separators/spaces to mimic user input
38
+ const dirty = ` ${il.national.replace(/\s/g, '-')} `
39
+ const out = normalizePhoneOrThrowWithRegion(dirty, 'IL')
40
+ expect(out.e164).toBe(il.e164)
41
+ expect(out.regionCode).toBe('IL')
42
+ expect(out.international).toMatch(/^\+972/)
43
+ })
44
44
 
45
- it('normalizePhoneOrThrow (smart): international path without region', () => {
46
- const us = exampleForRegion('US')
47
- const out = normalizePhoneOrThrow(us.e164)
48
- expect(out.e164).toBe(us.e164)
49
- expect(out.regionCode).toBe('US')
50
- })
45
+ it('normalizePhoneOrThrow (smart): international path without region', () => {
46
+ const us = exampleForRegion('US')
47
+ const out = normalizePhoneOrThrow(us.e164)
48
+ expect(out.e164).toBe(us.e164)
49
+ expect(out.regionCode).toBe('US')
50
+ })
51
51
 
52
- it('normalizePhoneOrThrow (smart): national path requires defaultRegion', () => {
53
- const il = exampleForRegion('IL')
54
- const dirty = il.national.replace(/\s/g, ' - ')
55
- const out = normalizePhoneOrThrow(dirty, { defaultRegion: 'IL' })
56
- expect(out.e164).toBe(il.e164)
57
- expect(out.regionCode).toBe('IL')
58
- })
52
+ it('normalizePhoneOrThrow (smart): national path requires defaultRegion', () => {
53
+ const il = exampleForRegion('IL')
54
+ const dirty = il.national.replace(/\s/g, ' - ')
55
+ const out = normalizePhoneOrThrow(dirty, { defaultRegion: 'IL' })
56
+ expect(out.e164).toBe(il.e164)
57
+ expect(out.regionCode).toBe('IL')
58
+ })
59
59
 
60
- it('normalizePhoneOrThrow (smart): throws if national with no defaultRegion', () => {
61
- expect(() => normalizePhoneOrThrow('054-123-4567')).toThrow(
62
- /defaultRegion is required/i,
63
- )
64
- })
60
+ it('normalizePhoneOrThrow (smart): throws if national with no defaultRegion', () => {
61
+ expect(() => normalizePhoneOrThrow('054-123-4567')).toThrow(
62
+ /defaultRegion is required/i,
63
+ )
64
+ })
65
65
 
66
- it('all helpers: throw on truly invalid numbers', () => {
67
- expect(() => normalizePhoneOrThrowIntl('++972')).toThrow(
68
- /Invalid phone number/i,
69
- )
70
- expect(() => normalizePhoneOrThrowWithRegion('123', 'IL')).toThrow(
71
- /Invalid phone number/i,
72
- )
73
- expect(() => normalizePhoneOrThrow('++972')).toThrow(
74
- /Invalid phone number/i,
75
- )
76
- })
66
+ it('all helpers: throw on truly invalid numbers', () => {
67
+ expect(() => normalizePhoneOrThrowIntl('++972')).toThrow(
68
+ /Invalid phone number/i,
69
+ )
70
+ expect(() => normalizePhoneOrThrowWithRegion('123', 'IL')).toThrow(
71
+ /Invalid phone number/i,
72
+ )
73
+ expect(() => normalizePhoneOrThrow('++972')).toThrow(
74
+ /Invalid phone number/i,
75
+ )
76
+ })
77
77
 
78
- it('should normalize a valid international number', () => {
79
- const result = normalizePhoneOrThrowIntl('+972523444444')
78
+ it('should normalize a valid international number', () => {
79
+ const result = normalizePhoneOrThrowIntl('+972523444444')
80
80
 
81
- expect(result).toMatchObject({
82
- e164: '+972523444444',
83
- national: expect.stringContaining('052'),
84
- international: expect.stringContaining('+972'),
85
- regionCode: 'IL',
86
- type: expect.any(Number), // e.g. 1 = MOBILE
81
+ expect(result).toMatchObject({
82
+ e164: '+972523444444',
83
+ national: expect.stringContaining('052'),
84
+ international: expect.stringContaining('+972'),
85
+ regionCode: 'IL',
86
+ type: expect.any(Number), // e.g. 1 = MOBILE
87
+ })
87
88
  })
88
89
  })
89
- })
90
90
 
91
- describe('phone normalization — no region (international) & with region', () => {
92
- // Valid full international IL mobile number (E.164)
93
- const intlIl = '+972523444444' // 052-344-4444
91
+ describe('phone normalization — no region (international) & with region', () => {
92
+ // Valid full international IL mobile number (E.164)
93
+ const intlIl = '+972523444444' // 052-344-4444
94
94
 
95
- it('normalizePhoneOrThrowIntl: accepts full international number without region', () => {
96
- const out = normalizePhoneOrThrowIntl(intlIl)
97
- expect(out.e164).toBe(intlIl)
98
- expect(out.regionCode).toBe('IL')
99
- expect(out.international).toMatch(/^\+972/)
100
- expect(typeof out.type).toBe('number')
101
- })
95
+ it('normalizePhoneOrThrowIntl: accepts full international number without region', () => {
96
+ const out = normalizePhoneOrThrowIntl(intlIl)
97
+ expect(out.e164).toBe(intlIl)
98
+ expect(out.regionCode).toBe('IL')
99
+ expect(out.international).toMatch(/^\+972/)
100
+ expect(typeof out.type).toBe('number')
101
+ })
102
102
 
103
- it('normalizePhoneOrThrow (smart): accepts +972... without defaultRegion', () => {
104
- const out = normalizePhoneOrThrow(intlIl) // no opts.defaultRegion
105
- expect(out.e164).toBe(intlIl)
106
- expect(out.regionCode).toBe('IL')
107
- })
103
+ it('normalizePhoneOrThrow (smart): accepts +972... without defaultRegion', () => {
104
+ const out = normalizePhoneOrThrow(intlIl) // no opts.defaultRegion
105
+ expect(out.e164).toBe(intlIl)
106
+ expect(out.regionCode).toBe('IL')
107
+ })
108
108
 
109
- it('normalizePhoneOrThrowWithRegion: accepts national number with region', () => {
110
- const out = normalizePhoneOrThrowWithRegion('052-344-4444', 'IL')
111
- expect(out.e164).toBe(intlIl)
112
- expect(out.regionCode).toBe('IL')
113
- expect(out.national).toMatch(/052/)
109
+ it('normalizePhoneOrThrowWithRegion: accepts national number with region', () => {
110
+ const out = normalizePhoneOrThrowWithRegion('052-344-4444', 'IL')
111
+ expect(out.e164).toBe(intlIl)
112
+ expect(out.regionCode).toBe('IL')
113
+ expect(out.national).toMatch(/052/)
114
+ })
114
115
  })
115
116
  })