@temboplus/afloat 0.1.70 → 0.1.72
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/dist/features/contact/contact.api-contract.d.ts +0 -18
- package/dist/features/contact/contact.dtos.d.ts +0 -6
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api/base-repository.d.ts +1 -1
- package/dist/models/contact-info.model.d.ts +78 -53
- package/dist/models/contact.model.d.ts +0 -15
- package/package.json +10 -12
- package/dist/index.cjs.js +0 -4
- package/dist/index.cjs.js.map +0 -1
- package/dist/index.esm.js +0 -4
- package/dist/index.esm.js.map +0 -1
|
@@ -108,7 +108,7 @@ export declare class BaseRepository<TContract extends AppRouter> {
|
|
|
108
108
|
* // - x-request-id: "uuid-v4-string"
|
|
109
109
|
* ```
|
|
110
110
|
*/
|
|
111
|
-
get client(): { [TKey in keyof TContract]: TContract[TKey] extends import("@ts-rest/core").AppRoute ? import("@ts-rest/core").AppRouteFunction<TContract[TKey], InitClientArgs, import("@ts-rest/core").PartialClientInferRequest<TContract[TKey], InitClientArgs>> : TContract[TKey] extends AppRouter ? TContract[TKey] extends infer T extends AppRouter ? { [
|
|
111
|
+
get client(): { [TKey in keyof TContract]: TContract[TKey] extends import("@ts-rest/core").AppRoute ? import("@ts-rest/core").AppRouteFunction<TContract[TKey], InitClientArgs, import("@ts-rest/core").PartialClientInferRequest<TContract[TKey], InitClientArgs>> : TContract[TKey] extends AppRouter ? TContract[TKey] extends infer T extends AppRouter ? { [TKey_2 in keyof T]: T[TKey_2] extends import("@ts-rest/core").AppRoute ? import("@ts-rest/core").AppRouteFunction<T[TKey_2], TClientArgs, import("@ts-rest/core").PartialClientInferRequest<T[TKey_2], TClientArgs>> : T[TKey_2] extends AppRouter ? T[TKey_2] extends infer T_1 extends AppRouter ? { [TKey_3 in keyof T_1]: T_1[TKey_3] extends import("@ts-rest/core").AppRoute ? import("@ts-rest/core").AppRouteFunction<T_1[TKey_3], TClientArgs, import("@ts-rest/core").PartialClientInferRequest<T_1[TKey_3], TClientArgs>> : T_1[TKey_3] extends AppRouter ? T_1[TKey_3] extends infer T_2 extends AppRouter ? { [TKey_4 in keyof T_2]: T_2[TKey_4] extends import("@ts-rest/core").AppRoute ? import("@ts-rest/core").AppRouteFunction<T_2[TKey_4], TClientArgs, import("@ts-rest/core").PartialClientInferRequest<T_2[TKey_4], TClientArgs>> : T_2[TKey_4] extends AppRouter ? T_2[TKey_4] extends infer T_3 extends AppRouter ? { [TKey_5 in keyof T_3]: T_3[TKey_5] extends import("@ts-rest/core").AppRoute ? import("@ts-rest/core").AppRouteFunction<T_3[TKey_5], TClientArgs, import("@ts-rest/core").PartialClientInferRequest<T_3[TKey_5], TClientArgs>> : T_3[TKey_5] extends AppRouter ? T_3[TKey_5] extends infer T_4 extends AppRouter ? { [TKey_6 in keyof T_4]: T_4[TKey_6] extends import("@ts-rest/core").AppRoute ? import("@ts-rest/core").AppRouteFunction<T_4[TKey_6], TClientArgs, import("@ts-rest/core").PartialClientInferRequest<T_4[TKey_6], TClientArgs>> : T_4[TKey_6] extends AppRouter ? T_4[TKey_6] extends infer T_5 extends AppRouter ? { [TKey_7 in keyof T_5]: T_5[TKey_7] extends import("@ts-rest/core").AppRoute ? import("@ts-rest/core").AppRouteFunction<T_5[TKey_7], TClientArgs, import("@ts-rest/core").PartialClientInferRequest<T_5[TKey_7], TClientArgs>> : T_5[TKey_7] extends AppRouter ? T_5[TKey_7] extends infer T_6 extends AppRouter ? { [TKey_8 in keyof T_6]: T_6[TKey_8] extends import("@ts-rest/core").AppRoute ? import("@ts-rest/core").AppRouteFunction<T_6[TKey_8], TClientArgs, import("@ts-rest/core").PartialClientInferRequest<T_6[TKey_8], TClientArgs>> : T_6[TKey_8] extends AppRouter ? T_6[TKey_8] extends infer T_7 extends AppRouter ? { [TKey_9 in keyof T_7]: T_7[TKey_9] extends import("@ts-rest/core").AppRoute ? import("@ts-rest/core").AppRouteFunction<T_7[TKey_9], TClientArgs, import("@ts-rest/core").PartialClientInferRequest<T_7[TKey_9], TClientArgs>> : T_7[TKey_9] extends AppRouter ? T_7[TKey_9] extends infer T_8 extends AppRouter ? { [TKey_10 in keyof T_8]: T_8[TKey_10] extends import("@ts-rest/core").AppRoute ? import("@ts-rest/core").AppRouteFunction<T_8[TKey_10], TClientArgs, import("@ts-rest/core").PartialClientInferRequest<T_8[TKey_10], TClientArgs>> : T_8[TKey_10] extends AppRouter ? T_8[TKey_10] extends infer T_9 extends AppRouter ? { [TKey_11 in keyof T_9]: T_9[TKey_11] extends import("@ts-rest/core").AppRoute ? import("@ts-rest/core").AppRouteFunction<T_9[TKey_11], TClientArgs, import("@ts-rest/core").PartialClientInferRequest<T_9[TKey_11], TClientArgs>> : T_9[TKey_11] extends AppRouter ? /*elided*/ any : never; } : never : never; } : never : never; } : never : never; } : never : never; } : never : never; } : never : never; } : never : never; } : never : never; } : never : never; } : never : never; };
|
|
112
112
|
/**
|
|
113
113
|
* Updates the authentication token used by this repository.
|
|
114
114
|
*
|
|
@@ -9,11 +9,15 @@ import type { BankSwiftCode, MNOId } from "@temboplus/frontend-core";
|
|
|
9
9
|
* Serves as the foundation for type-safe contact handling throughout the application,
|
|
10
10
|
* ensuring consistent behavior between mobile money and bank transfer contacts.
|
|
11
11
|
*
|
|
12
|
+
* **Country Code Handling:**
|
|
13
|
+
* The country code is always derived from the underlying domain objects (PhoneNumber or Bank)
|
|
14
|
+
* rather than being passed as a separate parameter, ensuring consistency and single source of truth.
|
|
15
|
+
*
|
|
12
16
|
* @abstract
|
|
13
17
|
* @class BaseContactInfo
|
|
14
18
|
*
|
|
15
19
|
* @property {ContactType} type - The type of contact (either "Mobile" or "Bank")
|
|
16
|
-
* @property {ISO2CountryCode} countryCode - The ISO2 country code
|
|
20
|
+
* @property {ISO2CountryCode} countryCode - The ISO2 country code derived from PhoneNumber or Bank
|
|
17
21
|
*
|
|
18
22
|
* @example
|
|
19
23
|
* ```typescript
|
|
@@ -25,6 +29,7 @@ import type { BankSwiftCode, MNOId } from "@temboplus/frontend-core";
|
|
|
25
29
|
* function processContact(contact: BaseContactInfo) {
|
|
26
30
|
* console.log(`Processing ${contact.type} contact: ${contact.displayName}`);
|
|
27
31
|
* console.log(`Channel: ${contact.channelDisplayName}`);
|
|
32
|
+
* console.log(`Country: ${contact.countryCode}`); // Always available
|
|
28
33
|
* }
|
|
29
34
|
* ```
|
|
30
35
|
*/
|
|
@@ -37,7 +42,7 @@ declare abstract class BaseContactInfo {
|
|
|
37
42
|
*
|
|
38
43
|
* @protected
|
|
39
44
|
* @param {ContactType} type - The type of contact to create ("Mobile" or "Bank")
|
|
40
|
-
* @param {ISO2CountryCode} countryCode - The ISO2 country code
|
|
45
|
+
* @param {ISO2CountryCode} countryCode - The ISO2 country code derived from domain objects
|
|
41
46
|
*/
|
|
42
47
|
constructor(type: ContactType, countryCode: ISO2CountryCode);
|
|
43
48
|
/**
|
|
@@ -117,12 +122,14 @@ declare abstract class BaseContactInfo {
|
|
|
117
122
|
*
|
|
118
123
|
* This class properly delegates MNO-related logic to country-specific implementations,
|
|
119
124
|
* supporting both countries with Mobile Number Portability (MNP) and those without.
|
|
125
|
+
* The country code is always derived from the PhoneNumber object, ensuring consistency.
|
|
120
126
|
*
|
|
121
127
|
* **Key Features:**
|
|
122
128
|
* - Automatic MNO detection for countries without MNP (e.g., Tanzania)
|
|
123
129
|
* - Explicit MNO requirement for countries with MNP (e.g., Kenya)
|
|
124
130
|
* - Country-specific validation through MNOUtils delegation
|
|
125
131
|
* - Comprehensive error handling with structured context
|
|
132
|
+
* - Country code derived from PhoneNumber (single source of truth)
|
|
126
133
|
*
|
|
127
134
|
* **MNP Handling:**
|
|
128
135
|
* - **Tanzania (no MNP)**: MNO is always auto-detected from phone number prefix, ignoring any provided MNO
|
|
@@ -140,6 +147,7 @@ declare abstract class BaseContactInfo {
|
|
|
140
147
|
* // Tanzania - MNO auto-detected from prefix (ignores provided MNO)
|
|
141
148
|
* const tzContact = new MobileContactInfo("John Doe", tzPhoneNumber);
|
|
142
149
|
* console.log(tzContact.channel); // "VODACOM" (auto-detected)
|
|
150
|
+
* console.log(tzContact.countryCode); // "TZ" (from phoneNumber)
|
|
143
151
|
*
|
|
144
152
|
* // Tanzania - Even with explicit MNO, it's auto-detected from prefix
|
|
145
153
|
* const tzExplicit = new MobileContactInfo("John Doe", tzPhoneNumber, TZMNOId.AIRTEL);
|
|
@@ -147,6 +155,7 @@ declare abstract class BaseContactInfo {
|
|
|
147
155
|
*
|
|
148
156
|
* // Kenya - MNO must be explicit due to MNP
|
|
149
157
|
* const keContact = new MobileContactInfo("Jane Smith", kePhoneNumber, KEMNOId.SAFARICOM);
|
|
158
|
+
* console.log(keContact.countryCode); // "KE" (from phoneNumber)
|
|
150
159
|
*
|
|
151
160
|
* // Kenya - This would throw an error (MNO required)
|
|
152
161
|
* // const keContact = new MobileContactInfo("Jane Smith", kePhoneNumber); // ❌ Error
|
|
@@ -164,12 +173,13 @@ export declare class MobileContactInfo extends BaseContactInfo {
|
|
|
164
173
|
* **Validation Process:**
|
|
165
174
|
* 1. Validates name is non-empty
|
|
166
175
|
* 2. Validates phone number structure
|
|
167
|
-
* 3.
|
|
176
|
+
* 3. Extracts country code from PhoneNumber object
|
|
177
|
+
* 4. Handles MNO validation based on country MNP status:
|
|
168
178
|
* - **Countries with MNP (KE)**: Requires explicit MNO, validates it's valid for country
|
|
169
179
|
* - **Countries without MNP (TZ)**: Always auto-detects MNO from phone number prefix (ignores provided MNO)
|
|
170
180
|
*
|
|
171
181
|
* @param {string} name - The contact's personal name (required, non-empty)
|
|
172
|
-
* @param {PhoneNumber} phoneNumber - The validated phone number object
|
|
182
|
+
* @param {PhoneNumber} phoneNumber - The validated phone number object (contains country code)
|
|
173
183
|
* @param {MNOId} [mnoId] - MNO ID. Required for MNP countries (KE), ignored for non-MNP countries (TZ)
|
|
174
184
|
*
|
|
175
185
|
* @throws {ContactInfoError} When any validation fails:
|
|
@@ -199,21 +209,20 @@ export declare class MobileContactInfo extends BaseContactInfo {
|
|
|
199
209
|
/**
|
|
200
210
|
* Creates a MobileContactInfo instance from a ContactDTO object.
|
|
201
211
|
* Handles validation and MNO extraction from the DTO's channel field.
|
|
212
|
+
* The country code is automatically derived from the parsed phone number.
|
|
202
213
|
*
|
|
203
214
|
* **Process:**
|
|
204
215
|
* 1. Validates DTO type is "Mobile"
|
|
205
|
-
* 2.
|
|
206
|
-
* 3.
|
|
207
|
-
* 4. Handles MNO based on country MNP status:
|
|
216
|
+
* 2. Parses phone number (extracts country code from E164 format)
|
|
217
|
+
* 3. Handles MNO based on country MNP status:
|
|
208
218
|
* - **MNP countries**: Uses channel field (required)
|
|
209
219
|
* - **Non-MNP countries**: Auto-detects from phone number (ignores channel field)
|
|
210
|
-
*
|
|
220
|
+
* 4. Delegates to constructor for final validation
|
|
211
221
|
*
|
|
212
222
|
* @static
|
|
213
223
|
* @param {ContactDTO} info - The contact data transfer object
|
|
214
224
|
* @param {string} info.type - Must be "Mobile"
|
|
215
|
-
* @param {string} info.accountNo - The phone number string to parse
|
|
216
|
-
* @param {string} info.countryCode - ISO2 country code
|
|
225
|
+
* @param {string} info.accountNo - The phone number string to parse (should be E164 format)
|
|
217
226
|
* @param {string} info.displayName - The contact's name
|
|
218
227
|
* @param {string} [info.channel] - MNO ID (required for MNP countries, ignored for non-MNP countries)
|
|
219
228
|
*
|
|
@@ -225,7 +234,6 @@ export declare class MobileContactInfo extends BaseContactInfo {
|
|
|
225
234
|
* const tzContactDTO = {
|
|
226
235
|
* type: "Mobile",
|
|
227
236
|
* accountNo: "+255712345678", // Vodacom prefix
|
|
228
|
-
* countryCode: "TZ",
|
|
229
237
|
* displayName: "John Doe",
|
|
230
238
|
* channel: "AIRTEL" // This will be ignored, Vodacom will be auto-detected
|
|
231
239
|
* };
|
|
@@ -234,36 +242,39 @@ export declare class MobileContactInfo extends BaseContactInfo {
|
|
|
234
242
|
* const keContactDTO = {
|
|
235
243
|
* type: "Mobile",
|
|
236
244
|
* accountNo: "+254712345678",
|
|
237
|
-
* countryCode: "KE",
|
|
238
245
|
* displayName: "Jane Smith",
|
|
239
246
|
* channel: "SAFARICOM" // Required for Kenya
|
|
240
247
|
* };
|
|
241
248
|
*
|
|
242
249
|
* const tzContact = MobileContactInfo.fromContactDTO(tzContactDTO);
|
|
243
250
|
* console.log(tzContact?.channelId); // "VODACOM" (not "AIRTEL")
|
|
251
|
+
* console.log(tzContact?.countryCode); // "TZ" (from phone number)
|
|
244
252
|
*
|
|
245
253
|
* const keContact = MobileContactInfo.fromContactDTO(keContactDTO);
|
|
246
254
|
* console.log(keContact?.channelId); // "SAFARICOM"
|
|
255
|
+
* console.log(keContact?.countryCode); // "KE" (from phone number)
|
|
247
256
|
* ```
|
|
248
257
|
*/
|
|
249
258
|
static fromContactDTO(info: ContactDTO): MobileContactInfo | undefined;
|
|
250
259
|
/**
|
|
251
260
|
* Creates a MobileContactInfo instance from a PayoutDTO object.
|
|
252
261
|
* Extracts mobile contact information from payout data structure.
|
|
262
|
+
* The country code is derived from the parsed phone number.
|
|
253
263
|
*
|
|
254
264
|
* **Process:**
|
|
255
|
-
* 1. Validates country code format
|
|
256
|
-
* 2. Parses phone number from msisdn field
|
|
257
|
-
* 3.
|
|
265
|
+
* 1. Validates country code format in DTO
|
|
266
|
+
* 2. Parses phone number from msisdn field (uses DTO country as hint)
|
|
267
|
+
* 3. Uses phone number's country code (derived from E164 format)
|
|
268
|
+
* 4. Handles MNO based on country MNP status:
|
|
258
269
|
* - **MNP countries**: Uses channel field (required)
|
|
259
270
|
* - **Non-MNP countries**: Auto-detects from phone number (ignores channel field)
|
|
260
|
-
*
|
|
261
|
-
*
|
|
271
|
+
* 5. Uses payeeName as the contact name
|
|
272
|
+
* 6. Delegates to constructor for validation
|
|
262
273
|
*
|
|
263
274
|
* @static
|
|
264
275
|
* @param {PayoutDTO} info - The payout data transfer object
|
|
265
|
-
* @param {string} info.msisdn - The phone number in
|
|
266
|
-
* @param {string} info.countryCode - ISO2 country code
|
|
276
|
+
* @param {string} info.msisdn - The phone number in E164 or local format
|
|
277
|
+
* @param {string} info.countryCode - ISO2 country code (used as parsing hint)
|
|
267
278
|
* @param {string} info.payeeName - The recipient's name
|
|
268
279
|
* @param {string} [info.channel] - MNO ID (required for MNP countries, ignored for non-MNP countries)
|
|
269
280
|
*
|
|
@@ -289,6 +300,7 @@ export declare class MobileContactInfo extends BaseContactInfo {
|
|
|
289
300
|
*
|
|
290
301
|
* const tzContact = MobileContactInfo.fromPayoutDTO(tzPayoutDTO);
|
|
291
302
|
* console.log(tzContact?.channelName); // "M-Pesa" (Vodacom's service)
|
|
303
|
+
* console.log(tzContact?.countryCode); // "TZ" (from phoneNumber)
|
|
292
304
|
* ```
|
|
293
305
|
*/
|
|
294
306
|
static fromPayoutDTO(info: PayoutDTO): MobileContactInfo | undefined;
|
|
@@ -317,6 +329,7 @@ export declare class MobileContactInfo extends BaseContactInfo {
|
|
|
317
329
|
* console.log(unknownData.name); // ✅ Type-safe access
|
|
318
330
|
* console.log(unknownData.phoneNumber.e164Format); // ✅ Type-safe
|
|
319
331
|
* console.log(unknownData.mnoId); // ✅ Type-safe
|
|
332
|
+
* console.log(unknownData.countryCode); // ✅ Type-safe (from phoneNumber)
|
|
320
333
|
* } else {
|
|
321
334
|
* console.log("Invalid MobileContactInfo structure");
|
|
322
335
|
* }
|
|
@@ -414,15 +427,15 @@ export declare class MobileContactInfo extends BaseContactInfo {
|
|
|
414
427
|
get accountName(): string;
|
|
415
428
|
/**
|
|
416
429
|
* Gets the phone number formatted for display and storage.
|
|
417
|
-
* Returns the number in
|
|
430
|
+
* Returns the number in e164 format (with + prefix).
|
|
418
431
|
*
|
|
419
432
|
* @override
|
|
420
|
-
* @returns {string} Phone number in
|
|
433
|
+
* @returns {string} Phone number in e164 format (e.g., "+255712345678")
|
|
421
434
|
*
|
|
422
435
|
* @example
|
|
423
436
|
* ```typescript
|
|
424
437
|
* const contact = new MobileContactInfo("John", phoneNumber);
|
|
425
|
-
* console.log(contact.
|
|
438
|
+
* console.log(contact.accountNumber); // "+255712345678"
|
|
426
439
|
* ```
|
|
427
440
|
*/
|
|
428
441
|
get accountNumber(): string;
|
|
@@ -456,11 +469,11 @@ export declare class MobileContactInfo extends BaseContactInfo {
|
|
|
456
469
|
* @example
|
|
457
470
|
* ```typescript
|
|
458
471
|
* const contact = new MobileContactInfo("John", tzPhone, TZMNOId.VODACOM);
|
|
459
|
-
* console.log(contact.
|
|
472
|
+
* console.log(contact.channelId); // "VODACOM" (for MNP countries)
|
|
460
473
|
*
|
|
461
474
|
* // For non-MNP countries, always returns auto-detected value
|
|
462
475
|
* const contact2 = new MobileContactInfo("John", tzPhone, TZMNOId.AIRTEL); // AIRTEL ignored
|
|
463
|
-
* console.log(contact2.
|
|
476
|
+
* console.log(contact2.channelId); // "VODACOM" (auto-detected from phone prefix)
|
|
464
477
|
* ```
|
|
465
478
|
*/
|
|
466
479
|
get channelId(): MNOId;
|
|
@@ -479,14 +492,14 @@ export declare class MobileContactInfo extends BaseContactInfo {
|
|
|
479
492
|
* @example
|
|
480
493
|
* ```typescript
|
|
481
494
|
* const vodacomContact = new MobileContactInfo("John", tzPhone, TZMNOId.VODACOM);
|
|
482
|
-
* console.log(vodacomContact.
|
|
495
|
+
* console.log(vodacomContact.channelName); // "M-Pesa"
|
|
483
496
|
*
|
|
484
497
|
* const safaricomContact = new MobileContactInfo("Jane", kePhone, KEMNOId.SAFARICOM);
|
|
485
|
-
* console.log(safaricomContact.
|
|
498
|
+
* console.log(safaricomContact.channelName); // "M-Pesa"
|
|
486
499
|
*
|
|
487
500
|
* // For non-MNP countries, shows auto-detected service regardless of provided MNO
|
|
488
501
|
* const tzContact = new MobileContactInfo("Bob", tzVodacomPhone, TZMNOId.AIRTEL); // AIRTEL ignored
|
|
489
|
-
* console.log(tzContact.
|
|
502
|
+
* console.log(tzContact.channelName); // "M-Pesa" (Vodacom's service, auto-detected)
|
|
490
503
|
* ```
|
|
491
504
|
*
|
|
492
505
|
* @remarks
|
|
@@ -498,6 +511,7 @@ export declare class MobileContactInfo extends BaseContactInfo {
|
|
|
498
511
|
/**
|
|
499
512
|
* Implementation of BaseContactInfo for bank account contacts.
|
|
500
513
|
* Handles storage, validation, and display of contact details specific to bank transfers.
|
|
514
|
+
* The country code is automatically derived from the Bank object.
|
|
501
515
|
*
|
|
502
516
|
* This class provides comprehensive validation for bank account information including
|
|
503
517
|
* SWIFT code validation, account name verification, and account number format checking.
|
|
@@ -507,6 +521,7 @@ export declare class MobileContactInfo extends BaseContactInfo {
|
|
|
507
521
|
* - Account name format validation
|
|
508
522
|
* - Account number format validation (country-specific rules)
|
|
509
523
|
* - Integration with Bank service for institution data
|
|
524
|
+
* - Country code derived from Bank (single source of truth)
|
|
510
525
|
*
|
|
511
526
|
* @extends BaseContactInfo
|
|
512
527
|
* @class BankContactInfo
|
|
@@ -521,10 +536,11 @@ export declare class MobileContactInfo extends BaseContactInfo {
|
|
|
521
536
|
* const bank = Bank.from("CORUTZTZ", "TZ"); // CRDB Bank
|
|
522
537
|
* const contact = new BankContactInfo("John Doe", bank, "0150123456789");
|
|
523
538
|
*
|
|
524
|
-
* console.log(contact.
|
|
525
|
-
* console.log(contact.
|
|
526
|
-
* console.log(contact.
|
|
527
|
-
* console.log(contact.
|
|
539
|
+
* console.log(contact.channelId); // "CORUTZTZ" (SWIFT code)
|
|
540
|
+
* console.log(contact.channelName); // "CRDB" (bank short name)
|
|
541
|
+
* console.log(contact.accountName); // "John Doe"
|
|
542
|
+
* console.log(contact.accountNumber); // "0150123456789"
|
|
543
|
+
* console.log(contact.countryCode); // "TZ" (from bank)
|
|
528
544
|
* ```
|
|
529
545
|
*
|
|
530
546
|
* @throws {ContactInfoError} When validation fails (invalid account name, number, or bank)
|
|
@@ -535,14 +551,16 @@ export declare class BankContactInfo extends BaseContactInfo {
|
|
|
535
551
|
readonly accNo: string;
|
|
536
552
|
/**
|
|
537
553
|
* Creates a new bank contact with comprehensive validation.
|
|
554
|
+
* The country code is automatically extracted from the Bank object.
|
|
538
555
|
*
|
|
539
556
|
* **Validation Process:**
|
|
540
|
-
* 1. **
|
|
541
|
-
* 2. **Account
|
|
542
|
-
* 3. **
|
|
557
|
+
* 1. **Country code extraction**: Derived from bank.countryCode
|
|
558
|
+
* 2. **Account name validation**: Checks format and character requirements
|
|
559
|
+
* 3. **Account number validation**: Validates format per country banking rules
|
|
560
|
+
* 4. **Bank validation**: Ensures bank object is valid and contains required data
|
|
543
561
|
*
|
|
544
562
|
* @param {string} accName - The bank account holder's name (must pass BankValidation.validateAccountName)
|
|
545
|
-
* @param {Bank} bank - The bank institution object (must be valid Bank instance)
|
|
563
|
+
* @param {Bank} bank - The bank institution object (must be valid Bank instance with countryCode)
|
|
546
564
|
* @param {string} accNo - The bank account number (must pass country-specific validation)
|
|
547
565
|
*
|
|
548
566
|
* @throws {ContactInfoError} When validation fails:
|
|
@@ -556,6 +574,7 @@ export declare class BankContactInfo extends BaseContactInfo {
|
|
|
556
574
|
* const bank = Bank.from("CORUTZTZ", "TZ");
|
|
557
575
|
* const contact = new BankContactInfo("John Doe", bank, "0150123456789");
|
|
558
576
|
* console.log("Bank contact created successfully");
|
|
577
|
+
* console.log(`Country: ${contact.countryCode}`); // "TZ" (from bank)
|
|
559
578
|
* } catch (error) {
|
|
560
579
|
* if (error instanceof ContactInfoError) {
|
|
561
580
|
* console.log(`Validation failed: ${error.message}`);
|
|
@@ -567,19 +586,20 @@ export declare class BankContactInfo extends BaseContactInfo {
|
|
|
567
586
|
/**
|
|
568
587
|
* Creates a BankContactInfo instance from a ContactDTO object.
|
|
569
588
|
* Handles SWIFT code validation and bank lookup.
|
|
589
|
+
* The country code is derived from the SWIFT code.
|
|
570
590
|
*
|
|
571
591
|
* **Process:**
|
|
572
592
|
* 1. Validates DTO type is "Bank"
|
|
573
|
-
* 2.
|
|
574
|
-
* 3.
|
|
575
|
-
* 4.
|
|
576
|
-
* 5.
|
|
593
|
+
* 2. Extracts SWIFT code from channel field
|
|
594
|
+
* 3. Derives country code from SWIFT code
|
|
595
|
+
* 4. Validates SWIFT code format and existence
|
|
596
|
+
* 5. Looks up bank information using SWIFT code
|
|
597
|
+
* 6. Delegates to constructor for final validation
|
|
577
598
|
*
|
|
578
599
|
* @static
|
|
579
600
|
* @param {ContactDTO} info - The contact data transfer object
|
|
580
601
|
* @param {string} info.type - Must be "Bank"
|
|
581
602
|
* @param {string} info.channel - The SWIFT code for the bank
|
|
582
|
-
* @param {string} info.countryCode - ISO2 country code
|
|
583
603
|
* @param {string} info.displayName - The account holder's name
|
|
584
604
|
* @param {string} info.accountNo - The bank account number
|
|
585
605
|
*
|
|
@@ -590,14 +610,14 @@ export declare class BankContactInfo extends BaseContactInfo {
|
|
|
590
610
|
* const contactDTO = {
|
|
591
611
|
* type: "Bank",
|
|
592
612
|
* channel: "CORUTZTZ", // CRDB Bank SWIFT code
|
|
593
|
-
* countryCode: "TZ",
|
|
594
613
|
* displayName: "John Doe",
|
|
595
614
|
* accountNo: "0150123456789"
|
|
596
615
|
* };
|
|
597
616
|
*
|
|
598
617
|
* const contact = BankContactInfo.fromContactDTO(contactDTO);
|
|
599
618
|
* if (contact) {
|
|
600
|
-
* console.log(`Created bank contact: ${contact.
|
|
619
|
+
* console.log(`Created bank contact: ${contact.accountName} at ${contact.bank.shortName}`);
|
|
620
|
+
* console.log(`Country: ${contact.countryCode}`); // "TZ" (derived from SWIFT)
|
|
601
621
|
* }
|
|
602
622
|
* ```
|
|
603
623
|
*/
|
|
@@ -605,20 +625,21 @@ export declare class BankContactInfo extends BaseContactInfo {
|
|
|
605
625
|
/**
|
|
606
626
|
* Creates a BankContactInfo instance from a PayoutDTO object.
|
|
607
627
|
* Parses bank information from the payout's msisdn field using "swiftcode:accountno" format.
|
|
628
|
+
* The country code is derived from the parsed phone number or validated against the SWIFT code.
|
|
608
629
|
*
|
|
609
630
|
* **Expected Format:** The msisdn field should contain "SWIFTCODE:ACCOUNTNUMBER"
|
|
610
631
|
*
|
|
611
632
|
* **Process:**
|
|
612
|
-
* 1. Validates country code format
|
|
633
|
+
* 1. Validates country code format in DTO (used as hint/validation)
|
|
613
634
|
* 2. Splits msisdn field on ":" delimiter
|
|
614
635
|
* 3. Validates SWIFT code format and existence
|
|
615
|
-
* 4. Looks up bank information
|
|
636
|
+
* 4. Looks up bank information (bank contains country code)
|
|
616
637
|
* 5. Creates contact with parsed information
|
|
617
638
|
*
|
|
618
639
|
* @static
|
|
619
640
|
* @param {PayoutDTO} info - The payout data transfer object
|
|
620
641
|
* @param {string} info.msisdn - Bank info in format "SWIFTCODE:ACCOUNTNUMBER"
|
|
621
|
-
* @param {string} info.countryCode - ISO2 country code
|
|
642
|
+
* @param {string} info.countryCode - ISO2 country code (used for validation)
|
|
622
643
|
* @param {string} info.payeeName - The account holder's name
|
|
623
644
|
*
|
|
624
645
|
* @returns {BankContactInfo | undefined} New instance if successful, undefined if parsing fails
|
|
@@ -633,9 +654,10 @@ export declare class BankContactInfo extends BaseContactInfo {
|
|
|
633
654
|
*
|
|
634
655
|
* const contact = BankContactInfo.fromPayoutDTO(payoutDTO);
|
|
635
656
|
* if (contact) {
|
|
636
|
-
* console.log(`Payout to: ${contact.
|
|
657
|
+
* console.log(`Payout to: ${contact.accountName}`);
|
|
637
658
|
* console.log(`Bank: ${contact.bank.fullName}`);
|
|
638
|
-
* console.log(`Account: ${contact.
|
|
659
|
+
* console.log(`Account: ${contact.accountNumber}`);
|
|
660
|
+
* console.log(`Country: ${contact.countryCode}`); // "TZ" (from bank)
|
|
639
661
|
* }
|
|
640
662
|
* ```
|
|
641
663
|
*
|
|
@@ -670,6 +692,7 @@ export declare class BankContactInfo extends BaseContactInfo {
|
|
|
670
692
|
* console.log(unknownData.accName); // ✅ Type-safe access
|
|
671
693
|
* console.log(unknownData.bank.fullName); // ✅ Type-safe
|
|
672
694
|
* console.log(unknownData.accNo); // ✅ Type-safe
|
|
695
|
+
* console.log(unknownData.countryCode); // ✅ Type-safe (from bank)
|
|
673
696
|
* } else {
|
|
674
697
|
* console.log("Invalid BankContactInfo structure");
|
|
675
698
|
* }
|
|
@@ -731,10 +754,10 @@ export declare class BankContactInfo extends BaseContactInfo {
|
|
|
731
754
|
* @example
|
|
732
755
|
* ```typescript
|
|
733
756
|
* const contact = new BankContactInfo("John", crdBank, "123456789");
|
|
734
|
-
* console.log(contact.
|
|
757
|
+
* console.log(contact.channelId); // "CORUTZTZ"
|
|
735
758
|
*
|
|
736
759
|
* // Type-safe usage
|
|
737
|
-
* if (contact.
|
|
760
|
+
* if (contact.channelId === "CORUTZTZ") {
|
|
738
761
|
* console.log("This is a CRDB Bank account");
|
|
739
762
|
* }
|
|
740
763
|
* ```
|
|
@@ -749,10 +772,10 @@ export declare class BankContactInfo extends BaseContactInfo {
|
|
|
749
772
|
* @example
|
|
750
773
|
* ```typescript
|
|
751
774
|
* const crdContact = new BankContactInfo("John", crdBank, "123456789");
|
|
752
|
-
* console.log(crdContact.
|
|
775
|
+
* console.log(crdContact.channelName); // "CRDB"
|
|
753
776
|
*
|
|
754
777
|
* const kcbContact = new BankContactInfo("Jane", kcbBank, "987654321");
|
|
755
|
-
* console.log(kcbContact.
|
|
778
|
+
* console.log(kcbContact.channelName); // "KCB"
|
|
756
779
|
* ```
|
|
757
780
|
*
|
|
758
781
|
* @remarks
|
|
@@ -770,6 +793,7 @@ export declare class BankContactInfo extends BaseContactInfo {
|
|
|
770
793
|
* - **Runtime type discrimination**: Use `contact.type` to determine specific type
|
|
771
794
|
* - **Comprehensive validation**: Each type provides its own validation logic
|
|
772
795
|
* - **Consistent API**: Both types implement BaseContactInfo interface
|
|
796
|
+
* - **Country code access**: Always available via contact.countryCode (derived from domain objects)
|
|
773
797
|
*
|
|
774
798
|
* @typedef {MobileContactInfo | BankContactInfo} ContactInfo
|
|
775
799
|
*
|
|
@@ -777,8 +801,9 @@ export declare class BankContactInfo extends BaseContactInfo {
|
|
|
777
801
|
* ```typescript
|
|
778
802
|
* // Type-safe handling of mixed contact types
|
|
779
803
|
* function processContact(contact: ContactInfo) {
|
|
780
|
-
* console.log(`Processing ${contact.type} contact: ${contact.
|
|
781
|
-
* console.log(`Channel: ${contact.
|
|
804
|
+
* console.log(`Processing ${contact.type} contact: ${contact.accountName}`);
|
|
805
|
+
* console.log(`Channel: ${contact.channelName}`);
|
|
806
|
+
* console.log(`Country: ${contact.countryCode}`); // Always available
|
|
782
807
|
*
|
|
783
808
|
* // Type discrimination for specific behavior
|
|
784
809
|
* if (contact.type === "Mobile") {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type ContactDTO, ContactType } from "../features/contact/contact.dtos";
|
|
2
2
|
import { type ContactInfo } from "./contact-info.model";
|
|
3
|
-
import { Country, ISO2CountryCode } from "@temboplus/frontend-core";
|
|
4
3
|
/**
|
|
5
4
|
* Contact class that wraps the Zod schema and provides additional functionality
|
|
6
5
|
*/
|
|
@@ -87,21 +86,7 @@ export declare class Contact {
|
|
|
87
86
|
* - "Display Name" as fallback
|
|
88
87
|
*/
|
|
89
88
|
get accNameLabel(): string;
|
|
90
|
-
/**
|
|
91
|
-
* Country code associated with this contact
|
|
92
|
-
*
|
|
93
|
-
* @returns {string} Two-letter ISO country code
|
|
94
|
-
* @throws an error if the country code is not a valid ISO-2 country code
|
|
95
|
-
*/
|
|
96
|
-
get countryCode(): ISO2CountryCode;
|
|
97
89
|
get channelName(): string;
|
|
98
|
-
/**
|
|
99
|
-
* Country object associated with this contact
|
|
100
|
-
*
|
|
101
|
-
* @returns {Country} Country instance representing the contact's country
|
|
102
|
-
* @throws
|
|
103
|
-
*/
|
|
104
|
-
get country(): Country;
|
|
105
90
|
/**
|
|
106
91
|
* Creates a Contact instance from raw data
|
|
107
92
|
* @throws {ZodError} if validation fails
|
package/package.json
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@temboplus/afloat",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.72",
|
|
4
4
|
"description": "A foundational library for Temboplus-Afloat projects.",
|
|
5
|
-
"main": "./dist/index.cjs.js",
|
|
6
|
-
"module": "./dist/index.esm.js",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
5
|
"type": "module",
|
|
9
6
|
"exports": {
|
|
10
7
|
".": {
|
|
11
|
-
"import": "./dist/index.
|
|
12
|
-
"require": "./dist/index.cjs
|
|
8
|
+
"import": "./dist/index.js",
|
|
9
|
+
"require": "./dist/index.cjs",
|
|
13
10
|
"types": "./dist/index.d.ts"
|
|
14
11
|
}
|
|
15
12
|
},
|
|
@@ -19,8 +16,7 @@
|
|
|
19
16
|
"scripts": {
|
|
20
17
|
"build": "rollup -c rollup.config.js",
|
|
21
18
|
"prepare": "npm run build",
|
|
22
|
-
"dev": "npm run build -- --watch"
|
|
23
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
19
|
+
"dev": "npm run build -- --watch"
|
|
24
20
|
},
|
|
25
21
|
"repository": {
|
|
26
22
|
"type": "git",
|
|
@@ -37,12 +33,9 @@
|
|
|
37
33
|
},
|
|
38
34
|
"homepage": "https://github.com/TemboPlus-Frontend/afloat-js#readme",
|
|
39
35
|
"peerDependencies": {
|
|
40
|
-
"@temboplus/frontend-core": "^0.2.16",
|
|
41
|
-
"@ts-rest/core": "^3.52.1",
|
|
42
36
|
"tslib": "^2.8.1",
|
|
43
37
|
"uuid": "^11.1.0",
|
|
44
|
-
"zod": "^3.24.2"
|
|
45
|
-
"zustand": "^4.5.7"
|
|
38
|
+
"zod": "^3.24.2"
|
|
46
39
|
},
|
|
47
40
|
"devDependencies": {
|
|
48
41
|
"@rollup/plugin-alias": "^5.1.1",
|
|
@@ -57,5 +50,10 @@
|
|
|
57
50
|
"ts-jest": "^29.3.1",
|
|
58
51
|
"ts-node": "^10.9.2",
|
|
59
52
|
"typescript": "^5.8.3"
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@temboplus/frontend-core": "^0.2.17",
|
|
56
|
+
"zustand": "^4.5.7",
|
|
57
|
+
"@ts-rest/core": "^3.52.1"
|
|
60
58
|
}
|
|
61
59
|
}
|