@stack0/sdk 0.4.0 → 0.5.2

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/index.mjs CHANGED
@@ -75,14 +75,644 @@ var HttpClient = class {
75
75
  }
76
76
  };
77
77
 
78
+ // src/mail/audiences.ts
79
+ var Audiences = class {
80
+ constructor(http) {
81
+ this.http = http;
82
+ }
83
+ /**
84
+ * List all audiences
85
+ */
86
+ async list(request = {}) {
87
+ const params = new URLSearchParams();
88
+ if (request.environment) params.set("environment", request.environment);
89
+ if (request.limit) params.set("limit", request.limit.toString());
90
+ if (request.offset) params.set("offset", request.offset.toString());
91
+ if (request.search) params.set("search", request.search);
92
+ const query = params.toString();
93
+ return this.http.get(`/mail/audiences${query ? `?${query}` : ""}`);
94
+ }
95
+ /**
96
+ * Get an audience by ID
97
+ */
98
+ async get(id) {
99
+ return this.http.get(`/mail/audiences/${id}`);
100
+ }
101
+ /**
102
+ * Create a new audience
103
+ */
104
+ async create(request) {
105
+ return this.http.post("/mail/audiences", request);
106
+ }
107
+ /**
108
+ * Update an audience
109
+ */
110
+ async update(request) {
111
+ const { id, ...data } = request;
112
+ return this.http.put(`/mail/audiences/${id}`, data);
113
+ }
114
+ /**
115
+ * Delete an audience
116
+ */
117
+ async delete(id) {
118
+ return this.http.delete(`/mail/audiences/${id}`);
119
+ }
120
+ /**
121
+ * List contacts in an audience
122
+ */
123
+ async listContacts(request) {
124
+ const { id, ...params } = request;
125
+ const searchParams = new URLSearchParams();
126
+ if (params.environment) searchParams.set("environment", params.environment);
127
+ if (params.limit) searchParams.set("limit", params.limit.toString());
128
+ if (params.offset) searchParams.set("offset", params.offset.toString());
129
+ if (params.search) searchParams.set("search", params.search);
130
+ if (params.status) searchParams.set("status", params.status);
131
+ const query = searchParams.toString();
132
+ return this.http.get(`/mail/audiences/${id}/contacts${query ? `?${query}` : ""}`);
133
+ }
134
+ /**
135
+ * Add contacts to an audience
136
+ */
137
+ async addContacts(request) {
138
+ const { id, contactIds } = request;
139
+ return this.http.post(`/mail/audiences/${id}/contacts`, { contactIds });
140
+ }
141
+ /**
142
+ * Remove contacts from an audience
143
+ */
144
+ async removeContacts(request) {
145
+ const { id, contactIds } = request;
146
+ return this.http.deleteWithBody(`/mail/audiences/${id}/contacts`, {
147
+ contactIds
148
+ });
149
+ }
150
+ };
151
+
152
+ // src/mail/campaigns.ts
153
+ var Campaigns = class {
154
+ constructor(http) {
155
+ this.http = http;
156
+ }
157
+ /**
158
+ * List all campaigns
159
+ */
160
+ async list(request = {}) {
161
+ const params = new URLSearchParams();
162
+ if (request.environment) params.set("environment", request.environment);
163
+ if (request.limit) params.set("limit", request.limit.toString());
164
+ if (request.offset) params.set("offset", request.offset.toString());
165
+ if (request.search) params.set("search", request.search);
166
+ if (request.status) params.set("status", request.status);
167
+ const query = params.toString();
168
+ return this.http.get(`/mail/campaigns${query ? `?${query}` : ""}`);
169
+ }
170
+ /**
171
+ * Get a campaign by ID
172
+ */
173
+ async get(id) {
174
+ return this.http.get(`/mail/campaigns/${id}`);
175
+ }
176
+ /**
177
+ * Create a new campaign
178
+ */
179
+ async create(request) {
180
+ return this.http.post("/mail/campaigns", request);
181
+ }
182
+ /**
183
+ * Update a campaign
184
+ */
185
+ async update(request) {
186
+ const { id, ...data } = request;
187
+ return this.http.put(`/mail/campaigns/${id}`, data);
188
+ }
189
+ /**
190
+ * Delete a campaign
191
+ */
192
+ async delete(id) {
193
+ return this.http.delete(`/mail/campaigns/${id}`);
194
+ }
195
+ /**
196
+ * Send a campaign
197
+ */
198
+ async send(request) {
199
+ const { id, ...data } = request;
200
+ return this.http.post(`/mail/campaigns/${id}/send`, data);
201
+ }
202
+ /**
203
+ * Pause a sending campaign
204
+ */
205
+ async pause(id) {
206
+ return this.http.post(`/mail/campaigns/${id}/pause`, {});
207
+ }
208
+ /**
209
+ * Cancel a campaign
210
+ */
211
+ async cancel(id) {
212
+ return this.http.post(`/mail/campaigns/${id}/cancel`, {});
213
+ }
214
+ /**
215
+ * Duplicate a campaign
216
+ */
217
+ async duplicate(id) {
218
+ return this.http.post(`/mail/campaigns/${id}/duplicate`, {});
219
+ }
220
+ /**
221
+ * Get campaign statistics
222
+ */
223
+ async getStats(id) {
224
+ return this.http.get(`/mail/campaigns/${id}/stats`);
225
+ }
226
+ };
227
+
228
+ // src/mail/contacts.ts
229
+ var Contacts = class {
230
+ constructor(http) {
231
+ this.http = http;
232
+ }
233
+ /**
234
+ * List all contacts
235
+ */
236
+ async list(request = {}) {
237
+ const params = new URLSearchParams();
238
+ if (request.environment) params.set("environment", request.environment);
239
+ if (request.limit) params.set("limit", request.limit.toString());
240
+ if (request.offset) params.set("offset", request.offset.toString());
241
+ if (request.search) params.set("search", request.search);
242
+ if (request.status) params.set("status", request.status);
243
+ const query = params.toString();
244
+ return this.http.get(`/mail/contacts${query ? `?${query}` : ""}`);
245
+ }
246
+ /**
247
+ * Get a contact by ID
248
+ */
249
+ async get(id) {
250
+ return this.http.get(`/mail/contacts/${id}`);
251
+ }
252
+ /**
253
+ * Create a new contact
254
+ */
255
+ async create(request) {
256
+ return this.http.post("/mail/contacts", request);
257
+ }
258
+ /**
259
+ * Update a contact
260
+ */
261
+ async update(request) {
262
+ const { id, ...data } = request;
263
+ return this.http.put(`/mail/contacts/${id}`, data);
264
+ }
265
+ /**
266
+ * Delete a contact
267
+ */
268
+ async delete(id) {
269
+ return this.http.delete(`/mail/contacts/${id}`);
270
+ }
271
+ /**
272
+ * Import contacts in bulk
273
+ */
274
+ async import(request) {
275
+ return this.http.post("/mail/contacts/import", request);
276
+ }
277
+ };
278
+
279
+ // src/mail/domains.ts
280
+ var Domains = class {
281
+ constructor(http) {
282
+ this.http = http;
283
+ }
284
+ /**
285
+ * List all domains for the organization
286
+ */
287
+ async list(request) {
288
+ const params = new URLSearchParams();
289
+ params.set("projectSlug", request.projectSlug);
290
+ if (request.environment) params.set("environment", request.environment);
291
+ return this.http.get(`/mail/domains?${params.toString()}`);
292
+ }
293
+ /**
294
+ * Add a new domain
295
+ */
296
+ async add(request) {
297
+ return this.http.post("/mail/domains", request);
298
+ }
299
+ /**
300
+ * Get DNS records for a domain
301
+ */
302
+ async getDnsRecords(domainId) {
303
+ return this.http.get(`/mail/domains/${domainId}/dns`);
304
+ }
305
+ /**
306
+ * Verify a domain
307
+ */
308
+ async verify(domainId) {
309
+ return this.http.post(`/mail/domains/${domainId}/verify`, {});
310
+ }
311
+ /**
312
+ * Delete a domain
313
+ */
314
+ async delete(domainId) {
315
+ return this.http.delete(`/mail/domains/${domainId}`);
316
+ }
317
+ /**
318
+ * Set a domain as the default
319
+ */
320
+ async setDefault(domainId) {
321
+ return this.http.post(`/mail/domains/${domainId}/default`, {});
322
+ }
323
+ };
324
+
325
+ // src/mail/events.ts
326
+ var Events = class {
327
+ constructor(http) {
328
+ this.http = http;
329
+ }
330
+ // ============================================================================
331
+ // EVENT DEFINITIONS
332
+ // ============================================================================
333
+ /**
334
+ * List all event definitions
335
+ */
336
+ async list(request = {}) {
337
+ const params = new URLSearchParams();
338
+ if (request.projectSlug) params.set("projectSlug", request.projectSlug);
339
+ if (request.environment) params.set("environment", request.environment);
340
+ if (request.limit) params.set("limit", request.limit.toString());
341
+ if (request.offset) params.set("offset", request.offset.toString());
342
+ if (request.search) params.set("search", request.search);
343
+ const query = params.toString();
344
+ return this.http.get(`/mail/events${query ? `?${query}` : ""}`);
345
+ }
346
+ /**
347
+ * Get an event definition by ID
348
+ */
349
+ async get(id) {
350
+ return this.http.get(`/mail/events/${id}`);
351
+ }
352
+ /**
353
+ * Create a new event definition
354
+ */
355
+ async create(request) {
356
+ return this.http.post("/mail/events", request);
357
+ }
358
+ /**
359
+ * Update an event definition
360
+ */
361
+ async update(request) {
362
+ const { id, ...data } = request;
363
+ return this.http.put(`/mail/events/${id}`, data);
364
+ }
365
+ /**
366
+ * Delete an event definition
367
+ */
368
+ async delete(id) {
369
+ return this.http.delete(`/mail/events/${id}`);
370
+ }
371
+ // ============================================================================
372
+ // EVENT TRACKING
373
+ // ============================================================================
374
+ /**
375
+ * Track a single event
376
+ * This can trigger email sequences configured to listen for this event
377
+ */
378
+ async track(request) {
379
+ return this.http.post("/mail/events/track", request);
380
+ }
381
+ /**
382
+ * Track multiple events in a batch (max 100)
383
+ */
384
+ async trackBatch(request) {
385
+ return this.http.post("/mail/events/track/batch", request);
386
+ }
387
+ // ============================================================================
388
+ // EVENT OCCURRENCES
389
+ // ============================================================================
390
+ /**
391
+ * List event occurrences
392
+ */
393
+ async listOccurrences(request = {}) {
394
+ const params = new URLSearchParams();
395
+ if (request.eventId) params.set("eventId", request.eventId);
396
+ if (request.contactId) params.set("contactId", request.contactId);
397
+ if (request.limit) params.set("limit", request.limit.toString());
398
+ if (request.offset) params.set("offset", request.offset.toString());
399
+ if (request.startDate) {
400
+ params.set("startDate", request.startDate instanceof Date ? request.startDate.toISOString() : request.startDate);
401
+ }
402
+ if (request.endDate) {
403
+ params.set("endDate", request.endDate instanceof Date ? request.endDate.toISOString() : request.endDate);
404
+ }
405
+ const query = params.toString();
406
+ return this.http.get(`/mail/events/occurrences${query ? `?${query}` : ""}`);
407
+ }
408
+ // ============================================================================
409
+ // ANALYTICS
410
+ // ============================================================================
411
+ /**
412
+ * Get analytics for an event
413
+ */
414
+ async getAnalytics(id) {
415
+ return this.http.get(`/mail/events/analytics/${id}`);
416
+ }
417
+ };
418
+
419
+ // src/mail/sequences.ts
420
+ var Sequences = class {
421
+ constructor(http) {
422
+ this.http = http;
423
+ }
424
+ // ============================================================================
425
+ // SEQUENCE CRUD
426
+ // ============================================================================
427
+ /**
428
+ * List all sequences
429
+ */
430
+ async list(request = {}) {
431
+ const params = new URLSearchParams();
432
+ if (request.environment) params.set("environment", request.environment);
433
+ if (request.limit) params.set("limit", request.limit.toString());
434
+ if (request.offset) params.set("offset", request.offset.toString());
435
+ if (request.search) params.set("search", request.search);
436
+ if (request.status) params.set("status", request.status);
437
+ if (request.triggerType) params.set("triggerType", request.triggerType);
438
+ const query = params.toString();
439
+ return this.http.get(`/mail/sequences${query ? `?${query}` : ""}`);
440
+ }
441
+ /**
442
+ * Get a sequence by ID with all nodes and connections
443
+ */
444
+ async get(id) {
445
+ return this.http.get(`/mail/sequences/${id}`);
446
+ }
447
+ /**
448
+ * Create a new sequence
449
+ */
450
+ async create(request) {
451
+ return this.http.post("/mail/sequences", request);
452
+ }
453
+ /**
454
+ * Update a sequence
455
+ */
456
+ async update(request) {
457
+ const { id, ...data } = request;
458
+ return this.http.put(`/mail/sequences/${id}`, data);
459
+ }
460
+ /**
461
+ * Delete a sequence
462
+ */
463
+ async delete(id) {
464
+ return this.http.delete(`/mail/sequences/${id}`);
465
+ }
466
+ // ============================================================================
467
+ // SEQUENCE LIFECYCLE
468
+ // ============================================================================
469
+ /**
470
+ * Publish (activate) a sequence
471
+ */
472
+ async publish(id) {
473
+ return this.http.post(`/mail/sequences/${id}/publish`, {});
474
+ }
475
+ /**
476
+ * Pause an active sequence
477
+ */
478
+ async pause(id) {
479
+ return this.http.post(`/mail/sequences/${id}/pause`, {});
480
+ }
481
+ /**
482
+ * Resume a paused sequence
483
+ */
484
+ async resume(id) {
485
+ return this.http.post(`/mail/sequences/${id}/resume`, {});
486
+ }
487
+ /**
488
+ * Archive a sequence
489
+ */
490
+ async archive(id) {
491
+ return this.http.post(`/mail/sequences/${id}/archive`, {});
492
+ }
493
+ /**
494
+ * Duplicate a sequence
495
+ */
496
+ async duplicate(id, name) {
497
+ return this.http.post(`/mail/sequences/${id}/duplicate`, { name });
498
+ }
499
+ // ============================================================================
500
+ // NODE MANAGEMENT
501
+ // ============================================================================
502
+ /**
503
+ * Create a new node in a sequence
504
+ */
505
+ async createNode(request) {
506
+ const { id, ...data } = request;
507
+ return this.http.post(`/mail/sequences/${id}/nodes`, data);
508
+ }
509
+ /**
510
+ * Update a node
511
+ */
512
+ async updateNode(request) {
513
+ const { id, nodeId, ...data } = request;
514
+ return this.http.put(`/mail/sequences/${id}/nodes/${nodeId}`, data);
515
+ }
516
+ /**
517
+ * Update node position (for visual editor)
518
+ */
519
+ async updateNodePosition(request) {
520
+ const { id, nodeId, positionX, positionY } = request;
521
+ return this.http.put(`/mail/sequences/${id}/nodes/${nodeId}/position`, { positionX, positionY });
522
+ }
523
+ /**
524
+ * Delete a node
525
+ */
526
+ async deleteNode(sequenceId, nodeId) {
527
+ return this.http.delete(`/mail/sequences/${sequenceId}/nodes/${nodeId}`);
528
+ }
529
+ // ============================================================================
530
+ // NODE CONFIGURATIONS
531
+ // ============================================================================
532
+ /**
533
+ * Set email node content
534
+ */
535
+ async setNodeEmail(sequenceId, request) {
536
+ const { nodeId, ...data } = request;
537
+ return this.http.put(`/mail/sequences/${sequenceId}/nodes/${nodeId}/email`, data);
538
+ }
539
+ /**
540
+ * Set timer node configuration
541
+ */
542
+ async setNodeTimer(sequenceId, request) {
543
+ const { nodeId, ...data } = request;
544
+ return this.http.put(`/mail/sequences/${sequenceId}/nodes/${nodeId}/timer`, data);
545
+ }
546
+ /**
547
+ * Set filter node configuration
548
+ */
549
+ async setNodeFilter(sequenceId, request) {
550
+ const { nodeId, ...data } = request;
551
+ return this.http.put(`/mail/sequences/${sequenceId}/nodes/${nodeId}/filter`, data);
552
+ }
553
+ /**
554
+ * Set branch node configuration
555
+ */
556
+ async setNodeBranch(sequenceId, request) {
557
+ const { nodeId, ...data } = request;
558
+ return this.http.put(`/mail/sequences/${sequenceId}/nodes/${nodeId}/branch`, data);
559
+ }
560
+ /**
561
+ * Set experiment node configuration
562
+ */
563
+ async setNodeExperiment(sequenceId, request) {
564
+ const { nodeId, ...data } = request;
565
+ return this.http.put(`/mail/sequences/${sequenceId}/nodes/${nodeId}/experiment`, data);
566
+ }
567
+ // ============================================================================
568
+ // CONNECTIONS
569
+ // ============================================================================
570
+ /**
571
+ * Create a connection between nodes
572
+ */
573
+ async createConnection(request) {
574
+ const { id, ...data } = request;
575
+ return this.http.post(`/mail/sequences/${id}/connections`, data);
576
+ }
577
+ /**
578
+ * Delete a connection
579
+ */
580
+ async deleteConnection(sequenceId, connectionId) {
581
+ return this.http.delete(`/mail/sequences/${sequenceId}/connections/${connectionId}`);
582
+ }
583
+ // ============================================================================
584
+ // SEQUENCE ENTRIES (CONTACTS IN SEQUENCE)
585
+ // ============================================================================
586
+ /**
587
+ * List contacts in a sequence
588
+ */
589
+ async listEntries(request) {
590
+ const { id, ...params } = request;
591
+ const searchParams = new URLSearchParams();
592
+ if (params.limit) searchParams.set("limit", params.limit.toString());
593
+ if (params.offset) searchParams.set("offset", params.offset.toString());
594
+ if (params.status) searchParams.set("status", params.status);
595
+ const query = searchParams.toString();
596
+ return this.http.get(`/mail/sequences/${id}/entries${query ? `?${query}` : ""}`);
597
+ }
598
+ /**
599
+ * Add a contact to a sequence
600
+ */
601
+ async addContact(request) {
602
+ const { id, contactId } = request;
603
+ return this.http.post(`/mail/sequences/${id}/add-contact`, { contactId });
604
+ }
605
+ /**
606
+ * Remove a contact from a sequence
607
+ */
608
+ async removeContact(request) {
609
+ const { id, entryId, reason } = request;
610
+ return this.http.post(`/mail/sequences/${id}/remove-contact`, {
611
+ entryId,
612
+ reason
613
+ });
614
+ }
615
+ // ============================================================================
616
+ // ANALYTICS
617
+ // ============================================================================
618
+ /**
619
+ * Get sequence analytics
620
+ */
621
+ async getAnalytics(id) {
622
+ return this.http.get(`/mail/sequences/${id}/analytics`);
623
+ }
624
+ };
625
+
626
+ // src/mail/templates.ts
627
+ var Templates = class {
628
+ constructor(http) {
629
+ this.http = http;
630
+ }
631
+ /**
632
+ * List all templates
633
+ */
634
+ async list(request = {}) {
635
+ const params = new URLSearchParams();
636
+ if (request.environment) params.set("environment", request.environment);
637
+ if (request.limit) params.set("limit", request.limit.toString());
638
+ if (request.offset) params.set("offset", request.offset.toString());
639
+ if (request.isActive !== void 0) params.set("isActive", request.isActive.toString());
640
+ if (request.search) params.set("search", request.search);
641
+ const query = params.toString();
642
+ return this.http.get(`/mail/templates${query ? `?${query}` : ""}`);
643
+ }
644
+ /**
645
+ * Get a template by ID
646
+ */
647
+ async get(id) {
648
+ return this.http.get(`/mail/templates/${id}`);
649
+ }
650
+ /**
651
+ * Get a template by slug
652
+ */
653
+ async getBySlug(slug) {
654
+ return this.http.get(`/mail/templates/slug/${slug}`);
655
+ }
656
+ /**
657
+ * Create a new template
658
+ */
659
+ async create(request) {
660
+ return this.http.post("/mail/templates", request);
661
+ }
662
+ /**
663
+ * Update a template
664
+ */
665
+ async update(request) {
666
+ const { id, ...data } = request;
667
+ return this.http.put(`/mail/templates/${id}`, data);
668
+ }
669
+ /**
670
+ * Delete a template
671
+ */
672
+ async delete(id) {
673
+ return this.http.delete(`/mail/templates/${id}`);
674
+ }
675
+ /**
676
+ * Preview a template with variables
677
+ */
678
+ async preview(request) {
679
+ const { id, variables } = request;
680
+ return this.http.post(`/mail/templates/${id}/preview`, { variables });
681
+ }
682
+ };
683
+
78
684
  // src/mail/client.ts
