@devwithbobby/loops 0.1.13 → 0.1.16

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,26 +1,8 @@
1
1
  import { z } from "zod";
2
+ import { internalLib } from "../types";
2
3
  import { za, zm, zq } from "../utils.js";
3
- import { internal } from "./_generated/api";
4
+ import { loopsFetch, sanitizeLoopsError } from "./helpers";
4
5
  import { contactValidator } from "./validators.js";
5
- const LOOPS_API_BASE_URL = "https://app.loops.so/api/v1";
6
- /**
7
- * Sanitize error messages to avoid leaking sensitive information
8
- */
9
- const sanitizeError = (status, _errorText) => {
10
- if (status === 401 || status === 403) {
11
- return new Error("Authentication failed. Please check your API key.");
12
- }
13
- if (status === 404) {
14
- return new Error("Resource not found.");
15
- }
16
- if (status === 429) {
17
- return new Error("Rate limit exceeded. Please try again later.");
18
- }
19
- if (status >= 500) {
20
- return new Error("Loops service error. Please try again later.");
21
- }
22
- return new Error(`Loops API error (${status}). Please try again.`);
23
- };
24
6
  /**
25
7
  * Internal mutation to store/update a contact in the database
26
8
  */
@@ -111,21 +93,14 @@ export const logEmailOperation = zm({
111
93
  email: args.email,
112
94
  timestamp: Date.now(),
113
95
  success: args.success,
96
+ actorId: args.actorId,
97
+ transactionalId: args.transactionalId,
98
+ campaignId: args.campaignId,
99
+ loopId: args.loopId,
100
+ eventName: args.eventName,
101
+ messageId: args.messageId,
102
+ metadata: args.metadata,
114
103
  };
115
- if (args.actorId)
116
- operationData.actorId = args.actorId;
117
- if (args.transactionalId)
118
- operationData.transactionalId = args.transactionalId;
119
- if (args.campaignId)
120
- operationData.campaignId = args.campaignId;
121
- if (args.loopId)
122
- operationData.loopId = args.loopId;
123
- if (args.eventName)
124
- operationData.eventName = args.eventName;
125
- if (args.messageId)
126
- operationData.messageId = args.messageId;
127
- if (args.metadata)
128
- operationData.metadata = args.metadata;
129
104
  await ctx.db.insert("emailOperations", operationData);
130
105
  },
131
106
  });
@@ -275,36 +250,22 @@ export const addContact = za({
275
250
  id: z.string().optional(),
276
251
  }),
