fix(lion-input-tel): upgrade to awesome-phonenumber v4

This commit is contained in:
Thijs Louisse 2022-11-23 12:39:03 +01:00 committed by Thijs Louisse
parent 9ddde34c5b
commit 9b4cbb1dfc
10 changed files with 2450 additions and 3170 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/ui': patch
---
[lion-input-tel] upgrade to awesome-phonenumber v4

5524
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -72,10 +72,12 @@ export class LionInputTel extends LocalizeMixin(LionInput) {
get activePhoneNumberType() { get activePhoneNumberType() {
let pn; let pn;
try { try {
pn = this._phoneUtil && this._phoneUtil(this.modelValue, this.activeRegion); pn =
this._phoneUtil &&
this._phoneUtil.parsePhoneNumber(this.modelValue, { regionCode: this.activeRegion });
// eslint-disable-next-line no-empty // eslint-disable-next-line no-empty
} catch (_) {} } catch (_) {}
return pn?.g?.type || 'unknown'; return pn?.type || 'unknown';
} }
// @ts-ignore read only // @ts-ignore read only
@ -325,7 +327,8 @@ export class LionInputTel extends LocalizeMixin(LionInput) {
const value = !(this.modelValue instanceof Unparseable) const value = !(this.modelValue instanceof Unparseable)
? this.modelValue ? this.modelValue
: this.value.match(regex)?.join(''); : this.value.match(regex)?.join('');
const regionDerivedFromValue = value && this._phoneUtil && this._phoneUtil(value).g?.regionCode; const regionDerivedFromValue =
value && this._phoneUtil && this._phoneUtil.parsePhoneNumber(value).regionCode;
if (regionDerivedFromValue && this._allowedOrAllRegions.includes(regionDerivedFromValue)) { if (regionDerivedFromValue && this._allowedOrAllRegions.includes(regionDerivedFromValue)) {
this._setActiveRegion(regionDerivedFromValue); this._setActiveRegion(regionDerivedFromValue);

View file

@ -2,21 +2,25 @@
let resolveLoaded; let resolveLoaded;
/** /**
* - Handles lazy loading of the (relatively large) google-libphonenumber library, allowing * @typedef {* & import('awesome-phonenumber')} AwesomePhoneNumber
*/
/**
* - Handles lazy loading of the awesome-phonenumber library (relatively large, but way lighter than google-libphonenumber), allowing
* for quick first paints * for quick first paints
* - Maintains one instance of phoneNumberUtil that can be shared across multiple places * - Maintains one instance of phoneNumberUtil that can be shared across multiple places
* - Allows for easy mocking in unit tests * - Allows for easy mocking in unit tests
*/ */
export class PhoneUtilManager { export class PhoneUtilManager {
static async loadLibPhoneNumber() { static async loadLibPhoneNumber() {
const PhoneUtil = (await import('awesome-phonenumber')).default; const PhoneUtil = /** @type {AwesomePhoneNumber} */ (await import('awesome-phonenumber'));
this.PhoneUtil = PhoneUtil; this.PhoneUtil = { ...PhoneUtil };
resolveLoaded(undefined); resolveLoaded(undefined);
return PhoneUtil; return PhoneUtil;
} }
/** /**
* Check if google-libphonenumber has been loaded * Check if awesome-phonenumber has been loaded
*/ */
static get isLoaded() { static get isLoaded() {
return Boolean(this.PhoneUtil); return Boolean(this.PhoneUtil);
@ -24,7 +28,7 @@ export class PhoneUtilManager {
} }
/** /**
* Wait till google-libphonenumber has been loaded * Wait till awesome-phonenumber has been loaded
* @example * @example
* ```js * ```js
* await PhoneUtilManager.loadComplete; * await PhoneUtilManager.loadComplete;

View file

@ -3,7 +3,6 @@ import { PhoneUtilManager } from './PhoneUtilManager.js';
/** /**
* @typedef {import('awesome-phonenumber').PhoneNumberFormat} PhoneNumberFormat * @typedef {import('awesome-phonenumber').PhoneNumberFormat} PhoneNumberFormat
* @typedef {import('../types/index.js').RegionCode} RegionCode * @typedef {import('../types/index.js').RegionCode} RegionCode
* @typedef {* & import('awesome-phonenumber').default} AwesomePhoneNumber
*/ */
/** /**
@ -42,33 +41,32 @@ export function formatPhoneNumber(
return modelValue; return modelValue;
} }
// eslint-disable-next-line prefer-destructuring const AwesomePhoneNumber = PhoneUtilManager.PhoneUtil;
const PhoneUtil = /** @type {AwesomePhoneNumber} */ (PhoneUtilManager.PhoneUtil);
let pn; let pn;
try { try {
pn = new PhoneUtil(modelValue, regionCode); pn = AwesomePhoneNumber.parsePhoneNumber(modelValue, { regionCode });
// eslint-disable-next-line no-empty // eslint-disable-next-line no-empty
} catch (_) {} } catch (_) {}
if (modelValue?.length >= 4 && modelValue?.length <= 16 && pn?.isValid()) { if (modelValue?.length >= 4 && modelValue?.length <= 16 && pn?.valid) {
let formattedValue; let formattedValue;
switch (formatStrategy) { switch (formatStrategy) {
case 'e164': case 'e164':
formattedValue = pn.getNumber('e164'); // -> '+46707123456' (default) formattedValue = pn.number.e164; // -> '+46707123456' (default)
break; break;
case 'international': case 'international':
formattedValue = pn.getNumber('international'); // -> '+46 70 712 34 56' formattedValue = pn.number.international; // -> '+46 70 712 34 56'
break; break;
case 'national': case 'national':
formattedValue = pn.getNumber('national'); // -> '070-712 34 56' formattedValue = pn.number.national; // -> '070-712 34 56'
break; break;
case 'rfc3966': case 'rfc3966':
formattedValue = pn.getNumber('rfc3966'); // -> 'tel:+46-70-712-34-56' formattedValue = pn.number.rfc3966; // -> 'tel:+46-70-712-34-56'
break; break;
case 'significant': case 'significant':
formattedValue = pn.getNumber('significant'); // -> '707123456' formattedValue = pn.number.significant; // -> '707123456'
break; break;
default: default:
break; break;

View file

@ -2,7 +2,6 @@ import { PhoneUtilManager } from './PhoneUtilManager.js';
/** /**
* @typedef {import('../types/index.js').RegionCode} RegionCode * @typedef {import('../types/index.js').RegionCode} RegionCode
* @typedef {* & import('awesome-phonenumber').default} AwesomePhoneNumber
*/ */
/** /**
@ -17,17 +16,17 @@ export function parsePhoneNumber(viewValue, { regionCode }) {
} }
// eslint-disable-next-line prefer-destructuring // eslint-disable-next-line prefer-destructuring
const PhoneNumber = /** @type {AwesomePhoneNumber} */ (PhoneUtilManager.PhoneUtil); const AwesomePhoneNumber = PhoneUtilManager.PhoneUtil;
const regex = /[+0-9]+/gi; const regex = /[+0-9]+/gi;
const strippedViewValue = viewValue.match(regex)?.join(''); const strippedViewValue = viewValue.match(regex)?.join('');
let pn; let pn;
try { try {
pn = PhoneNumber(strippedViewValue, regionCode); pn = AwesomePhoneNumber.parsePhoneNumber(strippedViewValue, { regionCode });
// eslint-disable-next-line no-empty // eslint-disable-next-line no-empty
} catch (_) {} } catch (_) {}
if (pn) { if (pn) {
return pn.getNumber('e164'); return pn.number.e164;
} }
return viewValue; return viewValue;

View file

@ -20,15 +20,15 @@ function hasFeedback(modelValue, regionCode) {
if (regionCode && modelValue?.length >= 4 && modelValue?.length <= 16) { if (regionCode && modelValue?.length >= 4 && modelValue?.length <= 16) {
let pn; let pn;
try { try {
pn = PhoneNumber(modelValue, regionCode); pn = PhoneNumber.parsePhoneNumber(modelValue, { regionCode });
invalidCountryCode = pn.g.regionCode !== regionCode; invalidCountryCode = pn.regionCode !== regionCode;
if (invalidCountryCode) { if (invalidCountryCode) {
return 'invalid-country-code'; return 'invalid-country-code';
} }
// eslint-disable-next-line no-empty // eslint-disable-next-line no-empty
} catch (_) {} } catch (_) {}
// too-short/too-long info seems to be not there (we get 'is-possible'?) // too-short/too-long info seems to be not there (we get 'is-possible'?)
const enumValue = !pn.isValid() ? pn.g.possibility : false; const enumValue = !pn.valid ? pn.possibility : false;
if (enumValue === 'is-possible') { if (enumValue === 'is-possible') {
return 'unknown'; return 'unknown';
} }

View file

@ -4,7 +4,7 @@ import { PhoneNumber, PhoneUtilManager } from '@lion/ui/input-tel.js';
import { mockPhoneUtilManager, restorePhoneUtilManager } from '@lion/ui/input-tel-test-helpers.js'; import { mockPhoneUtilManager, restorePhoneUtilManager } from '@lion/ui/input-tel-test-helpers.js';
/** /**
* @typedef {* & import('awesome-phonenumber').default} AwesomePhoneNumber * @typedef {* & import('awesome-phonenumber')} AwesomePhoneNumber
*/ */
// For enum output, see: https://www.npmjs.com/package/awesome-phonenumber // For enum output, see: https://www.npmjs.com/package/awesome-phonenumber
@ -24,6 +24,7 @@ describe('PhoneNumber validation', () => {
expect(validator.execute('foo', 'NL')).to.equal('unknown'); expect(validator.execute('foo', 'NL')).to.equal('unknown');
}); });
// TODO: this changed after awesome-phonenumber v4. Skip for now, look into this later
it('is invalid when wrong country code is entered, returns "invalid-country-code"', () => { it('is invalid when wrong country code is entered, returns "invalid-country-code"', () => {
const validator = new PhoneNumber(); const validator = new PhoneNumber();
// 32 is BE region code // 32 is BE region code
@ -47,12 +48,13 @@ describe('PhoneNumber validation', () => {
it('handles validation via awesome-phonenumber', () => { it('handles validation via awesome-phonenumber', () => {
const validator = new PhoneNumber(); const validator = new PhoneNumber();
const spy = sinon.spy(PhoneUtilManager, 'PhoneUtil'); // @ts-ignore
const spy = sinon.spy(PhoneUtilManager.PhoneUtil, 'parsePhoneNumber');
validator.execute('0123456789', 'NL'); validator.execute('0123456789', 'NL');
expect(spy).to.have.been.calledOnce; expect(spy).to.have.been.calledOnce;
expect(spy.lastCall.args[1]).to.equal('NL'); expect(spy.lastCall.args[1]).to.eql({ regionCode: 'NL' });
validator.execute('0123456789', 'DE'); validator.execute('0123456789', 'DE');
expect(spy.lastCall.args[1]).to.equal('DE'); expect(spy.lastCall.args[1]).to.eql({ regionCode: 'DE' });
spy.restore(); spy.restore();
}); });
@ -75,7 +77,8 @@ describe('PhoneNumber validation', () => {
it('waits for the lib to be loaded before execution completes when still in async mode', async () => { it('waits for the lib to be loaded before execution completes when still in async mode', async () => {
const validator = new PhoneNumber(); const validator = new PhoneNumber();
const spy = sinon.spy(PhoneUtilManager, 'PhoneUtil'); // @ts-ignore
const spy = sinon.spy(PhoneUtilManager.PhoneUtil, 'parsePhoneNumber');
const validationResult = validator.execute('061234', 'NL'); const validationResult = validator.execute('061234', 'NL');
expect(validationResult).to.be.instanceOf(Promise); expect(validationResult).to.be.instanceOf(Promise);
expect(spy).to.not.have.been.called; expect(spy).to.not.have.been.called;

View file

@ -48,7 +48,7 @@
"@open-wc/dedupe-mixin": "^1.3.1", "@open-wc/dedupe-mixin": "^1.3.1",
"@open-wc/scoped-elements": "^2.1.3", "@open-wc/scoped-elements": "^2.1.3",
"autosize": "4.0.2", "autosize": "4.0.2",
"awesome-phonenumber": "^3.0.1", "awesome-phonenumber": "^4.0.0",
"ibantools": "^2.2.0", "ibantools": "^2.2.0",
"lit": "^2.4.0", "lit": "^2.4.0",
"singleton-manager": "^1.6.1" "singleton-manager": "^1.6.1"

View file

@ -1,12 +0,0 @@
diff --git a/node_modules/awesome-phonenumber/package.json b/node_modules/awesome-phonenumber/package.json
index 391577c..5a5ec22 100644
--- a/node_modules/awesome-phonenumber/package.json
+++ b/node_modules/awesome-phonenumber/package.json
@@ -15,6 +15,7 @@
"types": "./index.d.ts",
"exports": {
".": {
+ "types": "./index.d.ts",
"require": "./index.js",
"default": "./index-esm.mjs"
},