@devwithbobby/loops 0.1.13 → 0.1.14
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/client/index.d.ts +232 -44
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +21 -32
- package/dist/component/convex.config.d.ts.map +1 -1
- package/dist/component/convex.config.js +1 -1
- package/dist/component/helpers.d.ts +7 -0
- package/dist/component/helpers.d.ts.map +1 -0
- package/dist/component/helpers.js +30 -0
- package/dist/component/http.d.ts +3 -0
- package/dist/component/http.d.ts.map +1 -0
- package/dist/component/http.js +268 -0
- package/dist/component/lib.d.ts.map +1 -1
- package/dist/component/lib.js +57 -127
- package/dist/types.d.ts +97 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/package.json +1 -1
- package/src/client/index.ts +27 -54
- package/src/component/_generated/api.d.ts +3 -11
- package/src/component/convex.config.ts +7 -2
- package/src/component/helpers.ts +44 -0
- package/src/component/http.ts +304 -0
- package/src/component/lib.ts +78 -141
- package/src/types.ts +168 -0
- package/src/client/types.ts +0 -64
package/src/component/lib.ts
CHANGED
|
@@ -1,30 +1,10 @@
|
|
|
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
4
|
import type { Doc } from "./_generated/dataModel.js";
|
|
5
|
+
import { loopsFetch, sanitizeLoopsError } from "./helpers";
|
|
5
6
|
import { contactValidator } from "./validators.js";
|
|
6
7
|
|
|
7
|
-
const LOOPS_API_BASE_URL = "https://app.loops.so/api/v1";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Sanitize error messages to avoid leaking sensitive information
|
|
11
|
-
*/
|
|
12
|
-
const sanitizeError = (status: number, _errorText: string): Error => {
|
|
13
|
-
if (status === 401 || status === 403) {
|
|
14
|
-
return new Error("Authentication failed. Please check your API key.");
|
|
15
|
-
}
|
|
16
|
-
if (status === 404) {
|
|
17
|
-
return new Error("Resource not found.");
|
|
18
|
-
}
|
|
19
|
-
if (status === 429) {
|
|
20
|
-
return new Error("Rate limit exceeded. Please try again later.");
|
|
21
|
-
}
|
|
22
|
-
if (status >= 500) {
|
|
23
|
-
return new Error("Loops service error. Please try again later.");
|
|
24
|
-
}
|
|
25
|
-
return new Error(`Loops API error (${status}). Please try again.`);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
8
|
/**
|
|
29
9
|
* Internal mutation to store/update a contact in the database
|
|
30
10
|
*/
|
|
@@ -113,23 +93,24 @@ export const logEmailOperation = zm({
|
|
|
113
93
|
}),
|
|
114
94
|
returns: z.void(),
|
|
115
95
|
handler: async (ctx, args) => {
|
|
116
|
-
const operationData:
|
|
96
|
+
const operationData: Omit<
|
|
97
|
+
Doc<"emailOperations">,
|
|
98
|
+
"_id" | "_creationTime"
|
|
99
|
+
> = {
|
|
117
100
|
operationType: args.operationType,
|
|
118
101
|
email: args.email,
|
|
119
102
|
timestamp: Date.now(),
|
|
120
103
|
success: args.success,
|
|
104
|
+
actorId: args.actorId,
|
|
105
|
+
transactionalId: args.transactionalId,
|
|
106
|
+
campaignId: args.campaignId,
|
|
107
|
+
loopId: args.loopId,
|
|
108
|
+
eventName: args.eventName,
|
|
109
|
+
messageId: args.messageId,
|
|
110
|
+
metadata: args.metadata,
|
|
121
111
|
};
|
|
122
112
|
|
|
123
|
-
|
|
124
|
-
if (args.transactionalId)
|
|
125
|
-
operationData.transactionalId = args.transactionalId;
|
|
126
|
-
if (args.campaignId) operationData.campaignId = args.campaignId;
|
|
127
|
-
if (args.loopId) operationData.loopId = args.loopId;
|
|
128
|
-
if (args.eventName) operationData.eventName = args.eventName;
|
|
129
|
-
if (args.messageId) operationData.messageId = args.messageId;
|
|
130
|
-
if (args.metadata) operationData.metadata = args.metadata;
|
|
131
|
-
|
|
132
|
-
await ctx.db.insert("emailOperations", operationData as any);
|
|
113
|
+
await ctx.db.insert("emailOperations", operationData);
|
|
133
114
|
},
|
|
134
115
|
});
|
|
135
116
|
|
|
@@ -284,32 +265,23 @@ export const addContact = za({
|
|
|
284
265
|
id: z.string().optional(),
|
|
285
266
|
}),
|
|
286
267
|
handler: async (ctx, args) => {
|
|
287
|
-
const
|
|
268
|
+
const createResponse = await loopsFetch(args.apiKey, "/contacts/create", {
|
|
288
269
|
method: "POST",
|
|
289
|
-
|
|
290
|
-
Authorization: `Bearer ${args.apiKey}`,
|
|
291
|
-
"Content-Type": "application/json",
|
|
292
|
-
},
|
|
293
|
-
body: JSON.stringify(args.contact),
|
|
270
|
+
json: args.contact,
|
|
294
271
|
});
|
|
295
272
|
|
|
296
|
-
if (!
|
|
297
|
-
const errorText = await
|
|
273
|
+
if (!createResponse.ok) {
|
|
274
|
+
const errorText = await createResponse.text();
|
|
298
275
|
|
|
299
|
-
if (
|
|
276
|
+
if (createResponse.status === 409) {
|
|
300
277
|
console.log(
|
|
301
278
|
`Contact ${args.contact.email} already exists, updating instead`,
|
|
302
279
|
);
|
|
303
280
|
|
|
304
|
-
const findResponse = await
|
|
305
|
-
|
|
306
|
-
{
|
|
307
|
-
|
|
308
|
-
headers: {
|
|
309
|
-
Authorization: `Bearer ${args.apiKey}`,
|
|
310
|
-
"Content-Type": "application/json",
|
|
311
|
-
},
|
|
312
|
-
},
|
|
281
|
+
const findResponse = await loopsFetch(
|
|
282
|
+
args.apiKey,
|
|
283
|
+
`/contacts/find?email=${encodeURIComponent(args.contact.email)}`,
|
|
284
|
+
{ method: "GET" },
|
|
313
285
|
);
|
|
314
286
|
|
|
315
287
|
if (!findResponse.ok) {
|
|
@@ -320,15 +292,12 @@ export const addContact = za({
|
|
|
320
292
|
);
|
|
321
293
|
}
|
|
322
294
|
|
|
323
|
-
const updateResponse = await
|
|
324
|
-
|
|
295
|
+
const updateResponse = await loopsFetch(
|
|
296
|
+
args.apiKey,
|
|
297
|
+
"/contacts/update",
|
|
325
298
|
{
|
|
326
299
|
method: "PUT",
|
|
327
|
-
|
|
328
|
-
Authorization: `Bearer ${args.apiKey}`,
|
|
329
|
-
"Content-Type": "application/json",
|
|
330
|
-
},
|
|
331
|
-
body: JSON.stringify({
|
|
300
|
+
json: {
|
|
332
301
|
email: args.contact.email,
|
|
333
302
|
firstName: args.contact.firstName,
|
|
334
303
|
lastName: args.contact.lastName,
|
|
@@ -336,7 +305,7 @@ export const addContact = za({
|
|
|
336
305
|
source: args.contact.source,
|
|
337
306
|
subscribed: args.contact.subscribed,
|
|
338
307
|
userGroup: args.contact.userGroup,
|
|
339
|
-
}
|
|
308
|
+
},
|
|
340
309
|
},
|
|
341
310
|
);
|
|
342
311
|
|
|
@@ -346,7 +315,7 @@ export const addContact = za({
|
|
|
346
315
|
`Loops API error [${updateResponse.status}]:`,
|
|
347
316
|
updateErrorText,
|
|
348
317
|
);
|
|
349
|
-
throw
|
|
318
|
+
throw sanitizeLoopsError(updateResponse.status, updateErrorText);
|
|
350
319
|
}
|
|
351
320
|
|
|
352
321
|
// Get contact ID if available
|
|
@@ -357,7 +326,7 @@ export const addContact = za({
|
|
|
357
326
|
}
|
|
358
327
|
|
|
359
328
|
// Store/update in our database
|
|
360
|
-
await ctx.runMutation(
|
|
329
|
+
await ctx.runMutation(internalLib.storeContact, {
|
|
361
330
|
email: args.contact.email,
|
|
362
331
|
firstName: args.contact.firstName,
|
|
363
332
|
lastName: args.contact.lastName,
|
|
@@ -374,15 +343,14 @@ export const addContact = za({
|
|
|
374
343
|
};
|
|
375
344
|
}
|
|
376
345
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
throw sanitizeError(response.status, errorText);
|
|
346
|
+
console.error(`Loops API error [${createResponse.status}]:`, errorText);
|
|
347
|
+
throw sanitizeLoopsError(createResponse.status, errorText);
|
|
380
348
|
}
|
|
381
349
|
|
|
382
350
|
// Contact was created successfully
|
|
383
|
-
const data = (await
|
|
351
|
+
const data = (await createResponse.json()) as { id?: string };
|
|
384
352
|
|
|
385
|
-
await ctx.runMutation(
|
|
353
|
+
await ctx.runMutation(internalLib.storeContact, {
|
|
386
354
|
email: args.contact.email,
|
|
387
355
|
firstName: args.contact.firstName,
|
|
388
356
|
lastName: args.contact.lastName,
|
|
@@ -419,13 +387,9 @@ export const updateContact = za({
|
|
|
419
387
|
success: z.boolean(),
|
|
420
388
|
}),
|
|
421
389
|
handler: async (ctx, args) => {
|
|
422
|
-
const response = await
|
|
390
|
+
const response = await loopsFetch(args.apiKey, "/contacts/update", {
|
|
423
391
|
method: "PUT",
|
|
424
|
-
|
|
425
|
-
Authorization: `Bearer ${args.apiKey}`,
|
|
426
|
-
"Content-Type": "application/json",
|
|
427
|
-
},
|
|
428
|
-
body: JSON.stringify({
|
|
392
|
+
json: {
|
|
429
393
|
email: args.email,
|
|
430
394
|
dataVariables: args.dataVariables,
|
|
431
395
|
firstName: args.firstName,
|
|
@@ -434,16 +398,16 @@ export const updateContact = za({
|
|
|
434
398
|
source: args.source,
|
|
435
399
|
subscribed: args.subscribed,
|
|
436
400
|
userGroup: args.userGroup,
|
|
437
|
-
}
|
|
401
|
+
},
|
|
438
402
|
});
|
|
439
403
|
|
|
440
404
|
if (!response.ok) {
|
|
441
405
|
const errorText = await response.text();
|
|
442
406
|
console.error(`Loops API error [${response.status}]:`, errorText);
|
|
443
|
-
throw
|
|
407
|
+
throw sanitizeLoopsError(response.status, errorText);
|
|
444
408
|
}
|
|
445
409
|
|
|
446
|
-
await ctx.runMutation(
|
|
410
|
+
await ctx.runMutation(internalLib.storeContact, {
|
|
447
411
|
email: args.email,
|
|
448
412
|
firstName: args.firstName,
|
|
449
413
|
lastName: args.lastName,
|
|
@@ -472,35 +436,31 @@ export const sendTransactional = za({
|
|
|
472
436
|
messageId: z.string().optional(),
|
|
473
437
|
}),
|
|
474
438
|
handler: async (ctx, args) => {
|
|
475
|
-
const response = await
|
|
439
|
+
const response = await loopsFetch(args.apiKey, "/transactional", {
|
|
476
440
|
method: "POST",
|
|
477
|
-
|
|
478
|
-
Authorization: `Bearer ${args.apiKey}`,
|
|
479
|
-
"Content-Type": "application/json",
|
|
480
|
-
},
|
|
481
|
-
body: JSON.stringify({
|
|
441
|
+
json: {
|
|
482
442
|
transactionalId: args.transactionalId,
|
|
483
443
|
email: args.email,
|
|
484
444
|
dataVariables: args.dataVariables,
|
|
485
|
-
}
|
|
445
|
+
},
|
|
486
446
|
});
|
|
487
447
|
|
|
488
448
|
if (!response.ok) {
|
|
489
449
|
const errorText = await response.text();
|
|
490
450
|
console.error(`Loops API error [${response.status}]:`, errorText);
|
|
491
|
-
await ctx.runMutation(
|
|
451
|
+
await ctx.runMutation(internalLib.logEmailOperation, {
|
|
492
452
|
operationType: "transactional",
|
|
493
453
|
email: args.email,
|
|
494
454
|
success: false,
|
|
495
455
|
transactionalId: args.transactionalId,
|
|
496
456
|
});
|
|
497
457
|
|
|
498
|
-
throw
|
|
458
|
+
throw sanitizeLoopsError(response.status, errorText);
|
|
499
459
|
}
|
|
500
460
|
|
|
501
461
|
const data = (await response.json()) as { messageId?: string };
|
|
502
462
|
|
|
503
|
-
await ctx.runMutation(
|
|
463
|
+
await ctx.runMutation(internalLib.logEmailOperation, {
|
|
504
464
|
operationType: "transactional",
|
|
505
465
|
email: args.email,
|
|
506
466
|
success: true,
|
|
@@ -529,23 +489,19 @@ export const sendEvent = za({
|
|
|
529
489
|
success: z.boolean(),
|
|
530
490
|
}),
|
|
531
491
|
handler: async (_ctx, args) => {
|
|
532
|
-
const response = await
|
|
492
|
+
const response = await loopsFetch(args.apiKey, "/events/send", {
|
|
533
493
|
method: "POST",
|
|
534
|
-
|
|
535
|
-
Authorization: `Bearer ${args.apiKey}`,
|
|
536
|
-
"Content-Type": "application/json",
|
|
537
|
-
},
|
|
538
|
-
body: JSON.stringify({
|
|
494
|
+
json: {
|
|
539
495
|
email: args.email,
|
|
540
496
|
eventName: args.eventName,
|
|
541
497
|
eventProperties: args.eventProperties,
|
|
542
|
-
}
|
|
498
|
+
},
|
|
543
499
|
});
|
|
544
500
|
|
|
545
501
|
if (!response.ok) {
|
|
546
502
|
const errorText = await response.text();
|
|
547
503
|
console.error(`Loops API error [${response.status}]:`, errorText);
|
|
548
|
-
throw
|
|
504
|
+
throw sanitizeLoopsError(response.status, errorText);
|
|
549
505
|
}
|
|
550
506
|
|
|
551
507
|
return { success: true };
|
|
@@ -564,22 +520,18 @@ export const deleteContact = za({
|
|
|
564
520
|
success: z.boolean(),
|
|
565
521
|
}),
|
|
566
522
|
handler: async (ctx, args) => {
|
|
567
|
-
const response = await
|
|
523
|
+
const response = await loopsFetch(args.apiKey, "/contacts/delete", {
|
|
568
524
|
method: "POST",
|
|
569
|
-
|
|
570
|
-
Authorization: `Bearer ${args.apiKey}`,
|
|
571
|
-
"Content-Type": "application/json",
|
|
572
|
-
},
|
|
573
|
-
body: JSON.stringify({ email: args.email }),
|
|
525
|
+
json: { email: args.email },
|
|
574
526
|
});
|
|
575
527
|
|
|
576
528
|
if (!response.ok) {
|
|
577
529
|
const errorText = await response.text();
|
|
578
530
|
console.error(`Loops API error [${response.status}]:`, errorText);
|
|
579
|
-
throw
|
|
531
|
+
throw sanitizeLoopsError(response.status, errorText);
|
|
580
532
|
}
|
|
581
533
|
|
|
582
|
-
await ctx.runMutation(
|
|
534
|
+
await ctx.runMutation(internalLib.removeContact, {
|
|
583
535
|
email: args.email,
|
|
584
536
|
});
|
|
585
537
|
|
|
@@ -623,7 +575,7 @@ export const triggerLoop = za({
|
|
|
623
575
|
|
|
624
576
|
try {
|
|
625
577
|
// Send event to trigger the loop
|
|
626
|
-
await ctx.runAction(
|
|
578
|
+
await ctx.runAction(internalLib.sendEvent, {
|
|
627
579
|
apiKey: args.apiKey,
|
|
628
580
|
email: args.email,
|
|
629
581
|
eventName,
|
|
@@ -634,7 +586,7 @@ export const triggerLoop = za({
|
|
|
634
586
|
});
|
|
635
587
|
|
|
636
588
|
// Log as loop operation
|
|
637
|
-
await ctx.runMutation(
|
|
589
|
+
await ctx.runMutation(internalLib.logEmailOperation, {
|
|
638
590
|
operationType: "loop",
|
|
639
591
|
email: args.email,
|
|
640
592
|
success: true,
|
|
@@ -649,7 +601,7 @@ export const triggerLoop = za({
|
|
|
649
601
|
};
|
|
650
602
|
} catch (error) {
|
|
651
603
|
// Log failed loop operation
|
|
652
|
-
await ctx.runMutation(
|
|
604
|
+
await ctx.runMutation(internalLib.logEmailOperation, {
|
|
653
605
|
operationType: "loop",
|
|
654
606
|
email: args.email,
|
|
655
607
|
success: false,
|
|
@@ -692,15 +644,10 @@ export const findContact = za({
|
|
|
692
644
|
.optional(),
|
|
693
645
|
}),
|
|
694
646
|
handler: async (_ctx, args) => {
|
|
695
|
-
const response = await
|
|
696
|
-
|
|
697
|
-
{
|
|
698
|
-
|
|
699
|
-
headers: {
|
|
700
|
-
Authorization: `Bearer ${args.apiKey}`,
|
|
701
|
-
"Content-Type": "application/json",
|
|
702
|
-
},
|
|
703
|
-
},
|
|
647
|
+
const response = await loopsFetch(
|
|
648
|
+
args.apiKey,
|
|
649
|
+
`/contacts/find?email=${encodeURIComponent(args.email)}`,
|
|
650
|
+
{ method: "GET" },
|
|
704
651
|
);
|
|
705
652
|
|
|
706
653
|
if (!response.ok) {
|
|
@@ -709,12 +656,13 @@ export const findContact = za({
|
|
|
709
656
|
}
|
|
710
657
|
const errorText = await response.text();
|
|
711
658
|
console.error(`Loops API error [${response.status}]:`, errorText);
|
|
712
|
-
throw
|
|
659
|
+
throw sanitizeLoopsError(response.status, errorText);
|
|
713
660
|
}
|
|
714
661
|
|
|
662
|
+
type LoopsContactRecord = Record<string, unknown>;
|
|
715
663
|
const data = (await response.json()) as
|
|
716
|
-
|
|
|
717
|
-
| Array<
|
|
664
|
+
| LoopsContactRecord
|
|
665
|
+
| Array<LoopsContactRecord>;
|
|
718
666
|
|
|
719
667
|
// Handle case where Loops returns an array instead of a single object
|
|
720
668
|
let contact = Array.isArray(data) ? data[0] : data;
|
|
@@ -726,12 +674,12 @@ export const findContact = za({
|
|
|
726
674
|
key,
|
|
727
675
|
value === null ? undefined : value,
|
|
728
676
|
]),
|
|
729
|
-
) as
|
|
677
|
+
) as LoopsContactRecord;
|
|
730
678
|
}
|
|
731
679
|
|
|
732
680
|
return {
|
|
733
681
|
success: true,
|
|
734
|
-
contact: contact as
|
|
682
|
+
contact: contact as LoopsContactRecord | undefined,
|
|
735
683
|
};
|
|
736
684
|
},
|
|
737
685
|
});
|
|
@@ -770,13 +718,10 @@ export const batchCreateContacts = za({
|
|
|
770
718
|
for (const contact of args.contacts) {
|
|
771
719
|
try {
|
|
772
720
|
// Use the addContact function which handles create/update logic
|
|
773
|
-
const result = await ctx.runAction(
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
contact,
|
|
778
|
-
},
|
|
779
|
-
);
|
|
721
|
+
const result = await ctx.runAction(internalLib.addContact, {
|
|
722
|
+
apiKey: args.apiKey,
|
|
723
|
+
contact,
|
|
724
|
+
});
|
|
780
725
|
|
|
781
726
|
if (result.success) {
|
|
782
727
|
created++;
|
|
@@ -821,22 +766,18 @@ export const unsubscribeContact = za({
|
|
|
821
766
|
success: z.boolean(),
|
|
822
767
|
}),
|
|
823
768
|
handler: async (ctx, args) => {
|
|
824
|
-
const response = await
|
|
769
|
+
const response = await loopsFetch(args.apiKey, "/contacts/unsubscribe", {
|
|
825
770
|
method: "POST",
|
|
826
|
-
|
|
827
|
-
Authorization: `Bearer ${args.apiKey}`,
|
|
828
|
-
"Content-Type": "application/json",
|
|
829
|
-
},
|
|
830
|
-
body: JSON.stringify({ email: args.email }),
|
|
771
|
+
json: { email: args.email },
|
|
831
772
|
});
|
|
832
773
|
|
|
833
774
|
if (!response.ok) {
|
|
834
775
|
const errorText = await response.text();
|
|
835
776
|
console.error(`Loops API error [${response.status}]:`, errorText);
|
|
836
|
-
throw
|
|
777
|
+
throw sanitizeLoopsError(response.status, errorText);
|
|
837
778
|
}
|
|
838
779
|
|
|
839
|
-
await ctx.runMutation(
|
|
780
|
+
await ctx.runMutation(internalLib.storeContact, {
|
|
840
781
|
email: args.email,
|
|
841
782
|
subscribed: false,
|
|
842
783
|
});
|
|
@@ -858,22 +799,18 @@ export const resubscribeContact = za({
|
|
|
858
799
|
success: z.boolean(),
|
|
859
800
|
}),
|
|
860
801
|
handler: async (ctx, args) => {
|
|
861
|
-
const response = await
|
|
802
|
+
const response = await loopsFetch(args.apiKey, "/contacts/resubscribe", {
|
|
862
803
|
method: "POST",
|
|
863
|
-
|
|
864
|
-
Authorization: `Bearer ${args.apiKey}`,
|
|
865
|
-
"Content-Type": "application/json",
|
|
866
|
-
},
|
|
867
|
-
body: JSON.stringify({ email: args.email }),
|
|
804
|
+
json: { email: args.email },
|
|
868
805
|
});
|
|
869
806
|
|
|
870
807
|
if (!response.ok) {
|
|
871
808
|
const errorText = await response.text();
|
|
872
809
|
console.error(`Loops API error [${response.status}]:`, errorText);
|
|
873
|
-
throw
|
|
810
|
+
throw sanitizeLoopsError(response.status, errorText);
|
|
874
811
|
}
|
|
875
812
|
|
|
876
|
-
await ctx.runMutation(
|
|
813
|
+
await ctx.runMutation(internalLib.storeContact, {
|
|
877
814
|
email: args.email,
|
|
878
815
|
subscribed: true,
|
|
879
816
|
});
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Expand,
|
|
3
|
+
FunctionArgs,
|
|
4
|
+
FunctionReference,
|
|
5
|
+
FunctionReturnType,
|
|
6
|
+
StorageActionWriter,
|
|
7
|
+
StorageReader,
|
|
8
|
+
} from "convex/server";
|
|
9
|
+
import type { GenericId } from "convex/values";
|
|
10
|
+
import { internal } from "./component/_generated/api";
|
|
11
|
+
|
|
12
|
+
export type RunQueryCtx = {
|
|
13
|
+
runQuery: <Query extends FunctionReference<"query", "internal">>(
|
|
14
|
+
query: Query,
|
|
15
|
+
args: FunctionArgs<Query>,
|
|
16
|
+
) => Promise<FunctionReturnType<Query>>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type RunMutationCtx = RunQueryCtx & {
|
|
20
|
+
runMutation: <Mutation extends FunctionReference<"mutation", "internal">>(
|
|
21
|
+
mutation: Mutation,
|
|
22
|
+
args: FunctionArgs<Mutation>,
|
|
23
|
+
) => Promise<FunctionReturnType<Mutation>>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type RunActionCtx = RunMutationCtx & {
|
|
27
|
+
runAction<Action extends FunctionReference<"action", "internal">>(
|
|
28
|
+
action: Action,
|
|
29
|
+
args: FunctionArgs<Action>,
|
|
30
|
+
): Promise<FunctionReturnType<Action>>;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type ActionCtx = RunActionCtx & {
|
|
34
|
+
storage: StorageActionWriter;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type QueryCtx = RunQueryCtx & {
|
|
38
|
+
storage: StorageReader;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export type OpaqueIds<T> = T extends GenericId<infer _T>
|
|
42
|
+
? string
|
|
43
|
+
: T extends (infer U)[]
|
|
44
|
+
? OpaqueIds<U>[]
|
|
45
|
+
: T extends ArrayBuffer
|
|
46
|
+
? ArrayBuffer
|
|
47
|
+
: T extends object
|
|
48
|
+
? {
|
|
49
|
+
[K in keyof T]: OpaqueIds<T[K]>;
|
|
50
|
+
}
|
|
51
|
+
: T;
|
|
52
|
+
|
|
53
|
+
export type UseApi<API> = Expand<{
|
|
54
|
+
[mod in keyof API]: API[mod] extends FunctionReference<
|
|
55
|
+
infer FType,
|
|
56
|
+
"public",
|
|
57
|
+
infer FArgs,
|
|
58
|
+
infer FReturnType,
|
|
59
|
+
infer FComponentPath
|
|
60
|
+
>
|
|
61
|
+
? FunctionReference<
|
|
62
|
+
FType,
|
|
63
|
+
"internal",
|
|
64
|
+
OpaqueIds<FArgs>,
|
|
65
|
+
OpaqueIds<FReturnType>,
|
|
66
|
+
FComponentPath
|
|
67
|
+
>
|
|
68
|
+
: UseApi<API[mod]>;
|
|
69
|
+
}>;
|
|
70
|
+
|
|
71
|
+
export type HeadersInitParam = ConstructorParameters<typeof Headers>[0];
|
|
72
|
+
|
|
73
|
+
export interface ContactPayload {
|
|
74
|
+
email: string;
|
|
75
|
+
firstName?: string;
|
|
76
|
+
lastName?: string;
|
|
77
|
+
userId?: string;
|
|
78
|
+
source?: string;
|
|
79
|
+
subscribed?: boolean;
|
|
80
|
+
userGroup?: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface UpdateContactPayload extends Partial<ContactPayload> {
|
|
84
|
+
email: string;
|
|
85
|
+
dataVariables?: Record<string, unknown>;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface DeleteContactPayload {
|
|
89
|
+
email?: string;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface TransactionalPayload {
|
|
93
|
+
transactionalId?: string;
|
|
94
|
+
email?: string;
|
|
95
|
+
dataVariables?: Record<string, unknown>;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface EventPayload {
|
|
99
|
+
email?: string;
|
|
100
|
+
eventName?: string;
|
|
101
|
+
eventProperties?: Record<string, unknown>;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface TriggerPayload {
|
|
105
|
+
loopId?: string;
|
|
106
|
+
email?: string;
|
|
107
|
+
dataVariables?: Record<string, unknown>;
|
|
108
|
+
eventName?: string;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export type InternalActionRef<
|
|
112
|
+
Args extends Record<string, unknown> = Record<string, unknown>,
|
|
113
|
+
Result = unknown,
|
|
114
|
+
> = FunctionReference<"action", "internal", Args, Result>;
|
|
115
|
+
|
|
116
|
+
export type InternalMutationRef<
|
|
117
|
+
Args extends Record<string, unknown> = Record<string, unknown>,
|
|
118
|
+
Result = unknown,
|
|
119
|
+
> = FunctionReference<"mutation", "internal", Args, Result>;
|
|
120
|
+
|
|
121
|
+
export type InternalQueryRef<
|
|
122
|
+
Args extends Record<string, unknown> = Record<string, unknown>,
|
|
123
|
+
Result = unknown,
|
|
124
|
+
> = FunctionReference<"query", "internal", Args, Result>;
|
|
125
|
+
|
|
126
|
+
type AddContactArgs = {
|
|
127
|
+
apiKey: string;
|
|
128
|
+
contact: ContactPayload;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
type AddContactResult = {
|
|
132
|
+
success: boolean;
|
|
133
|
+
id?: string;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export interface InternalActionLib {
|
|
137
|
+
addContact: InternalActionRef<AddContactArgs, AddContactResult>;
|
|
138
|
+
updateContact: InternalActionRef;
|
|
139
|
+
findContact: InternalActionRef;
|
|
140
|
+
deleteContact: InternalActionRef;
|
|
141
|
+
sendTransactional: InternalActionRef;
|
|
142
|
+
sendEvent: InternalActionRef;
|
|
143
|
+
triggerLoop: InternalActionRef;
|
|
144
|
+
batchCreateContacts: InternalActionRef;
|
|
145
|
+
unsubscribeContact: InternalActionRef;
|
|
146
|
+
resubscribeContact: InternalActionRef;
|
|
147
|
+
storeContact: InternalMutationRef;
|
|
148
|
+
removeContact: InternalMutationRef;
|
|
149
|
+
logEmailOperation: InternalMutationRef;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface InternalQueryLib {
|
|
153
|
+
countContacts: InternalQueryRef;
|
|
154
|
+
listContacts: InternalQueryRef;
|
|
155
|
+
detectRecipientSpam: InternalQueryRef;
|
|
156
|
+
detectActorSpam: InternalQueryRef;
|
|
157
|
+
getEmailStats: InternalQueryRef;
|
|
158
|
+
detectRapidFirePatterns: InternalQueryRef;
|
|
159
|
+
checkRecipientRateLimit: InternalQueryRef;
|
|
160
|
+
checkActorRateLimit: InternalQueryRef;
|
|
161
|
+
checkGlobalRateLimit: InternalQueryRef;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export type InternalLibReferences = InternalActionLib & InternalQueryLib;
|
|
165
|
+
|
|
166
|
+
export const internalLib = (
|
|
167
|
+
internal as unknown as { lib: InternalLibReferences }
|
|
168
|
+
).lib;
|
package/src/client/types.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
Expand,
|
|
3
|
-
FunctionArgs,
|
|
4
|
-
FunctionReference,
|
|
5
|
-
FunctionReturnType,
|
|
6
|
-
StorageActionWriter,
|
|
7
|
-
StorageReader,
|
|
8
|
-
} from "convex/server";
|
|
9
|
-
import type { GenericId } from "convex/values";
|
|
10
|
-
|
|
11
|
-
export type RunQueryCtx = {
|
|
12
|
-
runQuery: <Query extends FunctionReference<"query", "internal">>(
|
|
13
|
-
query: Query,
|
|
14
|
-
args: FunctionArgs<Query>,
|
|
15
|
-
) => Promise<FunctionReturnType<Query>>;
|
|
16
|
-
};
|
|
17
|
-
export type RunMutationCtx = RunQueryCtx & {
|
|
18
|
-
runMutation: <Mutation extends FunctionReference<"mutation", "internal">>(
|
|
19
|
-
mutation: Mutation,
|
|
20
|
-
args: FunctionArgs<Mutation>,
|
|
21
|
-
) => Promise<FunctionReturnType<Mutation>>;
|
|
22
|
-
};
|
|
23
|
-
export type RunActionCtx = RunMutationCtx & {
|
|
24
|
-
runAction<Action extends FunctionReference<"action", "internal">>(
|
|
25
|
-
action: Action,
|
|
26
|
-
args: FunctionArgs<Action>,
|
|
27
|
-
): Promise<FunctionReturnType<Action>>;
|
|
28
|
-
};
|
|
29
|
-
export type ActionCtx = RunActionCtx & {
|
|
30
|
-
storage: StorageActionWriter;
|
|
31
|
-
};
|
|
32
|
-
export type QueryCtx = RunQueryCtx & {
|
|
33
|
-
storage: StorageReader;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export type OpaqueIds<T> = T extends GenericId<infer _T>
|
|
37
|
-
? string
|
|
38
|
-
: T extends (infer U)[]
|
|
39
|
-
? OpaqueIds<U>[]
|
|
40
|
-
: T extends ArrayBuffer
|
|
41
|
-
? ArrayBuffer
|
|
42
|
-
: T extends object
|
|
43
|
-
? {
|
|
44
|
-
[K in keyof T]: OpaqueIds<T[K]>;
|
|
45
|
-
}
|
|
46
|
-
: T;
|
|
47
|
-
|
|
48
|
-
export type UseApi<API> = Expand<{
|
|
49
|
-
[mod in keyof API]: API[mod] extends FunctionReference<
|
|
50
|
-
infer FType,
|
|
51
|
-
"public",
|
|
52
|
-
infer FArgs,
|
|
53
|
-
infer FReturnType,
|
|
54
|
-
infer FComponentPath
|
|
55
|
-
>
|
|
56
|
-
? FunctionReference<
|
|
57
|
-
FType,
|
|
58
|
-
"internal",
|
|
59
|
-
OpaqueIds<FArgs>,
|
|
60
|
-
OpaqueIds<FReturnType>,
|
|
61
|
-
FComponentPath
|
|
62
|
-
>
|
|
63
|
-
: UseApi<API[mod]>;
|
|
64
|
-
}>;
|