277
252
  handler: async (ctx, args) => {
278
- const response = await fetch(`${LOOPS_API_BASE_URL}/contacts/create`, {
253
+ const createResponse = await loopsFetch(args.apiKey, "/contacts/create", {
279
254
  method: "POST",
280
- headers: {
281
- Authorization: `Bearer ${args.apiKey}`,
282
- "Content-Type": "application/json",
283
- },
284
- body: JSON.stringify(args.contact),
255
+ json: args.contact,
285
256
  });
286
- if (!response.ok) {
287
- const errorText = await response.text();
288
- if (response.status === 409) {
257
+ if (!createResponse.ok) {
258
+ const errorText = await createResponse.text();
259
+ if (createResponse.status === 409) {
289
260
  console.log(`Contact ${args.contact.email} already exists, updating instead`);
290
- const findResponse = await fetch(`${LOOPS_API_BASE_URL}/contacts/find?email=${encodeURIComponent(args.contact.email)}`, {
291
- method: "GET",
292
- headers: {
293
- Authorization: `Bearer ${args.apiKey}`,
294
- "Content-Type": "application/json",
295
- },
296
- });
261
+ const findResponse = await loopsFetch(args.apiKey, `/contacts/find?email=${encodeURIComponent(args.contact.email)}`, { method: "GET" });
297
262
  if (!findResponse.ok) {
298
263
  const findErrorText = await findResponse.text();
299
264
  console.error(`Failed to find existing contact [${findResponse.status}]:`, findErrorText);
300
265
  }
301
- const updateResponse = await fetch(`${LOOPS_API_BASE_URL}/contacts/update`, {
266
+ const updateResponse = await loopsFetch(args.apiKey, "/contacts/update", {
302
267
  method: "PUT",
303
- headers: {
304
- Authorization: `Bearer ${args.apiKey}`,
305
- "Content-Type": "application/json",
306
- },
307
- body: JSON.stringify({
268
+ json: {
308
269
  email: args.contact.email,
309
270
  firstName: args.contact.firstName,
310
271
  lastName: args.contact.lastName,
@@ -312,12 +273,12 @@ export const addContact = za({
312
273
  source: args.contact.source,
313
274
  subscribed: args.contact.subscribed,
314
275
  userGroup: args.contact.userGroup,
315
- }),
276
+ },
316
277
  });
317
278
  if (!updateResponse.ok) {
318
279
  const updateErrorText = await updateResponse.text();
319
280
  console.error(`Loops API error [${updateResponse.status}]:`, updateErrorText);
320
- throw sanitizeError(updateResponse.status, updateErrorText);
281
+ throw sanitizeLoopsError(updateResponse.status, updateErrorText);
321
282
  }
322
283
  // Get contact ID if available
323
284
  let contactId;
@@ -326,7 +287,7 @@ export const addContact = za({
326
287
  contactId = findData.id;
327
288
  }
328
289
  // Store/update in our database
329
- await ctx.runMutation(internal.lib.storeContact, {
290
+ await ctx.runMutation(internalLib.storeContact, {
330
291
  email: args.contact.email,
331
292
  firstName: args.contact.firstName,
332
293
  lastName: args.contact.lastName,
@@ -341,13 +302,12 @@ export const addContact = za({
341
302
  id: contactId,
342
303
  };
343
304
  }
344
- // For other errors, throw as normal
345
- console.error(`Loops API error [${response.status}]:`, errorText);
346
- throw sanitizeError(response.status, errorText);
305
+ console.error(`Loops API error [${createResponse.status}]:`, errorText);
306
+ throw sanitizeLoopsError(createResponse.status, errorText);
347
307
  }
348
308
  // Contact was created successfully
349
- const data = (await response.json());
350
- await ctx.runMutation(internal.lib.storeContact, {
309
+ const data = (await createResponse.json());
310
+ await ctx.runMutation(internalLib.storeContact, {
351
311
  email: args.contact.email,
352
312
  firstName: args.contact.firstName,
353
313
  lastName: args.contact.lastName,
@@ -382,13 +342,9 @@ export const updateContact = za({
382
342
  success: z.boolean(),
383
343
  }),
384
344
  handler: async (ctx, args) => {
385
- const response = await fetch(`${LOOPS_API_BASE_URL}/contacts/update`, {
345
+ const response = await loopsFetch(args.apiKey, "/contacts/update", {
386
346
  method: "PUT",
387
- headers: {
388
- Authorization: `Bearer ${args.apiKey}`,
389
- "Content-Type": "application/json",
390
- },
391
- body: JSON.stringify({
347
+ json: {
392
348
  email: args.email,
393
349
  dataVariables: args.dataVariables,
394
350
  firstName: args.firstName,
@@ -397,14 +353,14 @@ export const updateContact = za({
397
353
  source: args.source,
398
354
  subscribed: args.subscribed,
399
355
  userGroup: args.userGroup,
400
- }),
356
+ },
401
357
  });
402
358
  if (!response.ok) {
403
359
  const errorText = await response.text();
404
360
  console.error(`Loops API error [${response.status}]:`, errorText);
405
- throw sanitizeError(response.status, errorText);
361
+ throw sanitizeLoopsError(response.status, errorText);
406
362
  }
407
- await ctx.runMutation(internal.lib.storeContact, {
363
+ await ctx.runMutation(internalLib.storeContact, {
408
364
  email: args.email,
409
365
  firstName: args.firstName,
410
366
  lastName: args.lastName,
@@ -431,31 +387,27 @@ export const sendTransactional = za({
431
387
  messageId: z.string().optional(),
432
388
  }),
433
389
  handler: async (ctx, args) => {
434
- const response = await fetch(`${LOOPS_API_BASE_URL}/transactional`, {
390
+ const response = await loopsFetch(args.apiKey, "/transactional", {
435
391
  method: "POST",
436
- headers: {
437
- Authorization: `Bearer ${args.apiKey}`,
438
- "Content-Type": "application/json",
439
- },
440
- body: JSON.stringify({
392
+ json: {
441
393
  transactionalId: args.transactionalId,
442
394
  email: args.email,
443
395
  dataVariables: args.dataVariables,
444
- }),
396
+ },
445
397
  });
446
398
  if (!response.ok) {
447
399
  const errorText = await response.text();
448
400
  console.error(`Loops API error [${response.status}]:`, errorText);
449
- await ctx.runMutation(internal.lib.logEmailOperation, {
401
+ await ctx.runMutation(internalLib.logEmailOperation, {
450
402
  operationType: "transactional",
451
403
  email: args.email,
452
404
  success: false,
453
405
  transactionalId: args.transactionalId,
454
406
  });
455
- throw sanitizeError(response.status, errorText);
407
+ throw sanitizeLoopsError(response.status, errorText);
456
408
  }
457
409
  const data = (await response.json());
458
- await ctx.runMutation(internal.lib.logEmailOperation, {
410
+ await ctx.runMutation(internalLib.logEmailOperation, {
459
411
  operationType: "transactional",
460
412
  email: args.email,
461
413
  success: true,
@@ -482,22 +434,18 @@ export const sendEvent = za({
482
434
  success: z.boolean(),
483
435
  }),
484
436
  handler: async (_ctx, args) => {
485
- const response = await fetch(`${LOOPS_API_BASE_URL}/events/send`, {
437
+ const response = await loopsFetch(args.apiKey, "/events/send", {
486
438
  method: "POST",
487
- headers: {
488
- Authorization: `Bearer ${args.apiKey}`,
489
- "Content-Type": "application/json",
490
- },
491
- body: JSON.stringify({
439
+ json: {
492
440
  email: args.email,
493
441
  eventName: args.eventName,
494
442
  eventProperties: args.eventProperties,
495
- }),
443
+ },
496
444
  });
497
445
  if (!response.ok) {
498
446
  const errorText = await response.text();
499
447
  console.error(`Loops API error [${response.status}]:`, errorText);
500
- throw sanitizeError(response.status, errorText);
448
+ throw sanitizeLoopsError(response.status, errorText);
501
449
  }
502
450
  return { success: true };
503
451
  },
@@ -514,20 +462,16 @@ export const deleteContact = za({
514
462
  success: z.boolean(),
515
463
  }),
516
464
  handler: async (ctx, args) => {
517
- const response = await fetch(`${LOOPS_API_BASE_URL}/contacts/delete`, {
465
+ const response = await loopsFetch(args.apiKey, "/contacts/delete", {
518
466
  method: "POST",
519
- headers: {
520
- Authorization: `Bearer ${args.apiKey}`,
521
- "Content-Type": "application/json",
522
- },
523
- body: JSON.stringify({ email: args.email }),
467
+ json: { email: args.email },
524
468
  });
525
469
  if (!response.ok) {
526
470
  const errorText = await response.text();
527
471
  console.error(`Loops API error [${response.status}]:`, errorText);
528
- throw sanitizeError(response.status, errorText);
472
+ throw sanitizeLoopsError(response.status, errorText);
529
473
  }
530
- await ctx.runMutation(internal.lib.removeContact, {
474
+ await ctx.runMutation(internalLib.removeContact, {
531
475
  email: args.email,
532
476
  });
533
477
  return { success: true };
@@ -568,7 +512,7 @@ export const triggerLoop = za({
568
512
  const eventName = args.eventName || `loop_${args.loopId}`;
569
513
  try {
570
514
  // Send event to trigger the loop
571
- await ctx.runAction(internal.lib.sendEvent, {
515
+ await ctx.runAction(internalLib.sendEvent, {
572
516
  apiKey: args.apiKey,
573
517
  email: args.email,
574
518
  eventName,
@@ -578,7 +522,7 @@ export const triggerLoop = za({
578
522
  },
579
523
  });
580
524
  // Log as loop operation
581
- await ctx.runMutation(internal.lib.logEmailOperation, {
525
+ await ctx.runMutation(internalLib.logEmailOperation, {
582
526
  operationType: "loop",
583
527
  email: args.email,
584
528
  success: true,
@@ -592,7 +536,7 @@ export const triggerLoop = za({
592
536
  }
593
537
  catch (error) {
594
538
  // Log failed loop operation
595
- await ctx.runMutation(internal.lib.logEmailOperation, {
539
+ await ctx.runMutation(internalLib.logEmailOperation, {
596
540
  operationType: "loop",
597
541
  email: args.email,
598
542
  success: false,
@@ -633,20 +577,14 @@ export const findContact = za({
633
577
  .optional(),
634
578
  }),
635
579
  handler: async (_ctx, args) => {
636
- const response = await fetch(`${LOOPS_API_BASE_URL}/contacts/find?email=${encodeURIComponent(args.email)}`, {
637
- method: "GET",
638
- headers: {
639
- Authorization: `Bearer ${args.apiKey}`,
640
- "Content-Type": "application/json",
641
- },
642
- });
580
+ const response = await loopsFetch(args.apiKey, `/contacts/find?email=${encodeURIComponent(args.email)}`, { method: "GET" });
643
581
  if (!response.ok) {
644
582
  if (response.status === 404) {
645
583
  return { success: false, contact: undefined };
646
584
  }
647
585
  const errorText = await response.text();
648
586
  console.error(`Loops API error [${response.status}]:`, errorText);
649
- throw sanitizeError(response.status, errorText);
587
+ throw sanitizeLoopsError(response.status, errorText);
650
588
  }
651
589
  const data = (await response.json());
652
590
  // Handle case where Loops returns an array instead of a single object
@@ -694,7 +632,7 @@ export const batchCreateContacts = za({
694
632
  for (const contact of args.contacts) {
695
633
  try {
696
634
  // Use the addContact function which handles create/update logic
697
- const result = await ctx.runAction(internal.lib.addContact, {
635
+ const result = await ctx.runAction(internalLib.addContact, {
698
636
  apiKey: args.apiKey,
699
637
  contact,
700
638
  });
@@ -741,20 +679,16 @@ export const unsubscribeContact = za({
741
679
  success: z.boolean(),
742
680
  }),
743
681
  handler: async (ctx, args) => {
744
- const response = await fetch(`${LOOPS_API_BASE_URL}/contacts/unsubscribe`, {
682
+ const response = await loopsFetch(args.apiKey, "/contacts/unsubscribe", {
745
683
  method: "POST",
746
- headers: {
747
- Authorization: `Bearer ${args.apiKey}`,
748
- "Content-Type": "application/json",
749
- },
750
- body: JSON.stringify({ email: args.email }),
684
+ json: { email: args.email },
751
685
  });
752
686
  if (!response.ok) {
753
687
  const errorText = await response.text();
754
688
  console.error(`Loops API error [${response.status}]:`, errorText);
755
- throw sanitizeError(response.status, errorText);
689
+ throw sanitizeLoopsError(response.status, errorText);
756
690
  }
757
- await ctx.runMutation(internal.lib.storeContact, {
691
+ await ctx.runMutation(internalLib.storeContact, {
758
692
  email: args.email,
759
693
  subscribed: false,
760
694
  });
@@ -774,20 +708,16 @@ export const resubscribeContact = za({
774
708
  success: z.boolean(),
775
709
  }),
776
710
  handler: async (ctx, args) => {
777
- const response = await fetch(`${LOOPS_API_BASE_URL}/contacts/resubscribe`, {
711
+ const response = await loopsFetch(args.apiKey, "/contacts/resubscribe", {
778
712
  method: "POST",
779
- headers: {
780
- Authorization: `Bearer ${args.apiKey}`,
781
- "Content-Type": "application/json",
782
- },
783
- body: JSON.stringify({ email: args.email }),
713
+ json: { email: args.email },
784
714
  });
785
715
  if (!response.ok) {
786
716
  const errorText = await response.text();
787
717
  console.error(`Loops API error [${response.status}]:`, errorText);
788
- throw sanitizeError(response.status, errorText);
718
+ throw sanitizeLoopsError(response.status, errorText);
789
719
  }
790
- await ctx.runMutation(internal.lib.storeContact, {
720
+ await ctx.runMutation(internalLib.storeContact, {
791
721
  email: args.email,
792
722
  subscribed: true,
793
723
  });
@@ -1 +1 @@
1
- {"version":3,"file":"contacts.d.ts","sourceRoot":"","sources":["../../../src/component/tables/contacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAWnB,CAAC"}
1
+ {"version":3,"file":"contacts.d.ts","sourceRoot":"","sources":["../../../src/component/tables/contacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAYu99B,EAAG,SAAS;;;;;;;;uBAAgW,EAAG,SAAS;;CADl2+B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"emailOperations.d.ts","sourceRoot":"","sources":["../../../src/component/tables/emailOperations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAY1B,CAAC"}
1
+ {"version":3,"file":"emailOperations.d.ts","sourceRoot":"","sources":["../../../src/component/tables/emailOperations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAay29B,EAAG,SAAS;;;;;;;;uBAAgW,EAAG,SAAS;;CAD3v+B,CAAC"}
@@ -0,0 +1,97 @@
1
+ import type { Expand, FunctionArgs, FunctionReference, FunctionReturnType, StorageActionWriter, StorageReader } from "convex/server";
2
+ import type { GenericId } from "convex/values";
3
+ export type RunQueryCtx = {
4
+ runQuery: <Query extends FunctionReference<"query", "internal">>(query: Query, args: FunctionArgs<Query>) => Promise<FunctionReturnType<Query>>;
5
+ };
6
+ export type RunMutationCtx = RunQueryCtx & {
7
+ runMutation: <Mutation extends FunctionReference<"mutation", "internal">>(mutation: Mutation, args: FunctionArgs<Mutation>) => Promise<FunctionReturnType<Mutation>>;
8
+ };
9
+ export type RunActionCtx = RunMutationCtx & {
10
+ runAction<Action extends FunctionReference<"action", "internal">>(action: Action, args: FunctionArgs<Action>): Promise<FunctionReturnType<Action>>;
11
+ };
12
+ export type ActionCtx = RunActionCtx & {
13
+ storage: StorageActionWriter;
14
+ };
15
+ export type QueryCtx = RunQueryCtx & {
16
+ storage: StorageReader;
17
+ };
18
+ export type OpaqueIds<T> = T extends GenericId<infer _T> ? string : T extends (infer U)[] ? OpaqueIds<U>[] : T extends ArrayBuffer ? ArrayBuffer : T extends object ? {
19
+ [K in keyof T]: OpaqueIds<T[K]>;
20
+ } : T;
21
+ export type UseApi<API> = Expand<{
22
+ [mod in keyof API]: API[mod] extends FunctionReference<infer FType, "public", infer FArgs, infer FReturnType, infer FComponentPath> ? FunctionReference<FType, "internal", OpaqueIds<FArgs>, OpaqueIds<FReturnType>, FComponentPath> : UseApi<API[mod]>;
23
+ }>;
24
+ export type HeadersInitParam = ConstructorParameters<typeof Headers>[0];
25
+ export interface ContactPayload {
26
+ email: string;
27
+ firstName?: string;
28
+ lastName?: string;
29
+ userId?: string;
30
+ source?: string;
31
+ subscribed?: boolean;
32
+ userGroup?: string;
33
+ }
34
+ export interface UpdateContactPayload extends Partial<ContactPayload> {
35
+ email: string;
36
+ dataVariables?: Record<string, unknown>;
37
+ }
38
+ export interface DeleteContactPayload {
39
+ email?: string;
40
+ }
41
+ export interface TransactionalPayload {
42
+ transactionalId?: string;
43
+ email?: string;
44
+ dataVariables?: Record<string, unknown>;
45
+ }
46
+ export interface EventPayload {
47
+ email?: string;
48
+ eventName?: string;
49
+ eventProperties?: Record<string, unknown>;
50
+ }
51
+ export interface TriggerPayload {
52
+ loopId?: string;
53
+ email?: string;
54
+ dataVariables?: Record<string, unknown>;
55
+ eventName?: string;
56
+ }
57
+ export type InternalActionRef<Args extends Record<string, unknown> = Record<string, unknown>, Result = unknown> = FunctionReference<"action", "internal", Args, Result>;
58
+ export type InternalMutationRef<Args extends Record<string, unknown> = Record<string, unknown>, Result = unknown> = FunctionReference<"mutation", "internal", Args, Result>;
59
+ export type InternalQueryRef<Args extends Record<string, unknown> = Record<string, unknown>, Result = unknown> = FunctionReference<"query", "internal", Args, Result>;
60
+ type AddContactArgs = {
61
+ apiKey: string;
62
+ contact: ContactPayload;
63
+ };
64
+ type AddContactResult = {
65
+ success: boolean;
66
+ id?: string;
67
+ };
68
+ export interface InternalActionLib {
69
+ addContact: InternalActionRef<AddContactArgs, AddContactResult>;
70
+ updateContact: InternalActionRef;
71
+ findContact: InternalActionRef;
72
+ deleteContact: InternalActionRef;
73
+ sendTransactional: InternalActionRef;
74
+ sendEvent: InternalActionRef;
75
+ triggerLoop: InternalActionRef;
76
+ batchCreateContacts: InternalActionRef;
77
+ unsubscribeContact: InternalActionRef;
78
+ resubscribeContact: InternalActionRef;
79
+ storeContact: InternalMutationRef;
80
+ removeContact: InternalMutationRef;
81
+ logEmailOperation: InternalMutationRef;
82
+ }
83
+ export interface InternalQueryLib {
84
+ countContacts: InternalQueryRef;
85
+ listContacts: InternalQueryRef;
86
+ detectRecipientSpam: InternalQueryRef;
87
+ detectActorSpam: InternalQueryRef;
88
+ getEmailStats: InternalQueryRef;
89
+ detectRapidFirePatterns: InternalQueryRef;
90
+ checkRecipientRateLimit: InternalQueryRef;
91
+ checkActorRateLimit: InternalQueryRef;
92
+ checkGlobalRateLimit: InternalQueryRef;
93
+ }
94
+ export type InternalLibReferences = InternalActionLib & InternalQueryLib;
95
+ export declare const internalLib: InternalLibReferences;
96
+ export {};
97
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ import { internal } from "./component/_generated/api";
2
+ export const internalLib = internal.lib;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devwithbobby/loops",
3
- "version": "0.1.13",
3
+ "version": "0.1.16",
4
4
  "description": "Convex component for integrating with Loops.so email marketing platform",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -93,7 +93,6 @@
93
93
  "convex": "^1.28.0",
94
94
  "convex-helpers": "^0.1.104",
95
95
  "convex-test": "^0.0.38",
96
- "lefthook": "^2.0.0",
97
96
  "npm-run-all": "^4.1.5",
98
97
  "pkg-pr-new": "^0.0.60",
99
98
  "react": "^19.2.0",