@devwithbobby/loops 0.1.8 → 0.1.9

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.
@@ -56,7 +56,8 @@ export declare const triggerLoop: any;
56
56
  export declare const findContact: any;
57
57
  /**
58
58
  * Batch create contacts
59
- * Create multiple contacts in a single API call
59
+ * Creates multiple contacts sequentially using the single contact create endpoint.
60
+ * Note: Loops.so doesn't have a batch endpoint, so we create contacts one by one.
60
61
  */
61
62
  export declare const batchCreateContacts: any;
62
63
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../../src/component/lib.ts"],"names":[],"mappings":"AA0BA;;GAEG;AACH,eAAO,MAAM,YAAY,KA6CvB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa,KAexB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,iBAAiB,KAgC5B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,aAAa,KAwCxB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,UAAU,KAiHrB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa,KAoDxB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,iBAAiB,KAqD5B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,SAAS,KAgCpB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa,KA8BxB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,YAAY,KAkFvB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,WAAW,KA+CtB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,WAAW,KA2DtB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,mBAAmB,KA4C9B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,kBAAkB,KA+B7B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,kBAAkB,KA+B7B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,mBAAmB,KAwC9B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,eAAe,KAwC1B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa,KAgDxB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,uBAAuB,KAsGlC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,uBAAuB,KA6ClC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,mBAAmB,KA6C9B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,oBAAoB,KA8B/B,CAAC"}
1
+ {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../../src/component/lib.ts"],"names":[],"mappings":"AA0BA;;GAEG;AACH,eAAO,MAAM,YAAY,KA6CvB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa,KAexB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,iBAAiB,KAgC5B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,aAAa,KAwCxB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,UAAU,KAiHrB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa,KAoDxB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,iBAAiB,KAqD5B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,SAAS,KAgCpB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa,KA8BxB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,YAAY,KAkFvB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,WAAW,KA+CtB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,WAAW,KA2DtB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,KAyD9B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,kBAAkB,KA+B7B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,kBAAkB,KA+B7B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,mBAAmB,KAwC9B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,eAAe,KAwC1B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa,KAgDxB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,uBAAuB,KAsGlC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,uBAAuB,KA6ClC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,mBAAmB,KA6C9B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,oBAAoB,KA8B/B,CAAC"}
@@ -632,7 +632,8 @@ export const findContact = za({
632
632
  });
633
633
  /**
634
634
  * Batch create contacts
635
- * Create multiple contacts in a single API call
635
+ * Creates multiple contacts sequentially using the single contact create endpoint.
636
+ * Note: Loops.so doesn't have a batch endpoint, so we create contacts one by one.
636
637
  */
637
638
  export const batchCreateContacts = za({
638
639
  args: z.object({
@@ -642,36 +643,52 @@ export const batchCreateContacts = za({
642
643
  returns: z.object({
643
644
  success: z.boolean(),
644
645
  created: z.number().optional(),
646
+ failed: z.number().optional(),
647
+ results: z.array(z.object({
648
+ email: z.string(),
649
+ success: z.boolean(),
650
+ error: z.string().optional(),
651
+ })).optional(),
645
652
  }),
646
653
  handler: async (ctx, args) => {
647
- const response = await fetch(`${LOOPS_API_BASE_URL}/contacts/batch`, {
648
- method: "POST",
649
- headers: {
650
- Authorization: `Bearer ${args.apiKey}`,
651
- "Content-Type": "application/json",
652
- },
653
- body: JSON.stringify({ contacts: args.contacts }),
654
- });
655
- if (!response.ok) {
656
- const errorText = await response.text();
657
- console.error(`Loops API error [${response.status}]:`, errorText);
658
- throw sanitizeError(response.status, errorText);
659
- }
660
- const data = (await response.json());
654
+ let created = 0;
655
+ let failed = 0;
656
+ const results = [];
657
+ // Create contacts one by one since Loops.so doesn't have a batch endpoint
661
658
  for (const contact of args.contacts) {
662
- await ctx.runMutation((internal.lib.storeContact), {
663
- email: contact.email,
664
- firstName: contact.firstName,
665
- lastName: contact.lastName,
666
- userId: contact.userId,
667
- source: contact.source,
668
- subscribed: contact.subscribed,
669
- userGroup: contact.userGroup,
670
- });
659
+ try {
660
+ // Use the addContact function which handles create/update logic
661
+ const result = await ctx.runAction((internal.lib).addContact, {
662
+ apiKey: args.apiKey,
663
+ contact,
664
+ });
665
+ if (result.success) {
666
+ created++;
667
+ results.push({ email: contact.email, success: true });
668
+ }
669
+ else {
670
+ failed++;
671
+ results.push({
672
+ email: contact.email,
673
+ success: false,
674
+ error: "Unknown error"
675
+ });
676
+ }
677
+ }
678
+ catch (error) {
679
+ failed++;
680
+ results.push({
681
+ email: contact.email,
682
+ success: false,
683
+ error: error instanceof Error ? error.message : String(error),
684
+ });
685
+ }
671
686
  }
672
687
  return {
673
- success: true,
674
- created: data.created ?? args.contacts.length,
688
+ success: created > 0,
689
+ created,
690
+ failed,
691
+ results,
675
692
  };
676
693
  },
677
694
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devwithbobby/loops",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Convex component for integrating with Loops.so email marketing platform",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -694,7 +694,8 @@ export const findContact = za({
694
694
 
695
695
  /**
696
696
  * Batch create contacts
697
- * Create multiple contacts in a single API call
697
+ * Creates multiple contacts sequentially using the single contact create endpoint.
698
+ * Note: Loops.so doesn't have a batch endpoint, so we create contacts one by one.
698
699
  */
699
700
  export const batchCreateContacts = za({
700
701
  args: z.object({
@@ -704,40 +705,53 @@ export const batchCreateContacts = za({
704
705
  returns: z.object({
705
706
  success: z.boolean(),
706
707
  created: z.number().optional(),
708
+ failed: z.number().optional(),
709
+ results: z.array(z.object({
710
+ email: z.string(),
711
+ success: z.boolean(),
712
+ error: z.string().optional(),
713
+ })).optional(),
707
714
  }),
708
715
  handler: async (ctx, args) => {
709
- const response = await fetch(`${LOOPS_API_BASE_URL}/contacts/batch`, {
710
- method: "POST",
711
- headers: {
712
- Authorization: `Bearer ${args.apiKey}`,
713
- "Content-Type": "application/json",
714
- },
715
- body: JSON.stringify({ contacts: args.contacts }),
716
- });
717
-
718
- if (!response.ok) {
719
- const errorText = await response.text();
720
- console.error(`Loops API error [${response.status}]:`, errorText);
721
- throw sanitizeError(response.status, errorText);
722
- }
723
-
724
- const data = (await response.json()) as { created?: number };
716
+ let created = 0;
717
+ let failed = 0;
718
+ const results: Array<{ email: string; success: boolean; error?: string }> = [];
725
719
 
720
+ // Create contacts one by one since Loops.so doesn't have a batch endpoint
726
721
  for (const contact of args.contacts) {
727
- await ctx.runMutation(((internal as any).lib.storeContact) as any, {
728
- email: contact.email,
729
- firstName: contact.firstName,
730
- lastName: contact.lastName,
731
- userId: contact.userId,
732
- source: contact.source,
733
- subscribed: contact.subscribed,
734
- userGroup: contact.userGroup,
735
- });
722
+ try {
723
+ // Use the addContact function which handles create/update logic
724
+ const result = await ctx.runAction(((internal as any).lib).addContact as any, {
725
+ apiKey: args.apiKey,
726
+ contact,
727
+ });
728
+
729
+ if (result.success) {
730
+ created++;
731
+ results.push({ email: contact.email, success: true });
732
+ } else {
733
+ failed++;
734
+ results.push({
735
+ email: contact.email,
736
+ success: false,
737
+ error: "Unknown error"
738
+ });
739
+ }
740
+ } catch (error) {
741
+ failed++;
742
+ results.push({
743
+ email: contact.email,
744
+ success: false,
745
+ error: error instanceof Error ? error.message : String(error),
746
+ });
747
+ }
736
748
  }
737
749
 
738
750
  return {
739
- success: true,
740
- created: data.created ?? args.contacts.length,
751
+ success: created > 0,
752
+ created,
753
+ failed,
754
+ results,
741
755
  };
742
756
  },
743
757
  });