79
685
  var Mail = class {
80
686
  http;
687
+ /** Manage sending domains */
688
+ domains;
689
+ /** Manage email templates */
690
+ templates;
691
+ /** Manage contact audiences/lists */
692
+ audiences;
693
+ /** Manage contacts */
694
+ contacts;
695
+ /** Manage email campaigns */
696
+ campaigns;
697
+ /** Manage automated email sequences */
698
+ sequences;
699
+ /** Track and manage custom events */
700
+ events;
81
701
  constructor(config) {
82
702
  this.http = new HttpClient(config);
703
+ this.domains = new Domains(this.http);
704
+ this.templates = new Templates(this.http);
705
+ this.audiences = new Audiences(this.http);
706
+ this.contacts = new Contacts(this.http);
707
+ this.campaigns = new Campaigns(this.http);
708
+ this.sequences = new Sequences(this.http);
709
+ this.events = new Events(this.http);
83
710
  }
711
+ // ============================================================================
712
+ // TRANSACTIONAL EMAILS
713
+ // ============================================================================
84
714
  /**
85
- * Send an email
715
+ * Send a single email
86
716
  *
87
717
  * @example
88
718
  * ```typescript
@@ -95,11 +725,40 @@ var Mail = class {
95
725
  * ```
96
726
  */
97
727
  async send(request) {
98
- const response = await this.http.post("/mail/send", request);
99
- if (typeof response.createdAt === "string") {
100
- response.createdAt = new Date(response.createdAt);
101
- }
102
- return response;
728
+ return this.http.post("/mail/send", request);
729
+ }
730
+ /**
731
+ * Send multiple emails in a batch (up to 100)
732
+ * Each email can have different content and recipients
733
+ *
734
+ * @example
735
+ * ```typescript
736
+ * const result = await mail.sendBatch({
737
+ * emails: [
738
+ * { from: 'noreply@example.com', to: 'user1@example.com', subject: 'Hello', html: '<p>Hi User 1</p>' },
739
+ * { from: 'noreply@example.com', to: 'user2@example.com', subject: 'Hello', html: '<p>Hi User 2</p>' },
740
+ * ]
741
+ * });
742
+ * ```
743
+ */
744
+ async sendBatch(request) {
745
+ return this.http.post("/mail/send/batch", request);
746
+ }
747
+ /**
748
+ * Send a broadcast email (same content to multiple recipients, up to 1000)
749
+ *
750
+ * @example
751
+ * ```typescript
752
+ * const result = await mail.sendBroadcast({
753
+ * from: 'noreply@example.com',
754
+ * to: ['user1@example.com', 'user2@example.com', 'user3@example.com'],
755
+ * subject: 'Newsletter',
756
+ * html: '<p>Our latest updates...</p>',
757
+ * });
758
+ * ```
759
+ */
760
+ async sendBroadcast(request) {
761
+ return this.http.post("/mail/send/broadcast", request);
103
762
  }
104
763
  /**
105
764
  * Get email details by ID
@@ -111,14 +770,87 @@ var Mail = class {
111
770
  * ```
112
771
  */
113
772
  async get(id) {
114
- const response = await this.http.get(`/mail/${id}`);
115
- const dateFields = ["createdAt", "sentAt", "deliveredAt", "openedAt", "clickedAt", "bouncedAt"];
116
- for (const field of dateFields) {
117
- if (response[field] && typeof response[field] === "string") {
118
- response[field] = new Date(response[field]);
119
- }
773
+ return this.http.get(`/mail/${id}`);
774
+ }
775
+ /**
776
+ * List emails with optional filters
777
+ *
778
+ * @example
779
+ * ```typescript
780
+ * const result = await mail.list({
781
+ * status: 'delivered',
782
+ * limit: 50,
783
+ * });
784
+ * ```
785
+ */
786
+ async list(request = {}) {
787
+ const params = new URLSearchParams();
788
+ if (request.projectSlug) params.set("projectSlug", request.projectSlug);
789
+ if (request.environment) params.set("environment", request.environment);
790
+ if (request.limit) params.set("limit", request.limit.toString());
791
+ if (request.offset) params.set("offset", request.offset.toString());
792
+ if (request.status) params.set("status", request.status);
793
+ if (request.from) params.set("from", request.from);
794
+ if (request.to) params.set("to", request.to);
795
+ if (request.subject) params.set("subject", request.subject);
796
+ if (request.tag) params.set("tag", request.tag);
797
+ if (request.startDate) {
798
+ params.set("startDate", request.startDate instanceof Date ? request.startDate.toISOString() : request.startDate);
120
799
  }
121
- return response;
800
+ if (request.endDate) {
801
+ params.set("endDate", request.endDate instanceof Date ? request.endDate.toISOString() : request.endDate);
802
+ }
803
+ if (request.sortBy) params.set("sortBy", request.sortBy);
804
+ if (request.sortOrder) params.set("sortOrder", request.sortOrder);
805
+ const query = params.toString();
806
+ return this.http.get(`/mail${query ? `?${query}` : ""}`);
807
+ }
808
+ /**
809
+ * Resend a previously sent email
810
+ */
811
+ async resend(id) {
812
+ return this.http.post(`/mail/${id}/resend`, {});
813
+ }
814
+ /**
815
+ * Cancel a scheduled email
816
+ */
817
+ async cancel(id) {
818
+ return this.http.post(`/mail/${id}/cancel`, {});
819
+ }
820
+ // ============================================================================
821
+ // ANALYTICS
822
+ // ============================================================================
823
+ /**
824
+ * Get overall email analytics
825
+ */
826
+ async getAnalytics() {
827
+ return this.http.get("/mail/analytics");
828
+ }
829
+ /**
830
+ * Get time series analytics (daily breakdown)
831
+ */
832
+ async getTimeSeriesAnalytics(request = {}) {
833
+ const params = new URLSearchParams();
834
+ if (request.days) params.set("days", request.days.toString());
835
+ const query = params.toString();
836
+ return this.http.get(`/mail/analytics/timeseries${query ? `?${query}` : ""}`);
837
+ }
838
+ /**
839
+ * Get hourly analytics
840
+ */
841
+ async getHourlyAnalytics() {
842
+ return this.http.get("/mail/analytics/hourly");
843
+ }
844
+ /**
845
+ * List unique senders with their statistics
846
+ */
847
+ async listSenders(request = {}) {
848
+ const params = new URLSearchParams();
849
+ if (request.projectSlug) params.set("projectSlug", request.projectSlug);
850
+ if (request.environment) params.set("environment", request.environment);
851
+ if (request.search) params.set("search", request.search);
852
+ const query = params.toString();
853
+ return this.http.get(`/mail/senders${query ? `?${query}` : ""}`);
122
854
  }
123
855
  };
124
856
 
@@ -599,6 +1331,273 @@ var CDN = class {
599
1331
  }
600
1332
  return job;
601
1333
  }
