@temboplus/frontend-core 0.2.0 → 0.2.2

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.
Files changed (170) hide show
  1. package/README.md +64 -25
  2. package/esm/deps/jsr.io/@std/internal/1.0.5/assertion_state.d.ts.map +1 -0
  3. package/esm/deps/jsr.io/@std/testing/1.0.9/_test_suite.d.ts.map +1 -0
  4. package/esm/deps/jsr.io/@std/testing/1.0.9/bdd.d.ts.map +1 -0
  5. package/esm/src/{models/bank/banks.d.ts → data/banks_tz.d.ts} +1 -1
  6. package/esm/src/data/banks_tz.d.ts.map +1 -0
  7. package/esm/src/data/countries.d.ts +6 -0
  8. package/esm/src/data/countries.d.ts.map +1 -0
  9. package/esm/src/data/countries.js +974 -0
  10. package/esm/src/data/currencies.d.ts +1901 -0
  11. package/esm/src/data/currencies.d.ts.map +1 -0
  12. package/esm/src/data/currencies.js +1073 -0
  13. package/esm/src/data/phone_patterns.d.ts +3809 -0
  14. package/esm/src/data/phone_patterns.d.ts.map +1 -0
  15. package/esm/src/data/phone_patterns.js +2325 -0
  16. package/esm/src/models/amount/amount.d.ts +10 -12
  17. package/esm/src/models/amount/amount.d.ts.map +1 -1
  18. package/esm/src/models/amount/amount.js +58 -96
  19. package/esm/src/models/bank/bank.d.ts +58 -53
  20. package/esm/src/models/bank/bank.d.ts.map +1 -1
  21. package/esm/src/models/bank/bank.js +49 -84
  22. package/esm/src/models/bank/index.d.ts +1 -1
  23. package/esm/src/models/bank/index.d.ts.map +1 -1
  24. package/esm/src/models/bank/index.js +1 -1
  25. package/esm/src/models/bank/service.d.ts +106 -0
  26. package/esm/src/models/bank/service.d.ts.map +1 -0
  27. package/esm/src/models/bank/service.js +240 -0
  28. package/esm/src/models/country/country.d.ts +568 -0
  29. package/esm/src/models/country/country.d.ts.map +1 -0
  30. package/esm/src/models/country/country.js +165 -0
  31. package/esm/src/models/country/country.test.d.ts.map +1 -0
  32. package/esm/src/models/country/index.d.ts +3 -0
  33. package/esm/src/models/country/index.d.ts.map +1 -0
  34. package/esm/src/models/country/index.js +2 -0
  35. package/esm/src/models/country/service.d.ts +75 -0
  36. package/esm/src/models/country/service.d.ts.map +1 -0
  37. package/esm/src/models/country/service.js +267 -0
  38. package/esm/src/models/currency/currency.d.ts +341 -0
  39. package/esm/src/models/currency/currency.d.ts.map +1 -0
  40. package/esm/src/models/currency/currency.js +225 -0
  41. package/esm/src/models/currency/currency.test.d.ts.map +1 -0
  42. package/esm/src/models/currency/index.d.ts +3 -0
  43. package/esm/src/models/currency/index.d.ts.map +1 -0
  44. package/esm/src/models/currency/index.js +2 -0
  45. package/esm/src/models/currency/service.d.ts +96 -0
  46. package/esm/src/models/currency/service.d.ts.map +1 -0
  47. package/esm/src/models/currency/service.js +194 -0
  48. package/esm/src/models/index.d.ts +2 -0
  49. package/esm/src/models/index.d.ts.map +1 -1
  50. package/esm/src/models/index.js +2 -0
  51. package/esm/src/models/phone_number/format.d.ts +14 -0
  52. package/esm/src/models/phone_number/format.d.ts.map +1 -0
  53. package/esm/src/models/phone_number/format.js +14 -0
  54. package/esm/src/models/phone_number/global/phone_number.d.ts +160 -0
  55. package/esm/src/models/phone_number/global/phone_number.d.ts.map +1 -0
  56. package/esm/src/models/phone_number/global/phone_number.js +453 -0
  57. package/esm/src/models/phone_number/global/phone_number.test.d.ts.map +1 -0
  58. package/esm/src/models/phone_number/global/service.d.ts +260 -0
  59. package/esm/src/models/phone_number/global/service.d.ts.map +1 -0
  60. package/esm/src/models/phone_number/global/service.js +477 -0
  61. package/esm/src/models/phone_number/global/service.test.d.ts.map +1 -0
  62. package/esm/src/models/phone_number/index.d.ts +5 -3
  63. package/esm/src/models/phone_number/index.d.ts.map +1 -1
  64. package/esm/src/models/phone_number/index.js +5 -3
  65. package/esm/src/models/phone_number/{antd_validator.d.ts → tz/antd_validator.d.ts} +2 -2
  66. package/esm/src/models/phone_number/tz/antd_validator.d.ts.map +1 -0
  67. package/esm/src/models/phone_number/{antd_validator.js → tz/antd_validator.js} +2 -2
  68. package/esm/src/models/phone_number/tz/antdvalidator.test.d.ts.map +1 -0
  69. package/esm/src/models/phone_number/tz/network_operator.d.ts.map +1 -0
  70. package/{script/src/models/phone_number → esm/src/models/phone_number/tz}/phone_number.d.ts +46 -29
  71. package/esm/src/models/phone_number/tz/phone_number.d.ts.map +1 -0
  72. package/esm/src/models/phone_number/{phone_number.js → tz/phone_number.js} +87 -41
  73. package/esm/src/models/phone_number/tz/phone_number.test.d.ts.map +1 -0
  74. package/package.json +3 -3
  75. package/script/deps/jsr.io/@std/internal/1.0.5/assertion_state.d.ts.map +1 -0
  76. package/script/deps/jsr.io/@std/testing/1.0.9/_test_suite.d.ts.map +1 -0
  77. package/script/deps/jsr.io/@std/testing/1.0.9/bdd.d.ts.map +1 -0
  78. package/script/src/{models/bank/banks.d.ts → data/banks_tz.d.ts} +1 -1
  79. package/script/src/data/banks_tz.d.ts.map +1 -0
  80. package/script/src/data/countries.d.ts +6 -0
  81. package/script/src/data/countries.d.ts.map +1 -0
  82. package/script/src/data/countries.js +976 -0
  83. package/script/src/data/currencies.d.ts +1901 -0
  84. package/script/src/data/currencies.d.ts.map +1 -0
  85. package/script/src/data/currencies.js +1075 -0
  86. package/script/src/data/phone_patterns.d.ts +3809 -0
  87. package/script/src/data/phone_patterns.d.ts.map +1 -0
  88. package/script/src/data/phone_patterns.js +2327 -0
  89. package/script/src/models/amount/amount.d.ts +10 -12
  90. package/script/src/models/amount/amount.d.ts.map +1 -1
  91. package/script/src/models/amount/amount.js +60 -98
  92. package/script/src/models/bank/bank.d.ts +58 -53
  93. package/script/src/models/bank/bank.d.ts.map +1 -1
  94. package/script/src/models/bank/bank.js +49 -87
  95. package/script/src/models/bank/index.d.ts +1 -1
  96. package/script/src/models/bank/index.d.ts.map +1 -1
  97. package/script/src/models/bank/index.js +1 -1
  98. package/script/src/models/bank/service.d.ts +106 -0
  99. package/script/src/models/bank/service.d.ts.map +1 -0
  100. package/script/src/models/bank/service.js +247 -0
  101. package/script/src/models/country/country.d.ts +568 -0
  102. package/script/src/models/country/country.d.ts.map +1 -0
  103. package/script/src/models/country/country.js +169 -0
  104. package/script/src/models/country/country.test.d.ts.map +1 -0
  105. package/script/src/models/country/index.d.ts +3 -0
  106. package/script/src/models/country/index.d.ts.map +1 -0
  107. package/script/src/models/country/index.js +18 -0
  108. package/script/src/models/country/service.d.ts +75 -0
  109. package/script/src/models/country/service.d.ts.map +1 -0
  110. package/script/src/models/country/service.js +274 -0
  111. package/script/src/models/currency/currency.d.ts +341 -0
  112. package/script/src/models/currency/currency.d.ts.map +1 -0
  113. package/script/src/models/currency/currency.js +229 -0
  114. package/script/src/models/currency/currency.test.d.ts.map +1 -0
  115. package/script/src/models/currency/index.d.ts +3 -0
  116. package/script/src/models/currency/index.d.ts.map +1 -0
  117. package/script/src/models/currency/index.js +18 -0
  118. package/script/src/models/currency/service.d.ts +96 -0
  119. package/script/src/models/currency/service.d.ts.map +1 -0
  120. package/script/src/models/currency/service.js +201 -0
  121. package/script/src/models/index.d.ts +2 -0
  122. package/script/src/models/index.d.ts.map +1 -1
  123. package/script/src/models/index.js +2 -0
  124. package/script/src/models/phone_number/format.d.ts +14 -0
  125. package/script/src/models/phone_number/format.d.ts.map +1 -0
  126. package/script/src/models/phone_number/format.js +17 -0
  127. package/script/src/models/phone_number/global/phone_number.d.ts +160 -0
  128. package/script/src/models/phone_number/global/phone_number.d.ts.map +1 -0
  129. package/script/src/models/phone_number/global/phone_number.js +457 -0
  130. package/script/src/models/phone_number/global/phone_number.test.d.ts.map +1 -0
  131. package/script/src/models/phone_number/global/service.d.ts +260 -0
  132. package/script/src/models/phone_number/global/service.d.ts.map +1 -0
  133. package/script/src/models/phone_number/global/service.js +485 -0
  134. package/script/src/models/phone_number/global/service.test.d.ts.map +1 -0
  135. package/script/src/models/phone_number/index.d.ts +5 -3
  136. package/script/src/models/phone_number/index.d.ts.map +1 -1
  137. package/script/src/models/phone_number/index.js +5 -3
  138. package/script/src/models/phone_number/{antd_validator.d.ts → tz/antd_validator.d.ts} +2 -2
  139. package/script/src/models/phone_number/tz/antd_validator.d.ts.map +1 -0
  140. package/script/src/models/phone_number/{antd_validator.js → tz/antd_validator.js} +1 -1
  141. package/script/src/models/phone_number/tz/antdvalidator.test.d.ts.map +1 -0
  142. package/script/src/models/phone_number/tz/network_operator.d.ts.map +1 -0
  143. package/{esm/src/models/phone_number → script/src/models/phone_number/tz}/phone_number.d.ts +46 -29
  144. package/script/src/models/phone_number/tz/phone_number.d.ts.map +1 -0
  145. package/script/src/models/phone_number/{phone_number.js → tz/phone_number.js} +89 -43
  146. package/script/src/models/phone_number/tz/phone_number.test.d.ts.map +1 -0
  147. package/esm/src/models/bank/banks.d.ts.map +0 -1
  148. package/esm/src/models/bank/utils.d.ts +0 -25
  149. package/esm/src/models/bank/utils.d.ts.map +0 -1
  150. package/esm/src/models/bank/utils.js +0 -35
  151. package/esm/src/models/phone_number/antd_validator.d.ts.map +0 -1
  152. package/esm/src/models/phone_number/antdvalidator.test.d.ts.map +0 -1
  153. package/esm/src/models/phone_number/network_operator.d.ts.map +0 -1
  154. package/esm/src/models/phone_number/phone_number.d.ts.map +0 -1
  155. package/esm/src/models/phone_number/phone_number.test.d.ts.map +0 -1
  156. package/script/src/models/bank/banks.d.ts.map +0 -1
  157. package/script/src/models/bank/utils.d.ts +0 -25
  158. package/script/src/models/bank/utils.d.ts.map +0 -1
  159. package/script/src/models/bank/utils.js +0 -41
  160. package/script/src/models/phone_number/antd_validator.d.ts.map +0 -1
  161. package/script/src/models/phone_number/antdvalidator.test.d.ts.map +0 -1
  162. package/script/src/models/phone_number/network_operator.d.ts.map +0 -1
  163. package/script/src/models/phone_number/phone_number.d.ts.map +0 -1
  164. package/script/src/models/phone_number/phone_number.test.d.ts.map +0 -1
  165. /package/esm/src/{models/bank/banks.js → data/banks_tz.js} +0 -0
  166. /package/esm/src/models/phone_number/{network_operator.d.ts → tz/network_operator.d.ts} +0 -0
  167. /package/esm/src/models/phone_number/{network_operator.js → tz/network_operator.js} +0 -0
  168. /package/script/src/{models/bank/banks.js → data/banks_tz.js} +0 -0
  169. /package/script/src/models/phone_number/{network_operator.d.ts → tz/network_operator.d.ts} +0 -0
  170. /package/script/src/models/phone_number/{network_operator.js → tz/network_operator.js} +0 -0
