-
Notifications
You must be signed in to change notification settings - Fork 0
/
PhoneNumber.ts
83 lines (71 loc) · 3.04 KB
/
PhoneNumber.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import * as libphonenumber from 'google-libphonenumber';
import { ValueObject } from '../abstractions/ValueObject';
import { Result } from '../abstractions/Result';
import { serializer } from '@deepkit/type';
// we have to define our own type alias where runtime types are enabled and then use this type everywhere
class GooglePhone extends libphonenumber.PhoneNumber {}
serializer.serializeRegistry.registerClass(GooglePhone, (_, state) => {
state.addSetter(`${state.accessor}`);
});
serializer.deserializeRegistry.registerClass(GooglePhone, (_, state) => {
state.addSetter(state.accessor);
});
export class PhoneNumber extends ValueObject<PhoneNumber> {
private readonly phoneUtil = libphonenumber.PhoneNumberUtil.getInstance();
constructor(private readonly parsedNumber: GooglePhone) {
super()
}
public static get validRegions(): Array<string> {
return ['US', 'CO', 'RO'];
}
public static get validTypes(): Array<libphonenumber.PhoneNumberType> {
return [
libphonenumber.PhoneNumberType.FIXED_LINE_OR_MOBILE,
libphonenumber.PhoneNumberType.TOLL_FREE,
libphonenumber.PhoneNumberType.MOBILE,
];
}
public static create(phoneNumber: string): Result<PhoneNumber> {
const phoneUtil = libphonenumber.PhoneNumberUtil.getInstance();
const parsedNumber = this.parsePhoneNumber(phoneNumber, phoneUtil);
if (this.validTypes.includes(phoneUtil.getNumberType(parsedNumber)) === true) {
return Result.ok<PhoneNumber>(new PhoneNumber(parsedNumber));
} else {
if (phoneUtil.isPossibleNumber(parsedNumber) === false)
return Result.fail<PhoneNumber>(`PhoneNumber: ${phoneNumber} isn't possibly correct.`);
if (phoneUtil.isValidNumber(parsedNumber) === false)
return Result.fail<PhoneNumber>(`PhoneNumber: ${phoneNumber} isn't valid.`);
return Result.fail<PhoneNumber>(`PhoneNumber: ${phoneNumber} isn't the correct type.`);
}
}
public get couldBeMobile(): boolean {
return [libphonenumber.PhoneNumberType.FIXED_LINE_OR_MOBILE, libphonenumber.PhoneNumberType.MOBILE].includes(
this.phoneUtil.getNumberType(this.parsedNumber),
);
}
public get formatPhoneNumberAsNational(): string {
return this.phoneUtil.format(this.parsedNumber, libphonenumber.PhoneNumberFormat.NATIONAL);
}
public get formatPhoneNumberAsE164(): string {
return this.phoneUtil.format(this.parsedNumber, libphonenumber.PhoneNumberFormat.E164);
}
private static parsePhoneNumber = function (
phoneNumber: string,
phoneUtil: libphonenumber.PhoneNumberUtil,
): libphonenumber.PhoneNumber {
let parsedNumber = new GooglePhone();
try {
for (const region of PhoneNumber.validRegions) {
parsedNumber = phoneUtil.parse(phoneNumber, region);
if (
phoneUtil.isPossibleNumber(parsedNumber) === true && // faster then isValidNumber wont allow empty string or values of bad length
phoneUtil.isValidNumber(parsedNumber) === true
)
break;
}
} catch {
return new GooglePhone();
}
return parsedNumber;
};
}