1334
+ // ============================================================================
1335
+ // Private Files Methods
1336
+ // ============================================================================
1337
+ /**
1338
+ * Generate a presigned URL for uploading a private file
1339
+ *
1340
+ * Private files are stored securely and can only be accessed through
1341
+ * authorized download links with configurable expiration.
1342
+ *
1343
+ * @example
1344
+ * ```typescript
1345
+ * const { uploadUrl, fileId } = await cdn.getPrivateUploadUrl({
1346
+ * projectSlug: 'my-project',
1347
+ * filename: 'confidential.pdf',
1348
+ * mimeType: 'application/pdf',
1349
+ * size: 1024 * 1024,
1350
+ * });
1351
+ *
1352
+ * // Upload file to the presigned URL
1353
+ * await fetch(uploadUrl, {
1354
+ * method: 'PUT',
1355
+ * body: file,
1356
+ * headers: { 'Content-Type': 'application/pdf' },
1357
+ * });
1358
+ *
1359
+ * // Confirm the upload
1360
+ * const privateFile = await cdn.confirmPrivateUpload(fileId);
1361
+ * ```
1362
+ */
1363
+ async getPrivateUploadUrl(request) {
1364
+ const response = await this.http.post("/cdn/private/upload", request);
1365
+ if (typeof response.expiresAt === "string") {
1366
+ response.expiresAt = new Date(response.expiresAt);
1367
+ }
1368
+ return response;
1369
+ }
1370
+ /**
1371
+ * Confirm that a private file upload has completed
1372
+ */
1373
+ async confirmPrivateUpload(fileId) {
1374
+ const response = await this.http.post(`/cdn/private/upload/${fileId}/confirm`, {});
1375
+ return this.convertPrivateFileDates(response);
1376
+ }
1377
+ /**
1378
+ * Upload a private file directly (handles presigned URL flow automatically)
1379
+ *
1380
+ * @example
1381
+ * ```typescript
1382
+ * const privateFile = await cdn.uploadPrivate({
1383
+ * projectSlug: 'my-project',
1384
+ * file: fileBuffer,
1385
+ * filename: 'confidential.pdf',
1386
+ * mimeType: 'application/pdf',
1387
+ * });
1388
+ * ```
1389
+ */
1390
+ async uploadPrivate(options) {
1391
+ const { projectSlug, file, filename, mimeType, folder, description, metadata } = options;
1392
+ let size;
1393
+ if (file instanceof Blob) {
1394
+ size = file.size;
1395
+ } else if (file instanceof ArrayBuffer) {
1396
+ size = file.byteLength;
1397
+ } else {
1398
+ size = file.length;
1399
+ }
1400
+ const { uploadUrl, fileId } = await this.getPrivateUploadUrl({
1401
+ projectSlug,
1402
+ filename,
1403
+ mimeType,
1404
+ size,
1405
+ folder,
1406
+ description,
1407
+ metadata
1408
+ });
1409
+ const uploadResponse = await fetch(uploadUrl, {
1410
+ method: "PUT",
1411
+ body: file,
1412
+ headers: {
1413
+ "Content-Type": mimeType
1414
+ }
1415
+ });
1416
+ if (!uploadResponse.ok) {
1417
+ throw new Error(`Upload failed: ${uploadResponse.statusText}`);
1418
+ }
1419
+ return this.confirmPrivateUpload(fileId);
1420
+ }
1421
+ /**
1422
+ * Generate a presigned download URL for a private file
1423
+ *
1424
+ * @example
1425
+ * ```typescript
1426
+ * const { downloadUrl, expiresAt } = await cdn.getPrivateDownloadUrl({
1427
+ * fileId: 'file-id',
1428
+ * expiresIn: 86400, // 24 hours
1429
+ * });
1430
+ * ```
1431
+ */
1432
+ async getPrivateDownloadUrl(request) {
1433
+ const response = await this.http.post(
1434
+ `/cdn/private/${request.fileId}/download`,
1435
+ { expiresIn: request.expiresIn }
1436
+ );
1437
+ if (typeof response.expiresAt === "string") {
1438
+ response.expiresAt = new Date(response.expiresAt);
1439
+ }
1440
+ return response;
1441
+ }
1442
+ /**
1443
+ * Get a private file by ID
1444
+ */
1445
+ async getPrivateFile(fileId) {
1446
+ const response = await this.http.get(`/cdn/private/${fileId}`);
1447
+ return this.convertPrivateFileDates(response);
1448
+ }
1449
+ /**
1450
+ * Update a private file's metadata
1451
+ */
1452
+ async updatePrivateFile(request) {
1453
+ const { fileId, ...data } = request;
1454
+ const response = await this.http.patch(`/cdn/private/${fileId}`, data);
1455
+ return this.convertPrivateFileDates(response);
1456
+ }
1457
+ /**
1458
+ * Delete a private file
1459
+ */
1460
+ async deletePrivateFile(fileId) {
1461
+ return this.http.deleteWithBody(`/cdn/private/${fileId}`, { fileId });
1462
+ }
1463
+ /**
1464
+ * Delete multiple private files
1465
+ */
1466
+ async deletePrivateFiles(fileIds) {
1467
+ return this.http.post("/cdn/private/delete", { fileIds });
1468
+ }
1469
+ /**
1470
+ * List private files with filters and pagination
1471
+ *
1472
+ * @example
1473
+ * ```typescript
1474
+ * const { files, total, hasMore } = await cdn.listPrivateFiles({
1475
+ * projectSlug: 'my-project',
1476
+ * limit: 20,
1477
+ * });
1478
+ * ```
1479
+ */
1480
+ async listPrivateFiles(request) {
1481
+ const params = new URLSearchParams();
1482
+ params.set("projectSlug", request.projectSlug);
1483
+ if (request.folder !== void 0) params.set("folder", request.folder ?? "");
1484
+ if (request.status) params.set("status", request.status);
1485
+ if (request.search) params.set("search", request.search);
1486
+ if (request.sortBy) params.set("sortBy", request.sortBy);
1487
+ if (request.sortOrder) params.set("sortOrder", request.sortOrder);
1488
+ if (request.limit) params.set("limit", request.limit.toString());
1489
+ if (request.offset) params.set("offset", request.offset.toString());
1490
+ const response = await this.http.get(`/cdn/private?${params.toString()}`);
1491
+ return {
1492
+ ...response,
1493
+ files: response.files.map((file) => this.convertPrivateFileDates(file))
1494
+ };
1495
+ }
1496
+ convertPrivateFileDates(file) {
1497
+ if (typeof file.createdAt === "string") {
1498
+ file.createdAt = new Date(file.createdAt);
1499
+ }
1500
+ if (file.updatedAt && typeof file.updatedAt === "string") {
1501
+ file.updatedAt = new Date(file.updatedAt);
1502
+ }
1503
+ return file;
1504
+ }
1505
+ // ============================================================================
1506
+ // Download Bundle Methods
1507
+ // ============================================================================
1508
+ /**
1509
+ * Create a download bundle from assets and/or private files
1510
+ *
1511
+ * The bundle will be created asynchronously. Check the status using getBundle().
1512
+ *
1513
+ * @example
1514
+ * ```typescript
1515
+ * const { bundle } = await cdn.createBundle({
1516
+ * projectSlug: 'my-project',
1517
+ * name: 'Project Assets - Dec 2024',
1518
+ * assetIds: ['asset-1', 'asset-2'],
1519
+ * privateFileIds: ['file-1', 'file-2'],
1520
+ * expiresIn: 86400, // 24 hours
1521
+ * });
1522
+ * console.log(`Bundle ${bundle.id} status: ${bundle.status}`);
1523
+ * ```
1524
+ */
1525
+ async createBundle(request) {
1526
+ const response = await this.http.post("/cdn/bundles", request);
1527
+ return {
1528
+ bundle: this.convertBundleDates(response.bundle)
1529
+ };
1530
+ }
1531
+ /**
1532
+ * Get a download bundle by ID
1533
+ */
1534
+ async getBundle(bundleId) {
1535
+ const response = await this.http.get(`/cdn/bundles/${bundleId}`);
1536
+ return this.convertBundleDates(response);
1537
+ }
1538
+ /**
1539
+ * List download bundles with filters and pagination
1540
+ *
1541
+ * @example
1542
+ * ```typescript
1543
+ * const { bundles, total } = await cdn.listBundles({
1544
+ * projectSlug: 'my-project',
1545
+ * status: 'ready',
1546
+ * });
1547
+ * ```
1548
+ */
1549
+ async listBundles(request) {
1550
+ const params = new URLSearchParams();
1551
+ params.set("projectSlug", request.projectSlug);
1552
+ if (request.status) params.set("status", request.status);
1553
+ if (request.search) params.set("search", request.search);
1554
+ if (request.limit) params.set("limit", request.limit.toString());
1555
+ if (request.offset) params.set("offset", request.offset.toString());
1556
+ const response = await this.http.get(`/cdn/bundles?${params.toString()}`);
1557
+ return {
1558
+ ...response,
1559
+ bundles: response.bundles.map((bundle) => this.convertBundleDates(bundle))
1560
+ };
1561
+ }
1562
+ /**
1563
+ * Generate a presigned download URL for a bundle
1564
+ *
1565
+ * @example
1566
+ * ```typescript
1567
+ * const { downloadUrl, expiresAt } = await cdn.getBundleDownloadUrl({
1568
+ * bundleId: 'bundle-id',
1569
+ * expiresIn: 3600, // 1 hour
1570
+ * });
1571
+ * ```
1572
+ */
1573
+ async getBundleDownloadUrl(request) {
1574
+ const response = await this.http.post(
1575
+ `/cdn/bundles/${request.bundleId}/download`,
1576
+ { expiresIn: request.expiresIn }
1577
+ );
1578
+ if (typeof response.expiresAt === "string") {
1579
+ response.expiresAt = new Date(response.expiresAt);
1580
+ }
1581
+ return response;
1582
+ }
1583
+ /**
1584
+ * Delete a download bundle
1585
+ */
1586
+ async deleteBundle(bundleId) {
1587
+ return this.http.deleteWithBody(`/cdn/bundles/${bundleId}`, { bundleId });
1588
+ }
1589
+ convertBundleDates(bundle) {
1590
+ if (typeof bundle.createdAt === "string") {
1591
+ bundle.createdAt = new Date(bundle.createdAt);
1592
+ }
1593
+ if (bundle.completedAt && typeof bundle.completedAt === "string") {
1594
+ bundle.completedAt = new Date(bundle.completedAt);
1595
+ }
1596
+ if (bundle.expiresAt && typeof bundle.expiresAt === "string") {
1597
+ bundle.expiresAt = new Date(bundle.expiresAt);
1598
+ }
1599
+ return bundle;
1600
+ }
602
1601
  };
603
1602
 
604
1603
  // src/screenshots/client.ts
@@ -2643,6 +3642,6 @@ var Stack0 = class {
2643
3642
  };
2644
3643
  var src_default = Stack0;
2645
3644
 
2646
- export { CDN, Extraction, Integrations, Mail, Marketing, Screenshots, Stack0, Webdata, src_default as default };
3645
+ export { Audiences, CDN, Campaigns, Contacts, Domains, Events, Extraction, Integrations, Mail, Marketing, Screenshots, Sequences, Stack0, Templates, Webdata, src_default as default };
2647
3646
  //# sourceMappingURL=index.mjs.map
2648
3647
  //# sourceMappingURL=index.mjs.map