@devwithbobby/loops 0.1.11 → 0.1.13
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/README.md +1 -24
- package/dist/client/index.d.ts +122 -52
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +15 -26
- package/dist/component/convex.config.d.ts +1 -1
- package/dist/component/convex.config.d.ts.map +1 -1
- package/dist/component/convex.config.js +0 -1
- package/dist/component/lib.d.ts +237 -29
- package/dist/component/lib.d.ts.map +1 -1
- package/dist/component/lib.js +47 -133
- package/dist/component/schema.d.ts +66 -1
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/tables/contacts.d.ts +123 -1
- package/dist/component/tables/contacts.d.ts.map +1 -1
- package/dist/component/tables/emailOperations.d.ts +151 -1
- package/dist/component/tables/emailOperations.d.ts.map +1 -1
- package/dist/component/tables/emailOperations.js +1 -6
- package/dist/component/validators.d.ts +20 -3
- package/dist/component/validators.d.ts.map +1 -1
- package/dist/utils.d.ts +186 -3
- package/dist/utils.d.ts.map +1 -1
- package/package.json +101 -101
- package/src/client/index.ts +56 -57
- package/src/component/convex.config.ts +0 -1
- package/src/component/lib.ts +146 -219
- package/src/component/tables/contacts.ts +0 -1
- package/src/component/tables/emailOperations.ts +1 -7
- package/src/component/validators.ts +0 -1
package/README.md
CHANGED
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@devwithbobby/loops)
|
|
4
4
|
|
|
5
|
-
A Convex component for integrating with [Loops.so](https://loops.so) email marketing platform. Send transactional emails, manage contacts, trigger
|
|
5
|
+
A Convex component for integrating with [Loops.so](https://loops.so) email marketing platform. Send transactional emails, manage contacts, trigger loops, and monitor email operations with built-in spam detection and rate limiting.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- ✅ **Contact Management** - Create, update, find, and delete contacts
|
|
10
10
|
- ✅ **Transactional Emails** - Send one-off emails with templates
|
|
11
11
|
- ✅ **Events** - Trigger email workflows based on events
|
|
12
|
-
- ✅ **Campaigns** - Send campaigns to audiences or specific contacts
|
|
13
12
|
- ✅ **Loops** - Trigger automated email sequences
|
|
14
13
|
- ✅ **Monitoring** - Track all email operations with spam detection
|
|
15
14
|
- ✅ **Rate Limiting** - Built-in rate limiting queries for abuse prevention
|
|
@@ -201,26 +200,6 @@ await loops.sendEvent(ctx, {
|
|
|
201
200
|
});
|
|
202
201
|
```
|
|
203
202
|
|
|
204
|
-
#### Send Campaign
|
|
205
|
-
|
|
206
|
-
```typescript
|
|
207
|
-
// Send to specific emails
|
|
208
|
-
await loops.sendCampaign(ctx, {
|
|
209
|
-
campaignId: "campaign-id-from-loops",
|
|
210
|
-
emails: ["user1@example.com", "user2@example.com"],
|
|
211
|
-
dataVariables: { discount: "20%" },
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
// Send to audience
|
|
215
|
-
await loops.sendCampaign(ctx, {
|
|
216
|
-
campaignId: "campaign-id-from-loops",
|
|
217
|
-
audienceFilters: {
|
|
218
|
-
userGroup: "premium",
|
|
219
|
-
source: "webapp",
|
|
220
|
-
},
|
|
221
|
-
});
|
|
222
|
-
```
|
|
223
|
-
|
|
224
203
|
#### Trigger Loop (Automated Sequence)
|
|
225
204
|
|
|
226
205
|
```typescript
|
|
@@ -354,7 +333,6 @@ export const {
|
|
|
354
333
|
updateContact,
|
|
355
334
|
sendTransactional,
|
|
356
335
|
sendEvent,
|
|
357
|
-
sendCampaign,
|
|
358
336
|
triggerLoop,
|
|
359
337
|
countContacts,
|
|
360
338
|
// ... all other functions
|
|
@@ -488,7 +466,6 @@ This component implements the following Loops.so API endpoints:
|
|
|
488
466
|
- ✅ Count Contacts (custom implementation)
|
|
489
467
|
- ✅ Send Transactional Email
|
|
490
468
|
- ✅ Send Event
|
|
491
|
-
- ✅ Send Campaign
|
|
492
469
|
- ✅ Trigger Loop
|
|
493
470
|
|
|
494
471
|
## Contributing
|
package/dist/client/index.d.ts
CHANGED
|
@@ -32,41 +32,41 @@ export declare class Loops {
|
|
|
32
32
|
/**
|
|
33
33
|
* Add or update a contact in Loops
|
|
34
34
|
*/
|
|
35
|
-
addContact(ctx: RunActionCtx, contact: ContactData): Promise<
|
|
35
|
+
addContact(ctx: RunActionCtx, contact: ContactData): Promise<any>;
|
|
36
36
|
/**
|
|
37
37
|
* Update an existing contact in Loops
|
|
38
38
|
*/
|
|
39
39
|
updateContact(ctx: RunActionCtx, email: string, updates: Partial<ContactData> & {
|
|
40
40
|
dataVariables?: Record<string, any>;
|
|
41
|
-
}): Promise<
|
|
41
|
+
}): Promise<any>;
|
|
42
42
|
/**
|
|
43
43
|
* Send a transactional email using a transactional ID
|
|
44
44
|
*/
|
|
45
|
-
sendTransactional(ctx: RunActionCtx, options: TransactionalEmailOptions): Promise<
|
|
45
|
+
sendTransactional(ctx: RunActionCtx, options: TransactionalEmailOptions): Promise<any>;
|
|
46
46
|
/**
|
|
47
47
|
* Send an event to Loops to trigger email workflows
|
|
48
48
|
*/
|
|
49
|
-
sendEvent(ctx: RunActionCtx, options: EventOptions): Promise<
|
|
49
|
+
sendEvent(ctx: RunActionCtx, options: EventOptions): Promise<any>;
|
|
50
50
|
/**
|
|
51
51
|
* Find a contact by email
|
|
52
52
|
* Retrieves contact information from Loops
|
|
53
53
|
*/
|
|
54
|
-
findContact(ctx: RunActionCtx, email: string): Promise<
|
|
54
|
+
findContact(ctx: RunActionCtx, email: string): Promise<any>;
|
|
55
55
|
/**
|
|
56
56
|
* Batch create contacts
|
|
57
57
|
* Create multiple contacts in a single API call
|
|
58
58
|
*/
|
|
59
|
-
batchCreateContacts(ctx: RunActionCtx, contacts: ContactData[]): Promise<
|
|
59
|
+
batchCreateContacts(ctx: RunActionCtx, contacts: ContactData[]): Promise<any>;
|
|
60
60
|
/**
|
|
61
61
|
* Unsubscribe a contact
|
|
62
62
|
* Unsubscribes a contact from receiving emails (they remain in the system)
|
|
63
63
|
*/
|
|
64
|
-
unsubscribeContact(ctx: RunActionCtx, email: string): Promise<
|
|
64
|
+
unsubscribeContact(ctx: RunActionCtx, email: string): Promise<any>;
|
|
65
65
|
/**
|
|
66
66
|
* Resubscribe a contact
|
|
67
67
|
* Resubscribes a previously unsubscribed contact
|
|
68
68
|
*/
|
|
69
|
-
resubscribeContact(ctx: RunActionCtx, email: string): Promise<
|
|
69
|
+
resubscribeContact(ctx: RunActionCtx, email: string): Promise<any>;
|
|
70
70
|
/**
|
|
71
71
|
* Count contacts in the database
|
|
72
72
|
* Can filter by audience criteria (userGroup, source, subscribed status)
|
|
@@ -76,34 +76,46 @@ export declare class Loops {
|
|
|
76
76
|
userGroup?: string;
|
|
77
77
|
source?: string;
|
|
78
78
|
subscribed?: boolean;
|
|
79
|
-
}): Promise<
|
|
79
|
+
}): Promise<any>;
|
|
80
|
+
/**
|
|
81
|
+
* List contacts with pagination and optional filters
|
|
82
|
+
* Returns actual contact data, not just a count
|
|
83
|
+
* This queries the component's local database, not Loops API
|
|
84
|
+
*/
|
|
85
|
+
listContacts(ctx: RunQueryCtx, options?: {
|
|
86
|
+
userGroup?: string;
|
|
87
|
+
source?: string;
|
|
88
|
+
subscribed?: boolean;
|
|
89
|
+
limit?: number;
|
|
90
|
+
offset?: number;
|
|
91
|
+
}): Promise<any>;
|
|
80
92
|
/**
|
|
81
93
|
* Detect spam patterns: emails sent to the same recipient too frequently
|
|
82
94
|
*/
|
|
83
95
|
detectRecipientSpam(ctx: RunQueryCtx, options?: {
|
|
84
96
|
timeWindowMs?: number;
|
|
85
97
|
maxEmailsPerRecipient?: number;
|
|
86
|
-
}): Promise<
|
|
98
|
+
}): Promise<any>;
|
|
87
99
|
/**
|
|
88
100
|
* Detect spam patterns: emails sent by the same actor/user too frequently
|
|
89
101
|
*/
|
|
90
102
|
detectActorSpam(ctx: RunQueryCtx, options?: {
|
|
91
103
|
timeWindowMs?: number;
|
|
92
104
|
maxEmailsPerActor?: number;
|
|
93
|
-
}): Promise<
|
|
105
|
+
}): Promise<any>;
|
|
94
106
|
/**
|
|
95
107
|
* Get email operation statistics for monitoring
|
|
96
108
|
*/
|
|
97
109
|
getEmailStats(ctx: RunQueryCtx, options?: {
|
|
98
110
|
timeWindowMs?: number;
|
|
99
|
-
}): Promise<
|
|
111
|
+
}): Promise<any>;
|
|
100
112
|
/**
|
|
101
113
|
* Detect rapid-fire email sending patterns
|
|
102
114
|
*/
|
|
103
115
|
detectRapidFirePatterns(ctx: RunQueryCtx, options?: {
|
|
104
116
|
timeWindowMs?: number;
|
|
105
117
|
minEmailsInWindow?: number;
|
|
106
|
-
}): Promise<
|
|
118
|
+
}): Promise<any>;
|
|
107
119
|
/**
|
|
108
120
|
* Check if an email can be sent to a recipient based on rate limits
|
|
109
121
|
*/
|
|
@@ -111,7 +123,7 @@ export declare class Loops {
|
|
|
111
123
|
email: string;
|
|
112
124
|
timeWindowMs: number;
|
|
113
125
|
maxEmails: number;
|
|
114
|
-
}): Promise<
|
|
126
|
+
}): Promise<any>;
|
|
115
127
|
/**
|
|
116
128
|
* Check if an actor/user can send more emails based on rate limits
|
|
117
129
|
*/
|
|
@@ -119,32 +131,18 @@ export declare class Loops {
|
|
|
119
131
|
actorId: string;
|
|
120
132
|
timeWindowMs: number;
|
|
121
133
|
maxEmails: number;
|
|
122
|
-
}): Promise<
|
|
134
|
+
}): Promise<any>;
|
|
123
135
|
/**
|
|
124
136
|
* Check global email sending rate limit
|
|
125
137
|
*/
|
|
126
138
|
checkGlobalRateLimit(ctx: RunQueryCtx, options: {
|
|
127
139
|
timeWindowMs: number;
|
|
128
140
|
maxEmails: number;
|
|
129
|
-
}): Promise<
|
|
141
|
+
}): Promise<any>;
|
|
130
142
|
/**
|
|
131
143
|
* Delete a contact from Loops
|
|
132
144
|
*/
|
|
133
|
-
deleteContact(ctx: RunActionCtx, email: string): Promise<
|
|
134
|
-
/**
|
|
135
|
-
* Send a campaign to contacts
|
|
136
|
-
* Campaigns are one-time email sends to a segment or list of contacts
|
|
137
|
-
*/
|
|
138
|
-
sendCampaign(ctx: RunActionCtx, options: {
|
|
139
|
-
campaignId: string;
|
|
140
|
-
emails?: string[];
|
|
141
|
-
transactionalId?: string;
|
|
142
|
-
dataVariables?: Record<string, any>;
|
|
143
|
-
audienceFilters?: {
|
|
144
|
-
userGroup?: string;
|
|
145
|
-
source?: string;
|
|
146
|
-
};
|
|
147
|
-
}): Promise<FunctionReturnType<Action>>;
|
|
145
|
+
deleteContact(ctx: RunActionCtx, email: string): Promise<any>;
|
|
148
146
|
/**
|
|
149
147
|
* Trigger a loop for a contact
|
|
150
148
|
* Loops are automated email sequences that can be triggered by events
|
|
@@ -160,34 +158,106 @@ export declare class Loops {
|
|
|
160
158
|
email: string;
|
|
161
159
|
dataVariables?: Record<string, any>;
|
|
162
160
|
eventName?: string;
|
|
163
|
-
}): Promise<
|
|
161
|
+
}): Promise<any>;
|
|
164
162
|
/**
|
|
165
163
|
* For easy re-exporting.
|
|
166
164
|
* Apps can do
|
|
167
165
|
* ```ts
|
|
168
|
-
* export const { addContact, sendTransactional, sendEvent,
|
|
166
|
+
* export const { addContact, sendTransactional, sendEvent, triggerLoop } = loops.api();
|
|
169
167
|
* ```
|
|
170
168
|
*/
|
|
171
169
|
api(): {
|
|
172
|
-
addContact:
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
170
|
+
addContact: import("convex/server").RegisteredAction<"public", {
|
|
171
|
+
firstName?: string | undefined;
|
|
172
|
+
lastName?: string | undefined;
|
|
173
|
+
userId?: string | undefined;
|
|
174
|
+
source?: string | undefined;
|
|
175
|
+
subscribed?: boolean | undefined;
|
|
176
|
+
userGroup?: string | undefined;
|
|
177
|
+
email: string;
|
|
178
|
+
}, Promise<any>>;
|
|
179
|
+
updateContact: import("convex/server").RegisteredAction<"public", {
|
|
180
|
+
firstName?: string | undefined;
|
|
181
|
+
lastName?: string | undefined;
|
|
182
|
+
userId?: string | undefined;
|
|
183
|
+
source?: string | undefined;
|
|
184
|
+
subscribed?: boolean | undefined;
|
|
185
|
+
userGroup?: string | undefined;
|
|
186
|
+
dataVariables?: any;
|
|
187
|
+
email: string;
|
|
188
|
+
}, Promise<any>>;
|
|
189
|
+
sendTransactional: import("convex/server").RegisteredAction<"public", {
|
|
190
|
+
dataVariables?: any;
|
|
191
|
+
email: string;
|
|
192
|
+
transactionalId: string;
|
|
193
|
+
}, Promise<any>>;
|
|
194
|
+
sendEvent: import("convex/server").RegisteredAction<"public", {
|
|
195
|
+
eventProperties?: any;
|
|
196
|
+
email: string;
|
|
197
|
+
eventName: string;
|
|
198
|
+
}, Promise<any>>;
|
|
199
|
+
deleteContact: import("convex/server").RegisteredAction<"public", {
|
|
200
|
+
email: string;
|
|
201
|
+
}, Promise<any>>;
|
|
202
|
+
triggerLoop: import("convex/server").RegisteredAction<"public", {
|
|
203
|
+
dataVariables?: any;
|
|
204
|
+
email: string;
|
|
205
|
+
loopId: string;
|
|
206
|
+
}, Promise<any>>;
|
|
207
|
+
findContact: import("convex/server").RegisteredAction<"public", {
|
|
208
|
+
email: string;
|
|
209
|
+
}, Promise<any>>;
|
|
210
|
+
batchCreateContacts: import("convex/server").RegisteredAction<"public", {
|
|
211
|
+
contacts: {
|
|
212
|
+
firstName?: string | undefined;
|
|
213
|
+
lastName?: string | undefined;
|
|
214
|
+
userId?: string | undefined;
|
|
215
|
+
source?: string | undefined;
|
|
216
|
+
subscribed?: boolean | undefined;
|
|
217
|
+
userGroup?: string | undefined;
|
|
218
|
+
email: string;
|
|
219
|
+
}[];
|
|
220
|
+
}, Promise<any>>;
|
|
221
|
+
unsubscribeContact: import("convex/server").RegisteredAction<"public", {
|
|
222
|
+
email: string;
|
|
223
|
+
}, Promise<any>>;
|
|
224
|
+
resubscribeContact: import("convex/server").RegisteredAction<"public", {
|
|
225
|
+
email: string;
|
|
226
|
+
}, Promise<any>>;
|
|
227
|
+
countContacts: import("convex/server").RegisteredQuery<"public", {
|
|
228
|
+
source?: string | undefined;
|
|
229
|
+
subscribed?: boolean | undefined;
|
|
230
|
+
userGroup?: string | undefined;
|
|
231
|
+
}, Promise<any>>;
|
|
232
|
+
detectRecipientSpam: import("convex/server").RegisteredQuery<"public", {
|
|
233
|
+
timeWindowMs?: number | undefined;
|
|
234
|
+
maxEmailsPerRecipient?: number | undefined;
|
|
235
|
+
}, Promise<any>>;
|
|
236
|
+
detectActorSpam: import("convex/server").RegisteredQuery<"public", {
|
|
237
|
+
timeWindowMs?: number | undefined;
|
|
238
|
+
maxEmailsPerActor?: number | undefined;
|
|
239
|
+
}, Promise<any>>;
|
|
240
|
+
getEmailStats: import("convex/server").RegisteredQuery<"public", {
|
|
241
|
+
timeWindowMs?: number | undefined;
|
|
242
|
+
}, Promise<any>>;
|
|
243
|
+
detectRapidFirePatterns: import("convex/server").RegisteredQuery<"public", {
|
|
244
|
+
timeWindowMs?: number | undefined;
|
|
245
|
+
minEmailsInWindow?: number | undefined;
|
|
246
|
+
}, Promise<any>>;
|
|
247
|
+
checkRecipientRateLimit: import("convex/server").RegisteredQuery<"public", {
|
|
248
|
+
email: string;
|
|
249
|
+
timeWindowMs: number;
|
|
250
|
+
maxEmails: number;
|
|
251
|
+
}, Promise<any>>;
|
|
252
|
+
checkActorRateLimit: import("convex/server").RegisteredQuery<"public", {
|
|
253
|
+
actorId: string;
|
|
254
|
+
timeWindowMs: number;
|
|
255
|
+
maxEmails: number;
|
|
256
|
+
}, Promise<any>>;
|
|
257
|
+
checkGlobalRateLimit: import("convex/server").RegisteredQuery<"public", {
|
|
258
|
+
timeWindowMs: number;
|
|
259
|
+
maxEmails: number;
|
|
260
|
+
}, Promise<any>>;
|
|
191
261
|
};
|
|
192
262
|
}
|
|
193
263
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpE,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;AAE5C,MAAM,WAAW,WAAW;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACzC,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACtC;AAED,qBAAa,KAAK;IACjB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAC3C,SAAgB,OAAO,CAAC,EAAE;QACzB,MAAM,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;gBAGD,SAAS,EAAE,cAAc,EACzB,OAAO,CAAC,EAAE;QACT,MAAM,CAAC,EAAE,MAAM,CAAC;KAChB;IAwCF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;;OAEG;IACG,UAAU,CAAC,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW;IAsBxD;;OAEG;IACG,aAAa,CAClB,GAAG,EAAE,YAAY,EACjB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG;QAC/B,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KACpC;IASF;;OAEG;IACG,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
|
package/dist/client/index.js
CHANGED
|
@@ -125,6 +125,20 @@ export class Loops {
|
|
|
125
125
|
async countContacts(ctx, options) {
|
|
126
126
|
return ctx.runQuery(this.component.lib.countContacts, options ?? {});
|
|
127
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* List contacts with pagination and optional filters
|
|
130
|
+
* Returns actual contact data, not just a count
|
|
131
|
+
* This queries the component's local database, not Loops API
|
|
132
|
+
*/
|
|
133
|
+
async listContacts(ctx, options) {
|
|
134
|
+
return ctx.runQuery(this.component.lib.listContacts, {
|
|
135
|
+
userGroup: options?.userGroup,
|
|
136
|
+
source: options?.source,
|
|
137
|
+
subscribed: options?.subscribed,
|
|
138
|
+
limit: options?.limit ?? 100,
|
|
139
|
+
offset: options?.offset ?? 0,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
128
142
|
/**
|
|
129
143
|
* Detect spam patterns: emails sent to the same recipient too frequently
|
|
130
144
|
*/
|
|
@@ -187,16 +201,6 @@ export class Loops {
|
|
|
187
201
|
email,
|
|
188
202
|
});
|
|
189
203
|
}
|
|
190
|
-
/**
|
|
191
|
-
* Send a campaign to contacts
|
|
192
|
-
* Campaigns are one-time email sends to a segment or list of contacts
|
|
193
|
-
*/
|
|
194
|
-
async sendCampaign(ctx, options) {
|
|
195
|
-
return ctx.runAction(this.component.lib.sendCampaign, {
|
|
196
|
-
apiKey: this.apiKey,
|
|
197
|
-
...options,
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
204
|
/**
|
|
201
205
|
* Trigger a loop for a contact
|
|
202
206
|
* Loops are automated email sequences that can be triggered by events
|
|
@@ -217,7 +221,7 @@ export class Loops {
|
|
|
217
221
|
* For easy re-exporting.
|
|
218
222
|
* Apps can do
|
|
219
223
|
* ```ts
|
|
220
|
-
* export const { addContact, sendTransactional, sendEvent,
|
|
224
|
+
* export const { addContact, sendTransactional, sendEvent, triggerLoop } = loops.api();
|
|
221
225
|
* ```
|
|
222
226
|
*/
|
|
223
227
|
api() {
|
|
@@ -280,21 +284,6 @@ export class Loops {
|
|
|
280
284
|
return await this.deleteContact(ctx, args.email);
|
|
281
285
|
},
|
|
282
286
|
}),
|
|
283
|
-
sendCampaign: actionGeneric({
|
|
284
|
-
args: {
|
|
285
|
-
campaignId: v.string(),
|
|
286
|
-
emails: v.optional(v.array(v.string())),
|
|
287
|
-
transactionalId: v.optional(v.string()),
|
|
288
|
-
dataVariables: v.optional(v.any()),
|
|
289
|
-
audienceFilters: v.optional(v.object({
|
|
290
|
-
userGroup: v.optional(v.string()),
|
|
291
|
-
source: v.optional(v.string()),
|
|
292
|
-
})),
|
|
293
|
-
},
|
|
294
|
-
handler: async (ctx, args) => {
|
|
295
|
-
return await this.sendCampaign(ctx, args);
|
|
296
|
-
},
|
|
297
|
-
}),
|
|
298
287
|
triggerLoop: actionGeneric({
|
|
299
288
|
args: {
|
|
300
289
|
loopId: v.string(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convex.config.d.ts","sourceRoot":"","sources":["../../src/component/convex.config.ts"],"names":[],"mappings":"AAGA,QAAA,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"convex.config.d.ts","sourceRoot":"","sources":["../../src/component/convex.config.ts"],"names":[],"mappings":"AAGA,QAAA,MAAM,SAAS,kDAA2B,CAAC;AAuB3C,eAAe,SAAS,CAAC"}
|
|
@@ -12,7 +12,6 @@ component.export(api, {
|
|
|
12
12
|
listContacts: api.lib.listContacts,
|
|
13
13
|
sendTransactional: api.lib.sendTransactional,
|
|
14
14
|
sendEvent: api.lib.sendEvent,
|
|
15
|
-
sendCampaign: api.lib.sendCampaign,
|
|
16
15
|
triggerLoop: api.lib.triggerLoop,
|
|
17
16
|
deleteContact: api.lib.deleteContact,
|
|
18
17
|
detectRecipientSpam: api.lib.detectRecipientSpam,
|