@warriorteam/redai-zalo-sdk 1.28.0 → 1.29.0

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.
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ZNSService = void 0;
4
+ const common_1 = require("../types/common");
4
5
  /**
5
6
  * Service for Zalo Notification Service (ZNS)
6
7
  *
@@ -207,7 +208,7 @@ class ZNSService {
207
208
  try {
208
209
  // Validate limit (max 100)
209
210
  if (limit > 100) {
210
- throw new Error("Limit không được vượt quá 100");
211
+ throw new common_1.ZaloSDKError("Limit không được vượt quá 100", 400);
211
212
  }
212
213
  // Prepare query parameters
213
214
  const params = { offset, limit };
@@ -357,25 +358,12 @@ class ZNSService {
357
358
  */
358
359
  async updateTemplate(accessToken, templateData) {
359
360
  try {
360
- // Validate required fields
361
+ // Validate template_id first
361
362
  if (!templateData.template_id) {
362
- throw new Error("template_id is required");
363
- }
364
- if (!templateData.template_name) {
365
- throw new Error("template_name is required");
366
- }
367
- if (!templateData.template_type) {
368
- throw new Error("template_type is required");
369
- }
370
- if (!templateData.tag) {
371
- throw new Error("tag is required");
372
- }
373
- if (!templateData.layout) {
374
- throw new Error("layout is required");
375
- }
376
- if (!templateData.tracking_id) {
377
- throw new Error("tracking_id is required");
363
+ throw new common_1.ZaloSDKError("template_id bắt buộc", 400);
378
364
  }
365
+ // Comprehensive validation (same as createTemplate)
366
+ this.validateZNSTemplateRequest(templateData);
379
367
  const response = await this.client.apiPost(this.endpoints.template.edit, accessToken, templateData);
380
368
  return response;
381
369
  }
@@ -406,13 +394,13 @@ class ZNSService {
406
394
  .toLowerCase()
407
395
  .substring(filename.lastIndexOf("."));
408
396
  if (!allowedExtensions.includes(fileExtension)) {
409
- throw new Error("File phải có định dạng JPG hoặc PNG");
397
+ throw new common_1.ZaloSDKError("File phải có định dạng JPG hoặc PNG", 400);
410
398
  }
411
399
  // Validate file size if it's a Buffer (max 500KB)
412
400
  if (Buffer.isBuffer(imageFile)) {
413
401
  const maxSize = 500 * 1024; // 500KB
414
402
  if (imageFile.length > maxSize) {
415
- throw new Error("Dung lượng file không được vượt quá 500KB");
403
+ throw new common_1.ZaloSDKError("Dung lượng file không được vượt quá 500KB", 400);
416
404
  }
417
405
  }
418
406
  const response = await this.client.apiUploadFile(this.endpoints.template.uploadImage, accessToken, imageFile, filename);
@@ -439,7 +427,7 @@ class ZNSService {
439
427
  // 5. Note validation if provided
440
428
  if (templateData.note) {
441
429
  if (templateData.note.length < 1 || templateData.note.length > 400) {
442
- throw new Error("note phải có độ dài từ 1 đến 400 ký tự");
430
+ throw new common_1.ZaloSDKError("note phải có độ dài từ 1 đến 400 ký tự", 400);
443
431
  }
444
432
  }
445
433
  }
@@ -448,31 +436,31 @@ class ZNSService {
448
436
  */
449
437
  validateBasicFields(templateData) {
450
438
  if (!templateData.template_name) {
451
- throw new Error("template_name là bắt buộc");
439
+ throw new common_1.ZaloSDKError("template_name là bắt buộc", 400);
452
440
  }
453
441
  if (templateData.template_name.length < 10 || templateData.template_name.length > 60) {
454
- throw new Error("template_name phải có độ dài từ 10 đến 60 ký tự");
442
+ throw new common_1.ZaloSDKError("template_name phải có độ dài từ 10 đến 60 ký tự", 400);
455
443
  }
456
444
  if (!templateData.template_type) {
457
- throw new Error("template_type là bắt buộc");
445
+ throw new common_1.ZaloSDKError("template_type là bắt buộc", 400);
458
446
  }
459
447
  if (![1, 2, 3, 4, 5].includes(templateData.template_type)) {
460
- throw new Error("template_type phải là 1, 2, 3, 4 hoặc 5");
448
+ throw new common_1.ZaloSDKError("template_type phải là 1, 2, 3, 4 hoặc 5", 400);
461
449
  }
462
450
  if (!templateData.tag) {
463
- throw new Error("tag là bắt buộc");
451
+ throw new common_1.ZaloSDKError("tag là bắt buộc", 400);
464
452
  }
465
453
  if (!["1", "2", "3"].includes(templateData.tag)) {
466
- throw new Error("tag phải là '1', '2' hoặc '3'");
454
+ throw new common_1.ZaloSDKError("tag phải là '1', '2' hoặc '3'", 400);
467
455
  }
468
456
  if (!templateData.layout) {
469
- throw new Error("layout là bắt buộc");
457
+ throw new common_1.ZaloSDKError("layout là bắt buộc", 400);
470
458
  }
471
459
  if (!Array.isArray(templateData.layout) && typeof templateData.layout !== 'object') {
472
- throw new Error("layout phải là array hoặc object");
460
+ throw new common_1.ZaloSDKError("layout phải là array hoặc object", 400);
473
461
  }
474
462
  if (!templateData.tracking_id) {
475
- throw new Error("tracking_id là bắt buộc");
463
+ throw new common_1.ZaloSDKError("tracking_id là bắt buộc", 400);
476
464
  }
477
465
  }
478
466
  /**
@@ -487,7 +475,7 @@ class ZNSService {
487
475
  5: ["2"] // ZNS đánh giá dịch vụ
488
476
  };
489
477
  if (!compatibility[templateType]?.includes(tag)) {
490
- throw new Error(`template_type ${templateType} không tương thích với tag ${tag}`);
478
+ throw new common_1.ZaloSDKError(`template_type ${templateType} không tương thích với tag ${tag}`, 400);
491
479
  }
492
480
  }
493
481
  /**
@@ -520,7 +508,7 @@ class ZNSService {
520
508
  allComponents = [...headerComponents, ...bodyComponents, ...footerComponents];
521
509
  }
522
510
  else {
523
- throw new Error("layout phải là array hoặc object có cấu trúc header/body/footer");
511
+ throw new common_1.ZaloSDKError("layout phải là array hoặc object có cấu trúc header/body/footer", 400);
524
512
  }
525
513
  switch (templateType) {
526
514
  case 1: // ZNS tùy chỉnh
@@ -546,20 +534,20 @@ class ZNSService {
546
534
  * Check if component belongs to header
547
535
  */
548
536
  isHeaderComponent(component) {
549
- return component.LOGO || component.IMAGES;
537
+ return 'LOGO' in component || 'IMAGES' in component;
550
538
  }
551
539
  /**
552
540
  * Check if component belongs to body
553
541
  */
554
542
  isBodyComponent(component) {
555
- return component.TITLE || component.PARAGRAPH || component.TABLE ||
556
- component.OTP || component.PAYMENT || component.VOUCHER || component.RATING;
543
+ return 'TITLE' in component || 'PARAGRAPH' in component || 'TABLE' in component ||
544
+ 'OTP' in component || 'PAYMENT' in component || 'VOUCHER' in component || 'RATING' in component;
557
545
  }
558
546
  /**
559
547
  * Check if component belongs to footer
560
548
  */
561
549
  isFooterComponent(component) {
562
- return component.BUTTONS;
550
+ return 'BUTTONS' in component;
563
551
  }
564
552
  /**
565
553
  * Validate custom template layout (type 1)
@@ -567,29 +555,29 @@ class ZNSService {
567
555
  validateCustomTemplateLayout(header, body, footer) {
568
556
  // Header: Logo OR Image (exactly 1)
569
557
  if (header.length !== 1) {
570
- throw new Error("ZNS tùy chỉnh phải có đúng 1 component trong header (Logo hoặc Image)");
558
+ throw new common_1.ZaloSDKError("ZNS tùy chỉnh phải có đúng 1 component trong header (Logo hoặc Image)", 400);
571
559
  }
572
560
  // Body: Title (1) + Paragraph (0-4) + Table (0-1)
573
- const titles = body.filter(c => c.TITLE);
574
- const paragraphs = body.filter(c => c.PARAGRAPH);
575
- const tables = body.filter(c => c.TABLE);
561
+ const titles = body.filter(c => 'TITLE' in c);
562
+ const paragraphs = body.filter(c => 'PARAGRAPH' in c);
563
+ const tables = body.filter(c => 'TABLE' in c);
576
564
  if (titles.length !== 1) {
577
- throw new Error("ZNS tùy chỉnh phải có đúng 1 component TITLE");
565
+ throw new common_1.ZaloSDKError("ZNS tùy chỉnh phải có đúng 1 component TITLE", 400);
578
566
  }
579
567
  if (paragraphs.length > 4) {
580
- throw new Error("ZNS tùy chỉnh không được có quá 4 component PARAGRAPH");
568
+ throw new common_1.ZaloSDKError("ZNS tùy chỉnh không được có quá 4 component PARAGRAPH", 400);
581
569
  }
582
570
  if (tables.length > 1) {
583
- throw new Error("ZNS tùy chỉnh không được có quá 1 component TABLE");
571
+ throw new common_1.ZaloSDKError("ZNS tùy chỉnh không được có quá 1 component TABLE", 400);
584
572
  }
585
573
  // Footer: Buttons (0-2)
586
574
  if (footer.length > 2) {
587
- throw new Error("ZNS tùy chỉnh không được có quá 2 button");
575
+ throw new common_1.ZaloSDKError("ZNS tùy chỉnh không được có quá 2 button", 400);
588
576
  }
589
577
  // If has image, must have at least 1 button
590
- const hasImage = header.some(c => c.IMAGES);
578
+ const hasImage = header.some(c => 'IMAGES' in c);
591
579
  if (hasImage && footer.length === 0) {
592
- throw new Error("ZNS có component Image phải có ít nhất 1 button");
580
+ throw new common_1.ZaloSDKError("ZNS có component Image phải có ít nhất 1 button", 400);
593
581
  }
594
582
  }
595
583
  /**
@@ -597,21 +585,21 @@ class ZNSService {
597
585
  */
598
586
  validateAuthTemplateLayout(header, body, footer) {
599
587
  // Header: Logo only (1)
600
- if (header.length !== 1 || !header[0].LOGO) {
601
- throw new Error("ZNS xác thực phải có đúng 1 component LOGO trong header");
588
+ if (header.length !== 1 || !('LOGO' in header[0])) {
589
+ throw new common_1.ZaloSDKError("ZNS xác thực phải có đúng 1 component LOGO trong header", 400);
602
590
  }
603
591
  // Body: OTP (1) + Paragraph (1)
604
- const otps = body.filter(c => c.OTP);
605
- const paragraphs = body.filter(c => c.PARAGRAPH);
592
+ const otps = body.filter(c => 'OTP' in c);
593
+ const paragraphs = body.filter(c => 'PARAGRAPH' in c);
606
594
  if (otps.length !== 1) {
607
- throw new Error("ZNS xác thực phải có đúng 1 component OTP");
595
+ throw new common_1.ZaloSDKError("ZNS xác thực phải có đúng 1 component OTP", 400);
608
596
  }
609
597
  if (paragraphs.length !== 1) {
610
- throw new Error("ZNS xác thực phải có đúng 1 component PARAGRAPH");
598
+ throw new common_1.ZaloSDKError("ZNS xác thực phải có đúng 1 component PARAGRAPH", 400);
611
599
  }
612
600
  // Footer: None
613
601
  if (footer.length > 0) {
614
- throw new Error("ZNS xác thực không được có component trong footer");
602
+ throw new common_1.ZaloSDKError("ZNS xác thực không được có component trong footer", 400);
615
603
  }
616
604
  }
617
605
  /**
@@ -619,29 +607,29 @@ class ZNSService {
619
607
  */
620
608
  validatePaymentTemplateLayout(header, body, footer) {
621
609
  // Header: Logo only (1)
622
- if (header.length !== 1 || !header[0].LOGO) {
623
- throw new Error("ZNS yêu cầu thanh toán phải có đúng 1 component LOGO trong header");
610
+ if (header.length !== 1 || !('LOGO' in header[0])) {
611
+ throw new common_1.ZaloSDKError("ZNS yêu cầu thanh toán phải có đúng 1 component LOGO trong header", 400);
624
612
  }
625
613
  // Body: Title (1) + Paragraph (0-4) + Table (0-1) + Payment (1)
626
- const titles = body.filter(c => c.TITLE);
627
- const paragraphs = body.filter(c => c.PARAGRAPH);
628
- const tables = body.filter(c => c.TABLE);
629
- const payments = body.filter(c => c.PAYMENT);
614
+ const titles = body.filter(c => 'TITLE' in c);
615
+ const paragraphs = body.filter(c => 'PARAGRAPH' in c);
616
+ const tables = body.filter(c => 'TABLE' in c);
617
+ const payments = body.filter(c => 'PAYMENT' in c);
630
618
  if (titles.length !== 1) {
631
- throw new Error("ZNS yêu cầu thanh toán phải có đúng 1 component TITLE");
619
+ throw new common_1.ZaloSDKError("ZNS yêu cầu thanh toán phải có đúng 1 component TITLE", 400);
632
620
  }
633
621
  if (paragraphs.length > 4) {
634
- throw new Error("ZNS yêu cầu thanh toán không được có quá 4 component PARAGRAPH");
622
+ throw new common_1.ZaloSDKError("ZNS yêu cầu thanh toán không được có quá 4 component PARAGRAPH", 400);
635
623
  }
636
624
  if (tables.length > 1) {
637
- throw new Error("ZNS yêu cầu thanh toán không được có quá 1 component TABLE");
625
+ throw new common_1.ZaloSDKError("ZNS yêu cầu thanh toán không được có quá 1 component TABLE", 400);
638
626
  }
639
627
  if (payments.length !== 1) {
640
- throw new Error("ZNS yêu cầu thanh toán phải có đúng 1 component PAYMENT");
628
+ throw new common_1.ZaloSDKError("ZNS yêu cầu thanh toán phải có đúng 1 component PAYMENT", 400);
641
629
  }
642
630
  // Footer: Buttons (0-2)
643
631
  if (footer.length > 2) {
644
- throw new Error("ZNS yêu cầu thanh toán không được có quá 2 button");
632
+ throw new common_1.ZaloSDKError("ZNS yêu cầu thanh toán không được có quá 2 button", 400);
645
633
  }
646
634
  }
647
635
  /**
@@ -650,33 +638,33 @@ class ZNSService {
650
638
  validateVoucherTemplateLayout(header, body, footer) {
651
639
  // Header: Logo OR Image (exactly 1)
652
640
  if (header.length !== 1) {
653
- throw new Error("ZNS voucher phải có đúng 1 component trong header (Logo hoặc Image)");
641
+ throw new common_1.ZaloSDKError("ZNS voucher phải có đúng 1 component trong header (Logo hoặc Image)", 400);
654
642
  }
655
643
  // Body: Title (1) + Paragraph (0-4) + Table (0-1) + Voucher (1)
656
- const titles = body.filter(c => c.TITLE);
657
- const paragraphs = body.filter(c => c.PARAGRAPH);
658
- const tables = body.filter(c => c.TABLE);
659
- const vouchers = body.filter(c => c.VOUCHER);
644
+ const titles = body.filter(c => 'TITLE' in c);
645
+ const paragraphs = body.filter(c => 'PARAGRAPH' in c);
646
+ const tables = body.filter(c => 'TABLE' in c);
647
+ const vouchers = body.filter(c => 'VOUCHER' in c);
660
648
  if (titles.length !== 1) {
661
- throw new Error("ZNS voucher phải có đúng 1 component TITLE");
649
+ throw new common_1.ZaloSDKError("ZNS voucher phải có đúng 1 component TITLE", 400);
662
650
  }
663
651
  if (paragraphs.length > 4) {
664
- throw new Error("ZNS voucher không được có quá 4 component PARAGRAPH");
652
+ throw new common_1.ZaloSDKError("ZNS voucher không được có quá 4 component PARAGRAPH", 400);
665
653
  }
666
654
  if (tables.length > 1) {
667
- throw new Error("ZNS voucher không được có quá 1 component TABLE");
655
+ throw new common_1.ZaloSDKError("ZNS voucher không được có quá 1 component TABLE", 400);
668
656
  }
669
657
  if (vouchers.length !== 1) {
670
- throw new Error("ZNS voucher phải có đúng 1 component VOUCHER");
658
+ throw new common_1.ZaloSDKError("ZNS voucher phải có đúng 1 component VOUCHER", 400);
671
659
  }
672
660
  // Footer: Buttons (0-2)
673
661
  if (footer.length > 2) {
674
- throw new Error("ZNS voucher không được có quá 2 button");
662
+ throw new common_1.ZaloSDKError("ZNS voucher không được có quá 2 button", 400);
675
663
  }
676
664
  // If has image, must have at least 1 button, max 2
677
- const hasImage = header.some(c => c.IMAGES);
665
+ const hasImage = header.some(c => 'IMAGES' in c);
678
666
  if (hasImage && footer.length === 0) {
679
- throw new Error("ZNS voucher có component Image phải có ít nhất 1 button");
667
+ throw new common_1.ZaloSDKError("ZNS voucher có component Image phải có ít nhất 1 button", 400);
680
668
  }
681
669
  }
682
670
  /**
@@ -684,59 +672,59 @@ class ZNSService {
684
672
  */
685
673
  validateRatingTemplateLayout(header, body, footer) {
686
674
  // Header: Logo only (1)
687
- if (header.length !== 1 || !header[0].LOGO) {
688
- throw new Error("ZNS đánh giá dịch vụ phải có đúng 1 component LOGO trong header");
675
+ if (header.length !== 1 || !('LOGO' in header[0])) {
676
+ throw new common_1.ZaloSDKError("ZNS đánh giá dịch vụ phải có đúng 1 component LOGO trong header", 400);
689
677
  }
690
678
  // Body: Title (1) + Paragraph (0-1) + Rating (1)
691
- const titles = body.filter(c => c.TITLE);
692
- const paragraphs = body.filter(c => c.PARAGRAPH);
693
- const ratings = body.filter(c => c.RATING);
679
+ const titles = body.filter(c => 'TITLE' in c);
680
+ const paragraphs = body.filter(c => 'PARAGRAPH' in c);
681
+ const ratings = body.filter(c => 'RATING' in c);
694
682
  if (titles.length !== 1) {
695
- throw new Error("ZNS đánh giá dịch vụ phải có đúng 1 component TITLE");
683
+ throw new common_1.ZaloSDKError("ZNS đánh giá dịch vụ phải có đúng 1 component TITLE", 400);
696
684
  }
697
685
  if (paragraphs.length > 1) {
698
- throw new Error("ZNS đánh giá dịch vụ không được có quá 1 component PARAGRAPH");
686
+ throw new common_1.ZaloSDKError("ZNS đánh giá dịch vụ không được có quá 1 component PARAGRAPH", 400);
699
687
  }
700
688
  if (ratings.length !== 1) {
701
- throw new Error("ZNS đánh giá dịch vụ phải có đúng 1 component RATING");
689
+ throw new common_1.ZaloSDKError("ZNS đánh giá dịch vụ phải có đúng 1 component RATING", 400);
702
690
  }
703
691
  // Footer: Buttons (0-2)
704
692
  if (footer.length > 2) {
705
- throw new Error("ZNS đánh giá dịch vụ không được có quá 2 button");
693
+ throw new common_1.ZaloSDKError("ZNS đánh giá dịch vụ không được có quá 2 button", 400);
706
694
  }
707
695
  }
708
696
  /**
709
697
  * Validate individual component content
710
698
  */
711
699
  validateComponent(component) {
712
- if (component.TITLE) {
700
+ if ('TITLE' in component) {
713
701
  this.validateTitleComponent(component.TITLE);
714
702
  }
715
- if (component.PARAGRAPH) {
703
+ if ('PARAGRAPH' in component) {
716
704
  this.validateParagraphComponent(component.PARAGRAPH);
717
705
  }
718
- if (component.OTP) {
706
+ if ('OTP' in component) {
719
707
  this.validateOTPComponent(component.OTP);
720
708
  }
721
- if (component.TABLE) {
709
+ if ('TABLE' in component) {
722
710
  this.validateTableComponent(component.TABLE);
723
711
  }
724
- if (component.LOGO) {
712
+ if ('LOGO' in component) {
725
713
  this.validateLogoComponent(component.LOGO);
726
714
  }
727
- if (component.IMAGES) {
715
+ if ('IMAGES' in component) {
728
716
  this.validateImagesComponent(component.IMAGES);
729
717
  }
730
- if (component.BUTTONS) {
718
+ if ('BUTTONS' in component) {
731
719
  this.validateButtonsComponent(component.BUTTONS);
732
720
  }
733
- if (component.PAYMENT) {
721
+ if ('PAYMENT' in component) {
734
722
  this.validatePaymentComponent(component.PAYMENT);
735
723
  }
736
- if (component.VOUCHER) {
724
+ if ('VOUCHER' in component) {
737
725
  this.validateVoucherComponent(component.VOUCHER);
738
726
  }
739
- if (component.RATING) {
727
+ if ('RATING' in component) {
740
728
  this.validateRatingComponent(component.RATING);
741
729
  }
742
730
  }
@@ -745,15 +733,15 @@ class ZNSService {
745
733
  */
746
734
  validateTitleComponent(title) {
747
735
  if (!title.value || typeof title.value !== 'string') {
748
- throw new Error("TITLE component phải có field value kiểu string");
736
+ throw new common_1.ZaloSDKError("TITLE component phải có field value kiểu string", 400);
749
737
  }
750
738
  if (title.value.length < 9 || title.value.length > 65) {
751
- throw new Error("TITLE value phải có độ dài từ 9 đến 65 ký tự");
739
+ throw new common_1.ZaloSDKError("TITLE value phải có độ dài từ 9 đến 65 ký tự", 400);
752
740
  }
753
741
  // Check max 4 params
754
742
  const paramCount = (title.value.match(/\{\{[^}]+\}\}/g) || []).length;
755
743
  if (paramCount > 4) {
756
- throw new Error("TITLE component không được có quá 4 params");
744
+ throw new common_1.ZaloSDKError("TITLE component không được có quá 4 params", 400);
757
745
  }
758
746
  }
759
747
  /**
@@ -761,15 +749,15 @@ class ZNSService {
761
749
  */
762
750
  validateParagraphComponent(paragraph) {
763
751
  if (!paragraph.value || typeof paragraph.value !== 'string') {
764
- throw new Error("PARAGRAPH component phải có field value kiểu string");
752
+ throw new common_1.ZaloSDKError("PARAGRAPH component phải có field value kiểu string", 400);
765
753
  }
766
754
  if (paragraph.value.length < 9 || paragraph.value.length > 400) {
767
- throw new Error("PARAGRAPH value phải có độ dài từ 9 đến 400 ký tự");
755
+ throw new common_1.ZaloSDKError("PARAGRAPH value phải có độ dài từ 9 đến 400 ký tự", 400);
768
756
  }
769
757
  // Check max 10 params
770
758
  const paramCount = (paragraph.value.match(/\{\{[^}]+\}\}/g) || []).length;
771
759
  if (paramCount > 10) {
772
- throw new Error("PARAGRAPH component không được có quá 10 params");
760
+ throw new common_1.ZaloSDKError("PARAGRAPH component không được có quá 10 params", 400);
773
761
  }
774
762
  }
775
763
  /**
@@ -777,10 +765,10 @@ class ZNSService {
777
765
  */
778
766
  validateOTPComponent(otp) {
779
767
  if (!otp.value || typeof otp.value !== 'string') {
780
- throw new Error("OTP component phải có field value kiểu string");
768
+ throw new common_1.ZaloSDKError("OTP component phải có field value kiểu string", 400);
781
769
  }
782
770
  if (otp.value.length < 1 || otp.value.length > 10) {
783
- throw new Error("OTP value phải có độ dài từ 1 đến 10 ký tự");
771
+ throw new common_1.ZaloSDKError("OTP value phải có độ dài từ 1 đến 10 ký tự", 400);
784
772
  }
785
773
  }
786
774
  /**
@@ -788,26 +776,26 @@ class ZNSService {
788
776
  */
789
777
  validateTableComponent(table) {
790
778
  if (!table.rows || !Array.isArray(table.rows)) {
791
- throw new Error("TABLE component phải có field rows kiểu array");
779
+ throw new common_1.ZaloSDKError("TABLE component phải có field rows kiểu array", 400);
792
780
  }
793
781
  if (table.rows.length < 2 || table.rows.length > 8) {
794
- throw new Error("TABLE rows phải có từ 2 đến 8 objects");
782
+ throw new common_1.ZaloSDKError("TABLE rows phải có từ 2 đến 8 objects", 400);
795
783
  }
796
784
  table.rows.forEach((row, index) => {
797
785
  if (!row.title || typeof row.title !== 'string') {
798
- throw new Error(`TABLE row ${index + 1} phải có field title kiểu string`);
786
+ throw new common_1.ZaloSDKError(`TABLE row ${index + 1} phải có field title kiểu string`, 400);
799
787
  }
800
788
  if (row.title.length < 3 || row.title.length > 36) {
801
- throw new Error(`TABLE row ${index + 1} title phải có độ dài từ 3 đến 36 ký tự`);
789
+ throw new common_1.ZaloSDKError(`TABLE row ${index + 1} title phải có độ dài từ 3 đến 36 ký tự`, 400);
802
790
  }
803
791
  if (!row.value || typeof row.value !== 'string') {
804
- throw new Error(`TABLE row ${index + 1} phải có field value kiểu string`);
792
+ throw new common_1.ZaloSDKError(`TABLE row ${index + 1} phải có field value kiểu string`, 400);
805
793
  }
806
794
  if (row.value.length < 3 || row.value.length > 90) {
807
- throw new Error(`TABLE row ${index + 1} value phải có độ dài từ 3 đến 90 ký tự`);
795
+ throw new common_1.ZaloSDKError(`TABLE row ${index + 1} value phải có độ dài từ 3 đến 90 ký tự`, 400);
808
796
  }
809
797
  if (row.row_type !== undefined && ![0, 1, 2, 3, 4, 5].includes(row.row_type)) {
810
- throw new Error(`TABLE row ${index + 1} row_type phải là 0, 1, 2, 3, 4 hoặc 5`);
798
+ throw new common_1.ZaloSDKError(`TABLE row ${index + 1} row_type phải là 0, 1, 2, 3, 4 hoặc 5`, 400);
811
799
  }
812
800
  });
813
801
  }
@@ -816,7 +804,7 @@ class ZNSService {
816
804
  */
817
805
  validateLogoComponent(logo) {
818
806
  if (!logo.light || !logo.dark) {
819
- throw new Error("LOGO component phải có cả light và dark attachment");
807
+ throw new common_1.ZaloSDKError("LOGO component phải có cả light và dark attachment", 400);
820
808
  }
821
809
  this.validateAttachment(logo.light, "LOGO light");
822
810
  this.validateAttachment(logo.dark, "LOGO dark");
@@ -826,10 +814,10 @@ class ZNSService {
826
814
  */
827
815
  validateImagesComponent(images) {
828
816
  if (!images.items || !Array.isArray(images.items)) {
829
- throw new Error("IMAGES component phải có field items kiểu array");
817
+ throw new common_1.ZaloSDKError("IMAGES component phải có field items kiểu array", 400);
830
818
  }
831
819
  if (images.items.length < 1 || images.items.length > 3) {
832
- throw new Error("IMAGES items phải có từ 1 đến 3 attachments");
820
+ throw new common_1.ZaloSDKError("IMAGES items phải có từ 1 đến 3 attachments", 400);
833
821
  }
834
822
  images.items.forEach((item, index) => {
835
823
  this.validateAttachment(item, `IMAGES item ${index + 1}`);
@@ -840,23 +828,23 @@ class ZNSService {
840
828
  */
841
829
  validateButtonsComponent(buttons) {
842
830
  if (!buttons.items || !Array.isArray(buttons.items)) {
843
- throw new Error("BUTTONS component phải có field items kiểu array");
831
+ throw new common_1.ZaloSDKError("BUTTONS component phải có field items kiểu array", 400);
844
832
  }
845
833
  if (buttons.items.length < 1 || buttons.items.length > 2) {
846
- throw new Error("BUTTONS items phải có từ 1 đến 2 objects");
834
+ throw new common_1.ZaloSDKError("BUTTONS items phải có từ 1 đến 2 objects", 400);
847
835
  }
848
836
  buttons.items.forEach((button, index) => {
849
837
  if (!button.type || ![1, 2, 3, 4, 5, 6, 7, 8, 9].includes(button.type)) {
850
- throw new Error(`BUTTON ${index + 1} type phải là 1, 2, 3, 4, 5, 6, 7, 8 hoặc 9`);
838
+ throw new common_1.ZaloSDKError(`BUTTON ${index + 1} type phải là 1, 2, 3, 4, 5, 6, 7, 8 hoặc 9`, 400);
851
839
  }
852
840
  if (!button.title || typeof button.title !== 'string') {
853
- throw new Error(`BUTTON ${index + 1} phải có field title kiểu string`);
841
+ throw new common_1.ZaloSDKError(`BUTTON ${index + 1} phải có field title kiểu string`, 400);
854
842
  }
855
843
  if (button.title.length < 5 || button.title.length > 30) {
856
- throw new Error(`BUTTON ${index + 1} title phải có độ dài từ 5 đến 30 ký tự`);
844
+ throw new common_1.ZaloSDKError(`BUTTON ${index + 1} title phải có độ dài từ 5 đến 30 ký tự`, 400);
857
845
  }
858
846
  if (!button.content || typeof button.content !== 'string') {
859
- throw new Error(`BUTTON ${index + 1} phải có field content kiểu string`);
847
+ throw new common_1.ZaloSDKError(`BUTTON ${index + 1} phải có field content kiểu string`, 400);
860
848
  }
861
849
  });
862
850
  }
@@ -865,25 +853,25 @@ class ZNSService {
865
853
  */
866
854
  validatePaymentComponent(payment) {
867
855
  if (!payment.bank_code || typeof payment.bank_code !== 'string') {
868
- throw new Error("PAYMENT component phải có field bank_code kiểu string");
856
+ throw new common_1.ZaloSDKError("PAYMENT component phải có field bank_code kiểu string", 400);
869
857
  }
870
858
  if (!payment.account_name || typeof payment.account_name !== 'string') {
871
- throw new Error("PAYMENT component phải có field account_name kiểu string");
859
+ throw new common_1.ZaloSDKError("PAYMENT component phải có field account_name kiểu string", 400);
872
860
  }
873
861
  if (payment.account_name.length < 1 || payment.account_name.length > 100) {
874
- throw new Error("PAYMENT account_name phải có độ dài từ 1 đến 100 ký tự");
862
+ throw new common_1.ZaloSDKError("PAYMENT account_name phải có độ dài từ 1 đến 100 ký tự", 400);
875
863
  }
876
864
  if (!payment.bank_account || typeof payment.bank_account !== 'string') {
877
- throw new Error("PAYMENT component phải có field bank_account kiểu string");
865
+ throw new common_1.ZaloSDKError("PAYMENT component phải có field bank_account kiểu string", 400);
878
866
  }
879
867
  if (payment.bank_account.length < 1 || payment.bank_account.length > 100) {
880
- throw new Error("PAYMENT bank_account phải có độ dài từ 1 đến 100 ký tự");
868
+ throw new common_1.ZaloSDKError("PAYMENT bank_account phải có độ dài từ 1 đến 100 ký tự", 400);
881
869
  }
882
870
  if (!payment.amount) {
883
- throw new Error("PAYMENT component phải có field amount");
871
+ throw new common_1.ZaloSDKError("PAYMENT component phải có field amount", 400);
884
872
  }
885
873
  if (payment.note && (payment.note.length < 1 || payment.note.length > 90)) {
886
- throw new Error("PAYMENT note phải có độ dài từ 1 đến 90 ký tự");
874
+ throw new common_1.ZaloSDKError("PAYMENT note phải có độ dài từ 1 đến 90 ký tự", 400);
887
875
  }
888
876
  }
889
877
  /**
@@ -891,28 +879,28 @@ class ZNSService {
891
879
  */
892
880
  validateVoucherComponent(voucher) {
893
881
  if (!voucher.name || typeof voucher.name !== 'string') {
894
- throw new Error("VOUCHER component phải có field name kiểu string");
882
+ throw new common_1.ZaloSDKError("VOUCHER component phải có field name kiểu string", 400);
895
883
  }
896
884
  if (voucher.name.length < 1 || voucher.name.length > 30) {
897
- throw new Error("VOUCHER name phải có độ dài từ 1 đến 30 ký tự");
885
+ throw new common_1.ZaloSDKError("VOUCHER name phải có độ dài từ 1 đến 30 ký tự", 400);
898
886
  }
899
887
  if (!voucher.condition || typeof voucher.condition !== 'string') {
900
- throw new Error("VOUCHER component phải có field condition kiểu string");
888
+ throw new common_1.ZaloSDKError("VOUCHER component phải có field condition kiểu string", 400);
901
889
  }
902
890
  if (voucher.condition.length < 1 || voucher.condition.length > 40) {
903
- throw new Error("VOUCHER condition phải có độ dài từ 1 đến 40 ký tự");
891
+ throw new common_1.ZaloSDKError("VOUCHER condition phải có độ dài từ 1 đến 40 ký tự", 400);
904
892
  }
905
893
  if (!voucher.end_date || typeof voucher.end_date !== 'string') {
906
- throw new Error("VOUCHER component phải có field end_date kiểu string");
894
+ throw new common_1.ZaloSDKError("VOUCHER component phải có field end_date kiểu string", 400);
907
895
  }
908
896
  if (!voucher.voucher_code || typeof voucher.voucher_code !== 'string') {
909
- throw new Error("VOUCHER component phải có field voucher_code kiểu string");
897
+ throw new common_1.ZaloSDKError("VOUCHER component phải có field voucher_code kiểu string", 400);
910
898
  }
911
899
  if (voucher.voucher_code.length < 1 || voucher.voucher_code.length > 25) {
912
- throw new Error("VOUCHER voucher_code phải có độ dài từ 1 đến 25 ký tự");
900
+ throw new common_1.ZaloSDKError("VOUCHER voucher_code phải có độ dài từ 1 đến 25 ký tự", 400);
913
901
  }
914
902
  if (voucher.display_code !== undefined && ![1, 2, 3].includes(voucher.display_code)) {
915
- throw new Error("VOUCHER display_code phải là 1, 2 hoặc 3");
903
+ throw new common_1.ZaloSDKError("VOUCHER display_code phải là 1, 2 hoặc 3", 400);
916
904
  }
917
905
  }
918
906
  /**
@@ -920,46 +908,46 @@ class ZNSService {
920
908
  */
921
909
  validateRatingComponent(rating) {
922
910
  if (!rating.items || !Array.isArray(rating.items)) {
923
- throw new Error("RATING component phải có field items kiểu array");
911
+ throw new common_1.ZaloSDKError("RATING component phải có field items kiểu array", 400);
924
912
  }
925
913
  if (rating.items.length !== 5) {
926
- throw new Error("RATING items phải có đúng 5 objects");
914
+ throw new common_1.ZaloSDKError("RATING items phải có đúng 5 objects", 400);
927
915
  }
928
916
  rating.items.forEach((item, index) => {
929
- const starValue = index + 1;
917
+ const starValue = (index + 1);
930
918
  if (item.star !== starValue) {
931
- throw new Error(`RATING item ${index + 1} phải có star = ${starValue}`);
919
+ throw new common_1.ZaloSDKError(`RATING item ${index + 1} phải có star = ${starValue}`, 400);
932
920
  }
933
921
  if (!item.title || typeof item.title !== 'string') {
934
- throw new Error(`RATING item ${index + 1} phải có field title kiểu string`);
922
+ throw new common_1.ZaloSDKError(`RATING item ${index + 1} phải có field title kiểu string`, 400);
935
923
  }
936
924
  if (item.title.length < 1 || item.title.length > 50) {
937
- throw new Error(`RATING item ${index + 1} title phải có độ dài từ 1 đến 50 ký tự`);
925
+ throw new common_1.ZaloSDKError(`RATING item ${index + 1} title phải có độ dài từ 1 đến 50 ký tự`, 400);
938
926
  }
939
927
  if (item.question && (item.question.length < 1 || item.question.length > 100)) {
940
- throw new Error(`RATING item ${index + 1} question phải có độ dài từ 1 đến 100 ký tự`);
928
+ throw new common_1.ZaloSDKError(`RATING item ${index + 1} question phải có độ dài từ 1 đến 100 ký tự`, 400);
941
929
  }
942
930
  if (item.answers && Array.isArray(item.answers)) {
943
931
  if (item.answers.length < 1 || item.answers.length > 5) {
944
- throw new Error(`RATING item ${index + 1} answers phải có từ 1 đến 5 câu trả lời`);
932
+ throw new common_1.ZaloSDKError(`RATING item ${index + 1} answers phải có từ 1 đến 5 câu trả lời`, 400);
945
933
  }
946
934
  item.answers.forEach((answer, answerIndex) => {
947
935
  if (!answer || answer.length < 1 || answer.length > 50) {
948
- throw new Error(`RATING item ${index + 1} answer ${answerIndex + 1} phải có độ dài từ 1 đến 50 ký tự`);
936
+ throw new common_1.ZaloSDKError(`RATING item ${index + 1} answer ${answerIndex + 1} phải có độ dài từ 1 đến 50 ký tự`, 400);
949
937
  }
950
938
  });
951
939
  }
952
940
  if (!item.thanks || typeof item.thanks !== 'string') {
953
- throw new Error(`RATING item ${index + 1} phải có field thanks kiểu string`);
941
+ throw new common_1.ZaloSDKError(`RATING item ${index + 1} phải có field thanks kiểu string`, 400);
954
942
  }
955
943
  if (item.thanks.length < 1 || item.thanks.length > 100) {
956
- throw new Error(`RATING item ${index + 1} thanks phải có độ dài từ 1 đến 100 ký tự`);
944
+ throw new common_1.ZaloSDKError(`RATING item ${index + 1} thanks phải có độ dài từ 1 đến 100 ký tự`, 400);
957
945
  }
958
946
  if (!item.description || typeof item.description !== 'string') {
959
- throw new Error(`RATING item ${index + 1} phải có field description kiểu string`);
947
+ throw new common_1.ZaloSDKError(`RATING item ${index + 1} phải có field description kiểu string`, 400);
960
948
  }
961
949
  if (item.description.length < 1 || item.description.length > 200) {
962
- throw new Error(`RATING item ${index + 1} description phải có độ dài từ 1 đến 200 ký tự`);
950
+ throw new common_1.ZaloSDKError(`RATING item ${index + 1} description phải có độ dài từ 1 đến 200 ký tự`, 400);
963
951
  }
964
952
  });
965
953
  }
@@ -968,10 +956,10 @@ class ZNSService {
968
956
  */
969
957
  validateAttachment(attachment, context) {
970
958
  if (!attachment.type || !attachment.media_id) {
971
- throw new Error(`${context} phải có type và media_id`);
959
+ throw new common_1.ZaloSDKError(`${context} phải có type và media_id`, 400);
972
960
  }
973
961
  if (attachment.type !== "IMAGE") {
974
- throw new Error(`${context} type phải là "IMAGE"`);
962
+ throw new common_1.ZaloSDKError(`${context} type phải là "IMAGE"`, 400);
975
963
  }
976
964
  }
977
965
  /**
@@ -1008,36 +996,36 @@ class ZNSService {
1008
996
  // Validate each param
1009
997
  params.forEach((param, index) => {
1010
998
  if (!param.name || typeof param.name !== 'string') {
1011
- throw new Error(`Param ${index + 1} phải có field name kiểu string`);
999
+ throw new common_1.ZaloSDKError(`Param ${index + 1} phải có field name kiểu string`, 400);
1012
1000
  }
1013
1001
  if (!param.type || typeof param.type !== 'string') {
1014
- throw new Error(`Param ${index + 1} phải có field type kiểu string`);
1002
+ throw new common_1.ZaloSDKError(`Param ${index + 1} phải có field type kiểu string`, 400);
1015
1003
  }
1016
1004
  if (!Object.keys(paramTypeConstraints).includes(param.type)) {
1017
- throw new Error(`Param ${index + 1} type phải là 1-15`);
1005
+ throw new common_1.ZaloSDKError(`Param ${index + 1} type phải là 1-15`, 400);
1018
1006
  }
1019
1007
  if (!param.sample_value || typeof param.sample_value !== 'string') {
1020
- throw new Error(`Param ${index + 1} phải có field sample_value kiểu string`);
1008
+ throw new common_1.ZaloSDKError(`Param ${index + 1} phải có field sample_value kiểu string`, 400);
1021
1009
  }
1022
1010
  // Validate sample_value length based on type
1023
1011
  const maxLength = paramTypeConstraints[param.type];
1024
1012
  if (param.sample_value.length > maxLength) {
1025
- throw new Error(`Param ${index + 1} sample_value không được vượt quá ${maxLength} ký tự cho type ${param.type}`);
1013
+ throw new common_1.ZaloSDKError(`Param ${index + 1} sample_value không được vượt quá ${maxLength} ký tự cho type ${param.type}`, 400);
1026
1014
  }
1027
1015
  // Remove param from used set if found
1028
1016
  usedParams.delete(param.name);
1029
1017
  });
1030
1018
  // Check if all used params are defined
1031
1019
  if (usedParams.size > 0) {
1032
- throw new Error(`Các param sau được sử dụng trong layout nhưng chưa được định nghĩa: ${Array.from(usedParams).join(', ')}`);
1020
+ throw new common_1.ZaloSDKError(`Các param sau được sử dụng trong layout nhưng chưa được định nghĩa: ${Array.from(usedParams).join(', ')}`, 400);
1033
1021
  }
1034
1022
  }
1035
1023
  handleZNSError(error, defaultMessage) {
1036
1024
  if (error.response?.data) {
1037
1025
  const errorData = error.response.data;
1038
- return new Error(`${defaultMessage}: ${errorData.message || errorData.error || "Unknown error"}`);
1026
+ return new common_1.ZaloSDKError(`${defaultMessage}: ${errorData.message || errorData.error || "Unknown error"}`, errorData.error || -1, errorData);
1039
1027
  }
1040
- return new Error(`${defaultMessage}: ${error.message || "Unknown error"}`);
1028
+ return new common_1.ZaloSDKError(`${defaultMessage}: ${error.message || "Unknown error"}`, -1, error);
1041
1029
  }
1042
1030
  }
1043
1031
  exports.ZNSService = ZNSService;