@@ -0,0 +1,453 @@
1
+ /**
2
+ * @fileoverview
3
+ *
4
+ * # Global Phone Number Management System
5
+ *
6
+ * ## Features
7
+ * 1. Parsing and validation of international format phone numbers
8
+ * 2. Support for phone numbers across countries using standardized metadata
9
+ * 3. Standardized storage in E.164 format
10
+ * 4. Formatting options for display and API use:
11
+ * - INTERNATIONAL: "+{dial_code}{compactNumber}" - Returns the number with a plus and country code
12
+ * - COMPACT: Just the compactNumber without formatting
13
+ * - NATIONAL: Not fully implemented for global numbers, returns the compact number
14
+ * - RFC3966: "tel:+{dial_code}{compactNumber}" - Returns the number in URI format
15
+ * 5. Integration with Country class for country data
16
+ */
17
+ import { Country } from "../../country/country.js";
18
+ import { GlobalPhoneNumberService, SharedDialCodeError, } from "./service.js";
19
+ import { PhoneNumberFormat } from "../format.js";
20
+ /**
21
+ * Represents a global phone number
22
+ */
23
+ export class PhoneNumber {
24
+ /**
25
+ * Private constructor to prevent direct instantiation.
26
+ * Use PhoneNumber.from() or PhoneNumber.fromWithCountry() instead.
27
+ *
28
+ * @param country - The Country object representing the phone number's country
29
+ * @param compactNumber - The phone number in compact format without country code
30
+ */
31
+ constructor(country, compactNumber) {
32
+ /** The associated country object */
33
+ Object.defineProperty(this, "_country", {
34
+ enumerable: true,
35
+ configurable: true,
36
+ writable: true,
37
+ value: void 0
38
+ });
39
+ /** The national number without country code or leading zeros */
40
+ Object.defineProperty(this, "_compactNumber", {
41
+ enumerable: true,
42
+ configurable: true,
43
+ writable: true,
44
+ value: void 0
45
+ });
46
+ this._country = country;
47
+ this._compactNumber = compactNumber;
48
+ }
49
+ /**
50
+ * Gets the Country object associated with this phone number
51
+ */
52
+ get country() {
53
+ return this._country;
54
+ }
55
+ /**
56
+ * Gets the country code (ISO) of the phone number
57
+ */
58
+ get countryCode() {
59
+ return this._country.code;
60
+ }
61
+ /**
62
+ * Gets the dial code (numeric) of the phone number
63
+ */
64
+ get dialCode() {
65
+ const metadata = GlobalPhoneNumberService.getInstance().getCountryMetadata(this.countryCode);
66
+ return metadata?.code || 0;
67
+ }
68
+ /**
69
+ * Gets the compact number (national number without formatting)
70
+ */
71
+ get compactNumber() {
72
+ return this._compactNumber;
73
+ }
74
+ /**
75
+ * Gets the full E.164 formatted number (e.g., +12025550123)
76
+ */
77
+ get formattedNumber() {
78
+ return `+${this.dialCode}${this._compactNumber}`;
79
+ }
80
+ /**
81
+ * Gets a human-readable label for this phone number
82
+ * Uses international format with spaces for readability
83
+ */
84
+ get label() {
85
+ return this.getWithFormat(PhoneNumberFormat.INTERNATIONAL);
86
+ }
87
+ /**
88
+ * Formats the phone number according to the specified format
89
+ *
90
+ * @param format - The desired format
91
+ * @returns The formatted phone number string
92
+ */
93
+ getWithFormat(format) {
94
+ switch (format) {
95
+ case PhoneNumberFormat.INTERNATIONAL:
96
+ // Format: +{dial_code}{compactNumber}
97
+ return this.formatInternational();
98
+ case PhoneNumberFormat.NATIONAL:
99
+ // Note: NATIONAL format is not fully implemented for global numbers
100
+ // Currently returns only the compact number
101
+ return this._compactNumber;
102
+ case PhoneNumberFormat.COMPACT:
103
+ // Format: Just the compactNumber
104
+ return this._compactNumber;
105
+ case PhoneNumberFormat.RFC3966:
106
+ // Format: tel:+{dial_code}{compactNumber}
107
+ return this.formatRFC3966();
108
+ default:
109
+ return this.formattedNumber;
110
+ }
111
+ }
112
+ /**
113
+ * Formats the phone number in international format
114
+ * Returns +{dial_code}{compactNumber} format
115
+ */
116
+ formatInternational() {
117
+ return `+${this.dialCode}${this._compactNumber}`;
118
+ }
119
+ /**
120
+ * Formats the phone number according to RFC3966
121
+ * Returns tel:+{dial_code}{compactNumber} format
122
+ */
123
+ formatRFC3966() {
124
+ return `tel:+${this.dialCode}${this._compactNumber}`;
125
+ }
126
+ /**
127
+ * Validates that this phone number meets the requirements for its country
128
+ * Relies entirely on pattern validation
129
+ *
130
+ * @returns True if the phone number is valid, false otherwise
131
+ */
132
+ validate() {
133
+ try {
134
+ // Validate the country first
135
+ if (!this._country.validate()) {
136
+ return false;
137
+ }
138
+ // Get the metadata for this country
139
+ const service = GlobalPhoneNumberService.getInstance();
140
+ const metadata = service.getCountryMetadata(this._country.code);
141
+ if (!metadata) {
142
+ return false;
143
+ }
144
+ // Clean the compact number to ensure it only contains digits
145
+ const compactNumber = this._compactNumber.replace(/\D/g, "");
146
+ // Check if the compact number contains only digits
147
+ const isOnlyDigits = /^\d+$/.test(compactNumber);
148
+ if (!isOnlyDigits)
149
+ return false;
150
+ // Verify required patterns exist
151
+ if (!metadata.patterns || !metadata.patterns.landline ||
152
+ !metadata.patterns.mobile) {
153
+ console.error(`Country ${this._country.code} is missing required patterns for landline or mobile`);
154
+ return false;
155
+ }
156
+ return service.validatePattern(this._country.code, compactNumber);
157
+ }
158
+ catch (e) {
159
+ console.log(e);
160
+ return false;
161
+ }
162
+ }
163
+ /**
164
+ * Creates a PhoneNumber from an international format string.
165
+ * Only accepts the international format with a leading '+'.
166
+ * Thoroughly cleans the input by removing all non-digit characters except the leading '+'.
167
+ *
168
+ * @param input - The phone number string in international format (e.g., "+1 (202) 555-0123")
169
+ * @param options - Options for handling parsing, including defaultCountry and throwOnAmbiguous
170
+ * @returns A PhoneNumber instance if parsing succeeded, undefined otherwise
171
+ * @throws SharedDialCodeError when a shared dial code is encountered and throwOnAmbiguous is true
172
+ */
173
+ static from(input, options) {
174
+ try {
175
+ if (!input || typeof input !== "string")
176
+ return undefined;
177
+ const service = GlobalPhoneNumberService.getInstance();
178
+ // Clean the input (remove all non-digits except the leading '+')
179
+ const hasPlus = input.trim().startsWith("+");
180
+ const digitsOnly = input.replace(/\D/g, "");
181
+ const cleanedInput = hasPlus ? `+${digitsOnly}` : digitsOnly;
182
+ if (cleanedInput.length === 0)
183
+ return undefined;
184
+ // Must start with + for international format
185
+ if (!cleanedInput.startsWith("+"))
186
+ return undefined;
187
+ // Extract the dial code information
188
+ const dialCodeInfo = service.extractDialCode(cleanedInput);
189
+ if (!dialCodeInfo)
190
+ return undefined;
191
+ // Check if this is a shared dial code
192
+ if (dialCodeInfo.isShared) {
193
+ // Handle shared dial code according to options
194
+ if (options?.defaultCountry) {
195
+ // Try to use the provided default country
196
+ const defaultCountry = typeof options.defaultCountry === "string"
197
+ ? Country.fromCode(options.defaultCountry)
198
+ : options.defaultCountry;
199
+ if (defaultCountry) {
200
+ // Verify that the default country actually uses this dial code
201
+ const metadata = service.getCountryMetadata(defaultCountry.code);
202
+ if (metadata && metadata.code.toString() === dialCodeInfo.dialCode) {
203
+ // Create and validate phone number with the default country
204
+ const phoneNumber = new PhoneNumber(defaultCountry, dialCodeInfo.nationalNumber);
205
+ if (phoneNumber.validate()) {
206
+ return phoneNumber;
207
+ }
208
+ }
209
+ }
210
+ }
211
+ // If we get here, either no default country was provided, or it didn't validate
212
+ if (options?.throwOnAmbiguous) {
213
+ throw new SharedDialCodeError(dialCodeInfo.dialCode, dialCodeInfo.possibleCountries);
214
+ }
215
+ // Try each possible country
216
+ for (const countryCode of dialCodeInfo.possibleCountries) {
217
+ const country = Country.fromCode(countryCode);
218
+ if (!country)
219
+ continue;
220
+ const phoneNumber = new PhoneNumber(country, dialCodeInfo.nationalNumber);
221
+ if (phoneNumber.validate()) {
222
+ return phoneNumber;
223
+ }
224
+ }
225
+ // If we get here, we couldn't validate with any country
226
+ return undefined;
227
+ }
228
+ else {
229
+ // For non-shared dial codes, get the country
230
+ const countryCode = dialCodeInfo.possibleCountries[0];
231
+ if (!countryCode)
232
+ return undefined;
233
+ const country = Country.fromCode(countryCode);
234
+ if (!country)
235
+ return undefined;
236
+ // Create the phone number
237
+ const phoneNumber = new PhoneNumber(country, dialCodeInfo.nationalNumber);
238
+ // Validate and return
239
+ if (phoneNumber.validate()) {
240
+ return phoneNumber;
241
+ }
242
+ }
243
+ return undefined;
244
+ }
245
+ catch (e) {
246
+ if (e instanceof SharedDialCodeError) {
247
+ throw e; // Re-throw the shared dial code error
248
+ }
249
+ console.log(e);
250
+ return undefined;
251
+ }
252
+ }
253
+ /**
254
+ * Creates a PhoneNumber from various formats when a country is explicitly provided.
255
+ * Supports multiple input formats:
256
+ * - International format with plus and country code: "+{code}{number}" (e.g., "+12025550123")
257
+ * - Format with just country code: "{code}{number}" (e.g., "12025550123")
258
+ * - Local format with leading zero: "0{number}" (e.g., "02025550123")
259
+ * - Just the national number: "{number}" (e.g., "2025550123")
260
+ *
261
+ * Thoroughly cleans the input by removing all non-digit characters except the leading '+'.
262
+ *
263
+ * @param input - The phone number string in any format
264
+ * @param country - The Country object for this phone number
265
+ * @returns A PhoneNumber instance if parsing succeeded, undefined otherwise
266
+ */
267
+ static fromWithCountry(input, country) {
268
+ try {
269
+ if (!input || typeof input !== "string" || !country || !Country.is(country))
270
+ return undefined;
271
+ // Clean the input (remove all non-digits except the leading '+')
272
+ const hasPlus = input.trim().startsWith("+");
273
+ const digitsOnly = input.replace(/\D/g, "");
274
+ const cleanedInput = hasPlus ? `+${digitsOnly}` : digitsOnly;
275
+ if (cleanedInput.length === 0)
276
+ return undefined;
277
+ // Get the metadata for this country
278
+ const metadata = GlobalPhoneNumberService.getInstance()
279
+ .getCountryMetadata(country.code);
280
+ if (!metadata)
281
+ return undefined;
282
+ const dialCode = metadata.code.toString();
283
+ let nationalNumber;
284
+ // Handle different input formats
285
+ if (cleanedInput.startsWith("+")) {
286
+ // Check if the number actually starts with the correct dial code
287
+ const numberWithoutPlus = cleanedInput.substring(1);
288
+ if (numberWithoutPlus.startsWith(dialCode)) {
289
+ // International format with + and country code: +12025550123
290
+ nationalNumber = numberWithoutPlus.substring(dialCode.length);
291
+ }
292
+ else {
293
+ // Has a plus but wrong dial code for the specified country
294
+ return undefined;
295
+ }
296
+ }
297
+ else if (cleanedInput.startsWith(dialCode)) {
298
+ // Format with just country code: 12025550123
299
+ nationalNumber = cleanedInput.substring(dialCode.length);
300
+ }
301
+ else if (cleanedInput.startsWith("0")) {
302
+ // Local format with leading zero: 02025550123
303
+ nationalNumber = cleanedInput.substring(1);
304
+ }
305
+ else {
306
+ // Assume it's just the national number: 2025550123
307
+ nationalNumber = cleanedInput;
308
+ }
309
+ // Check if we have a non-empty national number
310
+ if (nationalNumber.length === 0)
311
+ return undefined;
312
+ // Create and validate the phone number
313
+ const phoneNumber = new PhoneNumber(country, nationalNumber);
314
+ if (!phoneNumber.validate())
315
+ return undefined;
316
+ return phoneNumber;
317
+ }
318
+ catch (e) {
319
+ console.log(e);
320
+ return undefined;
321
+ }
322
+ }
323
+ /**
324
+ * Checks if a string can be constructed into a valid phone number.
325
+ *
326
+ * @param input - The string to validate
327
+ * @param options - Options for handling parsing
328
+ * @returns True if the input can be parsed into a valid phone number, false otherwise
329
+ */
330
+ static canConstruct(input, options) {
331
+ if (!input || typeof input !== "string")
332
+ return false;
333
+ try {
334
+ const hasPlus = input.trim().startsWith("+");
335
+ const digitsOnly = input.replace(/\D/g, "");
336
+ const cleanedInput = hasPlus ? `+${digitsOnly}` : digitsOnly;
337
+ if (cleanedInput.length === 0)
338
+ return false;
339
+ const phone = PhoneNumber.from(cleanedInput, options);
340
+ return phone !== undefined;
341
+ }
342
+ catch (e) {
343
+ // If throwOnAmbiguous is true and we got a SharedDialCodeError,
344
+ // technically the phone number is constructible with a country
345
+ if (e instanceof SharedDialCodeError) {
346
+ return true;
347
+ }
348
+ return false;
349
+ }
350
+ }
351
+ /**
352
+ * Checks if a string can be constructed into a valid phone number with a given country.
353
+ *
354
+ * @param input - The string to validate
355
+ * @param country - The Country object to use
356
+ * @returns True if the input can be parsed into a valid phone number, false otherwise
357
+ */
358
+ static canConstructWithCountry(input, country) {
359
+ if (!input || typeof input !== "string" || !country)
360
+ return false;
361
+ const hasPlus = input.trim().startsWith("+");
362
+ const digitsOnly = input.replace(/\D/g, "");
363
+ const cleanedInput = hasPlus ? `+${digitsOnly}` : digitsOnly;
364
+ if (cleanedInput.length === 0)
365
+ return false;
366
+ const phone = PhoneNumber.fromWithCountry(cleanedInput, country);
367
+ return phone !== undefined;
368
+ }
369
+ /**
370
+ * Type guard to check if an unknown object is a valid PhoneNumber instance.
371
+ *
372
+ * @param obj - The object to check
373
+ * @returns Type predicate indicating if the object is a valid PhoneNumber
374
+ */
375
+ static is(obj) {
376
+ if (!obj || typeof obj !== "object")
377
+ return false;
378
+ const maybePhone = obj;
379
+ // Check required properties
380
+ if (typeof maybePhone._compactNumber !== "string") {
381
+ return false;
382
+ }
383
+ // Validate the country
384
+ if (!maybePhone._country || !Country.is(maybePhone._country)) {
385
+ return false;
386
+ }
387
+ // Basic structural validation passed
388
+ const country = maybePhone._country;
389
+ const compactNumber = maybePhone._compactNumber;
390
+ // Verify it has the right structure - doesn't call validate()
391
+ return (typeof compactNumber === "string" &&
392
+ /^\d+$/.test(compactNumber) &&
393
+ Country.is(country));
394
+ }
395
+ /**
396
+ * Attempts to extract the country from a phone number string in international format.
397
+ *
398
+ * For shared dial codes, this will return undefined unless a default country is provided.
399
+ *
400
+ * @param input - The phone number string to parse (must be in international format)
401
+ * @param options - Options for handling shared dial codes
402
+ * @returns The Country object if found, undefined if ambiguous or not found
403
+ * @throws SharedDialCodeError when a shared dial code is encountered and throwOnAmbiguous is true
404
+ */
405
+ static getCountry(input, options) {
406
+ try {
407
+ // Clean the input first
408
+ const hasPlus = input.trim().startsWith("+");
409
+ const digitsOnly = input.replace(/\D/g, "");
410
+ const cleanedInput = hasPlus ? `+${digitsOnly}` : digitsOnly;
411
+ if (!cleanedInput.startsWith("+"))
412
+ return undefined;
413
+ const service = GlobalPhoneNumberService.getInstance();
414
+ const dialCodeInfo = service.extractDialCode(cleanedInput);
415
+ if (!dialCodeInfo)
416
+ return undefined;
417
+ // Handle shared dial codes
418
+ if (dialCodeInfo.isShared) {
419
+ // If a default country is provided, try to use it
420
+ if (options?.defaultCountry) {
421
+ const defaultCountry = typeof options.defaultCountry === "string"
422
+ ? Country.fromCode(options.defaultCountry)
423
+ : options.defaultCountry;
424
+ if (defaultCountry) {
425
+ // Verify that the default country actually uses this dial code
426
+ const metadata = service.getCountryMetadata(defaultCountry.code);
427
+ if (metadata && metadata.code.toString() === dialCodeInfo.dialCode) {
428
+ return defaultCountry;
429
+ }
430
+ }
431
+ }
432
+ // If we get here, either no default country was provided, or it was invalid
433
+ if (options?.throwOnAmbiguous) {
434
+ throw new SharedDialCodeError(dialCodeInfo.dialCode, dialCodeInfo.possibleCountries);
435
+ }
436
+ // Return undefined for ambiguous dial codes
437
+ return undefined;
438
+ }
439
+ else {
440
+ // For non-shared dial codes, get the country
441
+ const countryCode = dialCodeInfo.possibleCountries[0];
442
+ return countryCode ? Country.fromCode(countryCode) : undefined;
443
+ }
444
+ }
445
+ catch (e) {
446
+ if (e instanceof SharedDialCodeError) {
447
+ throw e; // Re-throw the shared dial code error
448
+ }
449
+ console.log(e);
450
+ return undefined;
451
+ }
452
+ }
453
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phone_number.test.d.ts","sourceRoot":"","sources":["../../../../../src/src/models/phone_number/global/phone_number.test.ts"],"names":[],"mappings":""}