@temboplus/frontend-core 0.2.1 → 0.2.3

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