@depup/resend 6.9.4-depup.0

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 ADDED
@@ -0,0 +1,995 @@
1
+ import PostalMime from "postal-mime";
2
+ import { Webhook } from "svix";
3
+ //#region package.json
4
+ var version = "6.9.4";
5
+ //#endregion
6
+ //#region src/common/utils/build-pagination-query.ts
7
+ /**
8
+ * Builds a query string from pagination options
9
+ * @param options - Pagination options containing limit and either after or before (but not both)
10
+ * @returns Query string (without leading '?') or empty string if no options
11
+ */
12
+ function buildPaginationQuery(options) {
13
+ const searchParams = new URLSearchParams();
14
+ if (options.limit !== void 0) searchParams.set("limit", options.limit.toString());
15
+ if ("after" in options && options.after !== void 0) searchParams.set("after", options.after);
16
+ if ("before" in options && options.before !== void 0) searchParams.set("before", options.before);
17
+ return searchParams.toString();
18
+ }
19
+ //#endregion
20
+ //#region src/api-keys/api-keys.ts
21
+ var ApiKeys = class {
22
+ constructor(resend) {
23
+ this.resend = resend;
24
+ }
25
+ async create(payload, options = {}) {
26
+ return await this.resend.post("/api-keys", payload, options);
27
+ }
28
+ async list(options = {}) {
29
+ const queryString = buildPaginationQuery(options);
30
+ const url = queryString ? `/api-keys?${queryString}` : "/api-keys";
31
+ return await this.resend.get(url);
32
+ }
33
+ async remove(id) {
34
+ return await this.resend.delete(`/api-keys/${id}`);
35
+ }
36
+ };
37
+ //#endregion
38
+ //#region src/common/utils/parse-email-to-api-options.ts
39
+ function parseAttachments(attachments) {
40
+ return attachments?.map((attachment) => ({
41
+ content: attachment.content,
42
+ filename: attachment.filename,
43
+ path: attachment.path,
44
+ content_type: attachment.contentType,
45
+ content_id: attachment.contentId
46
+ }));
47
+ }
48
+ function parseEmailToApiOptions(email) {
49
+ return {
50
+ attachments: parseAttachments(email.attachments),
51
+ bcc: email.bcc,
52
+ cc: email.cc,
53
+ from: email.from,
54
+ headers: email.headers,
55
+ html: email.html,
56
+ reply_to: email.replyTo,
57
+ scheduled_at: email.scheduledAt,
58
+ subject: email.subject,
59
+ tags: email.tags,
60
+ text: email.text,
61
+ to: email.to,
62
+ template: email.template ? {
63
+ id: email.template.id,
64
+ variables: email.template.variables
65
+ } : void 0,
66
+ topic_id: email.topicId
67
+ };
68
+ }
69
+ //#endregion
70
+ //#region src/render.ts
71
+ async function render(node) {
72
+ let render;
73
+ try {
74
+ ({render} = await import("@react-email/render"));
75
+ } catch {
76
+ throw new Error("Failed to render React component. Make sure to install `@react-email/render` or `@react-email/components`.");
77
+ }
78
+ return render(node);
79
+ }
80
+ //#endregion
81
+ //#region src/batch/batch.ts
82
+ var Batch = class {
83
+ constructor(resend) {
84
+ this.resend = resend;
85
+ }
86
+ async send(payload, options) {
87
+ return this.create(payload, options);
88
+ }
89
+ async create(payload, options) {
90
+ const emails = [];
91
+ for (const email of payload) {
92
+ if (email.react) {
93
+ email.html = await render(email.react);
94
+ email.react = void 0;
95
+ }
96
+ emails.push(parseEmailToApiOptions(email));
97
+ }
98
+ return await this.resend.post("/emails/batch", emails, {
99
+ ...options,
100
+ headers: {
101
+ "x-batch-validation": options?.batchValidation ?? "strict",
102
+ ...options?.headers
103
+ }
104
+ });
105
+ }
106
+ };
107
+ //#endregion
108
+ //#region src/broadcasts/broadcasts.ts
109
+ var Broadcasts = class {
110
+ constructor(resend) {
111
+ this.resend = resend;
112
+ }
113
+ async create(payload, options = {}) {
114
+ if (payload.react) payload.html = await render(payload.react);
115
+ return await this.resend.post("/broadcasts", {
116
+ name: payload.name,
117
+ segment_id: payload.segmentId,
118
+ audience_id: payload.audienceId,
119
+ preview_text: payload.previewText,
120
+ from: payload.from,
121
+ html: payload.html,
122
+ reply_to: payload.replyTo,
123
+ subject: payload.subject,
124
+ text: payload.text,
125
+ topic_id: payload.topicId,
126
+ send: payload.send,
127
+ scheduled_at: payload.scheduledAt
128
+ }, options);
129
+ }
130
+ async send(id, payload) {
131
+ return await this.resend.post(`/broadcasts/${id}/send`, { scheduled_at: payload?.scheduledAt });
132
+ }
133
+ async list(options = {}) {
134
+ const queryString = buildPaginationQuery(options);
135
+ const url = queryString ? `/broadcasts?${queryString}` : "/broadcasts";
136
+ return await this.resend.get(url);
137
+ }
138
+ async get(id) {
139
+ return await this.resend.get(`/broadcasts/${id}`);
140
+ }
141
+ async remove(id) {
142
+ return await this.resend.delete(`/broadcasts/${id}`);
143
+ }
144
+ async update(id, payload) {
145
+ if (payload.react) payload.html = await render(payload.react);
146
+ return await this.resend.patch(`/broadcasts/${id}`, {
147
+ name: payload.name,
148
+ segment_id: payload.segmentId,
149
+ audience_id: payload.audienceId,
150
+ from: payload.from,
151
+ html: payload.html,
152
+ text: payload.text,
153
+ subject: payload.subject,
154
+ reply_to: payload.replyTo,
155
+ preview_text: payload.previewText,
156
+ topic_id: payload.topicId
157
+ });
158
+ }
159
+ };
160
+ //#endregion
161
+ //#region src/common/utils/parse-contact-properties-to-api-options.ts
162
+ function parseContactPropertyFromApi(contactProperty) {
163
+ return {
164
+ id: contactProperty.id,
165
+ key: contactProperty.key,
166
+ createdAt: contactProperty.created_at,
167
+ type: contactProperty.type,
168
+ fallbackValue: contactProperty.fallback_value
169
+ };
170
+ }
171
+ function parseContactPropertyToApiOptions(contactProperty) {
172
+ if ("key" in contactProperty) return {
173
+ key: contactProperty.key,
174
+ type: contactProperty.type,
175
+ fallback_value: contactProperty.fallbackValue
176
+ };
177
+ return { fallback_value: contactProperty.fallbackValue };
178
+ }
179
+ //#endregion
180
+ //#region src/contact-properties/contact-properties.ts
181
+ var ContactProperties = class {
182
+ constructor(resend) {
183
+ this.resend = resend;
184
+ }
185
+ async create(options) {
186
+ const apiOptions = parseContactPropertyToApiOptions(options);
187
+ return await this.resend.post("/contact-properties", apiOptions);
188
+ }
189
+ async list(options = {}) {
190
+ const queryString = buildPaginationQuery(options);
191
+ const url = queryString ? `/contact-properties?${queryString}` : "/contact-properties";
192
+ const response = await this.resend.get(url);
193
+ if (response.data) return {
194
+ data: {
195
+ ...response.data,
196
+ data: response.data.data.map((apiContactProperty) => parseContactPropertyFromApi(apiContactProperty))
197
+ },
198
+ headers: response.headers,
199
+ error: null
200
+ };
201
+ return response;
202
+ }
203
+ async get(id) {
204
+ if (!id) return {
205
+ data: null,
206
+ headers: null,
207
+ error: {
208
+ message: "Missing `id` field.",
209
+ statusCode: null,
210
+ name: "missing_required_field"
211
+ }
212
+ };
213
+ const response = await this.resend.get(`/contact-properties/${id}`);
214
+ if (response.data) return {
215
+ data: {
216
+ object: "contact_property",
217
+ ...parseContactPropertyFromApi(response.data)
218
+ },
219
+ headers: response.headers,
220
+ error: null
221
+ };
222
+ return response;
223
+ }
224
+ async update(payload) {
225
+ if (!payload.id) return {
226
+ data: null,
227
+ headers: null,
228
+ error: {
229
+ message: "Missing `id` field.",
230
+ statusCode: null,
231
+ name: "missing_required_field"
232
+ }
233
+ };
234
+ const apiOptions = parseContactPropertyToApiOptions(payload);
235
+ return await this.resend.patch(`/contact-properties/${payload.id}`, apiOptions);
236
+ }
237
+ async remove(id) {
238
+ if (!id) return {
239
+ data: null,
240
+ headers: null,
241
+ error: {
242
+ message: "Missing `id` field.",
243
+ statusCode: null,
244
+ name: "missing_required_field"
245
+ }
246
+ };
247
+ return await this.resend.delete(`/contact-properties/${id}`);
248
+ }
249
+ };
250
+ //#endregion
251
+ //#region src/contacts/segments/contact-segments.ts
252
+ var ContactSegments = class {
253
+ constructor(resend) {
254
+ this.resend = resend;
255
+ }
256
+ async list(options) {
257
+ if (!options.contactId && !options.email) return {
258
+ data: null,
259
+ headers: null,
260
+ error: {
261
+ message: "Missing `id` or `email` field.",
262
+ statusCode: null,
263
+ name: "missing_required_field"
264
+ }
265
+ };
266
+ const identifier = options.email ? options.email : options.contactId;
267
+ const queryString = buildPaginationQuery(options);
268
+ const url = queryString ? `/contacts/${identifier}/segments?${queryString}` : `/contacts/${identifier}/segments`;
269
+ return await this.resend.get(url);
270
+ }
271
+ async add(options) {
272
+ if (!options.contactId && !options.email) return {
273
+ data: null,
274
+ headers: null,
275
+ error: {
276
+ message: "Missing `id` or `email` field.",
277
+ statusCode: null,
278
+ name: "missing_required_field"
279
+ }
280
+ };
281
+ const identifier = options.email ? options.email : options.contactId;
282
+ return this.resend.post(`/contacts/${identifier}/segments/${options.segmentId}`);
283
+ }
284
+ async remove(options) {
285
+ if (!options.contactId && !options.email) return {
286
+ data: null,
287
+ headers: null,
288
+ error: {
289
+ message: "Missing `id` or `email` field.",
290
+ statusCode: null,
291
+ name: "missing_required_field"
292
+ }
293
+ };
294
+ const identifier = options.email ? options.email : options.contactId;
295
+ return this.resend.delete(`/contacts/${identifier}/segments/${options.segmentId}`);
296
+ }
297
+ };
298
+ //#endregion
299
+ //#region src/contacts/topics/contact-topics.ts
300
+ var ContactTopics = class {
301
+ constructor(resend) {
302
+ this.resend = resend;
303
+ }
304
+ async update(payload) {
305
+ if (!payload.id && !payload.email) return {
306
+ data: null,
307
+ headers: null,
308
+ error: {
309
+ message: "Missing `id` or `email` field.",
310
+ statusCode: null,
311
+ name: "missing_required_field"
312
+ }
313
+ };
314
+ const identifier = payload.email ? payload.email : payload.id;
315
+ return this.resend.patch(`/contacts/${identifier}/topics`, payload.topics);
316
+ }
317
+ async list(options) {
318
+ if (!options.id && !options.email) return {
319
+ data: null,
320
+ headers: null,
321
+ error: {
322
+ message: "Missing `id` or `email` field.",
323
+ statusCode: null,
324
+ name: "missing_required_field"
325
+ }
326
+ };
327
+ const identifier = options.email ? options.email : options.id;
328
+ const queryString = buildPaginationQuery(options);
329
+ const url = queryString ? `/contacts/${identifier}/topics?${queryString}` : `/contacts/${identifier}/topics`;
330
+ return this.resend.get(url);
331
+ }
332
+ };
333
+ //#endregion
334
+ //#region src/contacts/contacts.ts
335
+ var Contacts = class {
336
+ constructor(resend) {
337
+ this.resend = resend;
338
+ this.topics = new ContactTopics(this.resend);
339
+ this.segments = new ContactSegments(this.resend);
340
+ }
341
+ async create(payload, options = {}) {
342
+ if ("audienceId" in payload) {
343
+ if ("segments" in payload || "topics" in payload) return {
344
+ data: null,
345
+ headers: null,
346
+ error: {
347
+ message: "`audienceId` is deprecated, and cannot be used together with `segments` or `topics`. Use `segments` instead to add one or more segments to the new contact.",
348
+ statusCode: null,
349
+ name: "invalid_parameter"
350
+ }
351
+ };
352
+ return await this.resend.post(`/audiences/${payload.audienceId}/contacts`, {
353
+ unsubscribed: payload.unsubscribed,
354
+ email: payload.email,
355
+ first_name: payload.firstName,
356
+ last_name: payload.lastName,
357
+ properties: payload.properties
358
+ }, options);
359
+ }
360
+ return await this.resend.post("/contacts", {
361
+ unsubscribed: payload.unsubscribed,
362
+ email: payload.email,
363
+ first_name: payload.firstName,
364
+ last_name: payload.lastName,
365
+ properties: payload.properties,
366
+ segments: payload.segments,
367
+ topics: payload.topics
368
+ }, options);
369
+ }
370
+ async list(options = {}) {
371
+ const segmentId = options.segmentId ?? options.audienceId;
372
+ if (!segmentId) {
373
+ const queryString = buildPaginationQuery(options);
374
+ const url = queryString ? `/contacts?${queryString}` : "/contacts";
375
+ return await this.resend.get(url);
376
+ }
377
+ const queryString = buildPaginationQuery(options);
378
+ const url = queryString ? `/segments/${segmentId}/contacts?${queryString}` : `/segments/${segmentId}/contacts`;
379
+ return await this.resend.get(url);
380
+ }
381
+ async get(options) {
382
+ if (typeof options === "string") return this.resend.get(`/contacts/${options}`);
383
+ if (!options.id && !options.email) return {
384
+ data: null,
385
+ headers: null,
386
+ error: {
387
+ message: "Missing `id` or `email` field.",
388
+ statusCode: null,
389
+ name: "missing_required_field"
390
+ }
391
+ };
392
+ if (!options.audienceId) return this.resend.get(`/contacts/${options?.email ? options?.email : options?.id}`);
393
+ return this.resend.get(`/audiences/${options.audienceId}/contacts/${options?.email ? options?.email : options?.id}`);
394
+ }
395
+ async update(options) {
396
+ if (!options.id && !options.email) return {
397
+ data: null,
398
+ headers: null,
399
+ error: {
400
+ message: "Missing `id` or `email` field.",
401
+ statusCode: null,
402
+ name: "missing_required_field"
403
+ }
404
+ };
405
+ if (!options.audienceId) return await this.resend.patch(`/contacts/${options?.email ? options?.email : options?.id}`, {
406
+ unsubscribed: options.unsubscribed,
407
+ first_name: options.firstName,
408
+ last_name: options.lastName,
409
+ properties: options.properties
410
+ });
411
+ return await this.resend.patch(`/audiences/${options.audienceId}/contacts/${options?.email ? options?.email : options?.id}`, {
412
+ unsubscribed: options.unsubscribed,
413
+ first_name: options.firstName,
414
+ last_name: options.lastName,
415
+ properties: options.properties
416
+ });
417
+ }
418
+ async remove(payload) {
419
+ if (typeof payload === "string") return this.resend.delete(`/contacts/${payload}`);
420
+ if (!payload.id && !payload.email) return {
421
+ data: null,
422
+ headers: null,
423
+ error: {
424
+ message: "Missing `id` or `email` field.",
425
+ statusCode: null,
426
+ name: "missing_required_field"
427
+ }
428
+ };
429
+ if (!payload.audienceId) return this.resend.delete(`/contacts/${payload?.email ? payload?.email : payload?.id}`);
430
+ return this.resend.delete(`/audiences/${payload.audienceId}/contacts/${payload?.email ? payload?.email : payload?.id}`);
431
+ }
432
+ };
433
+ //#endregion
434
+ //#region src/common/utils/parse-domain-to-api-options.ts
435
+ function parseDomainToApiOptions(domain) {
436
+ return {
437
+ name: domain.name,
438
+ region: domain.region,
439
+ custom_return_path: domain.customReturnPath,
440
+ capabilities: domain.capabilities,
441
+ open_tracking: domain.openTracking,
442
+ click_tracking: domain.clickTracking,
443
+ tls: domain.tls
444
+ };
445
+ }
446
+ //#endregion
447
+ //#region src/domains/domains.ts
448
+ var Domains = class {
449
+ constructor(resend) {
450
+ this.resend = resend;
451
+ }
452
+ async create(payload, options = {}) {
453
+ return await this.resend.post("/domains", parseDomainToApiOptions(payload), options);
454
+ }
455
+ async list(options = {}) {
456
+ const queryString = buildPaginationQuery(options);
457
+ const url = queryString ? `/domains?${queryString}` : "/domains";
458
+ return await this.resend.get(url);
459
+ }
460
+ async get(id) {
461
+ return await this.resend.get(`/domains/${id}`);
462
+ }
463
+ async update(payload) {
464
+ return await this.resend.patch(`/domains/${payload.id}`, {
465
+ click_tracking: payload.clickTracking,
466
+ open_tracking: payload.openTracking,
467
+ tls: payload.tls,
468
+ capabilities: payload.capabilities
469
+ });
470
+ }
471
+ async remove(id) {
472
+ return await this.resend.delete(`/domains/${id}`);
473
+ }
474
+ async verify(id) {
475
+ return await this.resend.post(`/domains/${id}/verify`);
476
+ }
477
+ };
478
+ //#endregion
479
+ //#region src/emails/attachments/attachments.ts
480
+ var Attachments$1 = class {
481
+ constructor(resend) {
482
+ this.resend = resend;
483
+ }
484
+ async get(options) {
485
+ const { emailId, id } = options;
486
+ return await this.resend.get(`/emails/${emailId}/attachments/${id}`);
487
+ }
488
+ async list(options) {
489
+ const { emailId } = options;
490
+ const queryString = buildPaginationQuery(options);
491
+ const url = queryString ? `/emails/${emailId}/attachments?${queryString}` : `/emails/${emailId}/attachments`;
492
+ return await this.resend.get(url);
493
+ }
494
+ };
495
+ //#endregion
496
+ //#region src/emails/receiving/attachments/attachments.ts
497
+ var Attachments = class {
498
+ constructor(resend) {
499
+ this.resend = resend;
500
+ }
501
+ async get(options) {
502
+ const { emailId, id } = options;
503
+ return await this.resend.get(`/emails/receiving/${emailId}/attachments/${id}`);
504
+ }
505
+ async list(options) {
506
+ const { emailId } = options;
507
+ const queryString = buildPaginationQuery(options);
508
+ const url = queryString ? `/emails/receiving/${emailId}/attachments?${queryString}` : `/emails/receiving/${emailId}/attachments`;
509
+ return await this.resend.get(url);
510
+ }
511
+ };
512
+ //#endregion
513
+ //#region src/emails/receiving/receiving.ts
514
+ var Receiving = class {
515
+ constructor(resend) {
516
+ this.resend = resend;
517
+ this.attachments = new Attachments(resend);
518
+ }
519
+ async get(id) {
520
+ return await this.resend.get(`/emails/receiving/${id}`);
521
+ }
522
+ async list(options = {}) {
523
+ const queryString = buildPaginationQuery(options);
524
+ const url = queryString ? `/emails/receiving?${queryString}` : "/emails/receiving";
525
+ return await this.resend.get(url);
526
+ }
527
+ async forward(options) {
528
+ const { emailId, to, from } = options;
529
+ const passthrough = options.passthrough !== false;
530
+ const emailResponse = await this.get(emailId);
531
+ if (emailResponse.error) return {
532
+ data: null,
533
+ error: emailResponse.error,
534
+ headers: emailResponse.headers
535
+ };
536
+ const email = emailResponse.data;
537
+ const originalSubject = email.subject || "(no subject)";
538
+ if (passthrough) return this.forwardPassthrough(email, {
539
+ to,
540
+ from,
541
+ subject: originalSubject
542
+ });
543
+ const forwardSubject = originalSubject.startsWith("Fwd:") ? originalSubject : `Fwd: ${originalSubject}`;
544
+ return this.forwardWrapped(email, {
545
+ to,
546
+ from,
547
+ subject: forwardSubject,
548
+ text: "text" in options ? options.text : void 0,
549
+ html: "html" in options ? options.html : void 0
550
+ });
551
+ }
552
+ async forwardPassthrough(email, options) {
553
+ const { to, from, subject } = options;
554
+ if (!email.raw?.download_url) return {
555
+ data: null,
556
+ error: {
557
+ name: "validation_error",
558
+ message: "Raw email content is not available for this email",
559
+ statusCode: 400
560
+ },
561
+ headers: null
562
+ };
563
+ const rawResponse = await fetch(email.raw.download_url);
564
+ if (!rawResponse.ok) return {
565
+ data: null,
566
+ error: {
567
+ name: "application_error",
568
+ message: "Failed to download raw email content",
569
+ statusCode: rawResponse.status
570
+ },
571
+ headers: null
572
+ };
573
+ const rawEmailContent = await rawResponse.text();
574
+ const parsed = await PostalMime.parse(rawEmailContent, { attachmentEncoding: "base64" });
575
+ const attachments = parsed.attachments.map((attachment) => {
576
+ const contentId = attachment.contentId ? attachment.contentId.replace(/^<|>$/g, "") : void 0;
577
+ return {
578
+ filename: attachment.filename,
579
+ content: attachment.content.toString(),
580
+ content_type: attachment.mimeType,
581
+ content_id: contentId || void 0
582
+ };
583
+ });
584
+ return await this.resend.post("/emails", {
585
+ from,
586
+ to,
587
+ subject,
588
+ text: parsed.text || void 0,
589
+ html: parsed.html || void 0,
590
+ attachments: attachments.length > 0 ? attachments : void 0
591
+ });
592
+ }
593
+ async forwardWrapped(email, options) {
594
+ const { to, from, subject, text, html } = options;
595
+ if (!email.raw?.download_url) return {
596
+ data: null,
597
+ error: {
598
+ name: "validation_error",
599
+ message: "Raw email content is not available for this email",
600
+ statusCode: 400
601
+ },
602
+ headers: null
603
+ };
604
+ const rawResponse = await fetch(email.raw.download_url);
605
+ if (!rawResponse.ok) return {
606
+ data: null,
607
+ error: {
608
+ name: "application_error",
609
+ message: "Failed to download raw email content",
610
+ statusCode: rawResponse.status
611
+ },
612
+ headers: null
613
+ };
614
+ const rawEmailContent = await rawResponse.text();
615
+ return await this.resend.post("/emails", {
616
+ from,
617
+ to,
618
+ subject,
619
+ text,
620
+ html,
621
+ attachments: [{
622
+ filename: "forwarded_message.eml",
623
+ content: Buffer.from(rawEmailContent).toString("base64"),
624
+ content_type: "message/rfc822"
625
+ }]
626
+ });
627
+ }
628
+ };
629
+ //#endregion
630
+ //#region src/emails/emails.ts
631
+ var Emails = class {
632
+ constructor(resend) {
633
+ this.resend = resend;
634
+ this.attachments = new Attachments$1(resend);
635
+ this.receiving = new Receiving(resend);
636
+ }
637
+ async send(payload, options = {}) {
638
+ return this.create(payload, options);
639
+ }
640
+ async create(payload, options = {}) {
641
+ if (payload.react) payload.html = await render(payload.react);
642
+ return await this.resend.post("/emails", parseEmailToApiOptions(payload), options);
643
+ }
644
+ async get(id) {
645
+ return await this.resend.get(`/emails/${id}`);
646
+ }
647
+ async list(options = {}) {
648
+ const queryString = buildPaginationQuery(options);
649
+ const url = queryString ? `/emails?${queryString}` : "/emails";
650
+ return await this.resend.get(url);
651
+ }
652
+ async update(payload) {
653
+ return await this.resend.patch(`/emails/${payload.id}`, { scheduled_at: payload.scheduledAt });
654
+ }
655
+ async cancel(id) {
656
+ return await this.resend.post(`/emails/${id}/cancel`);
657
+ }
658
+ };
659
+ //#endregion
660
+ //#region src/segments/segments.ts
661
+ var Segments = class {
662
+ constructor(resend) {
663
+ this.resend = resend;
664
+ }
665
+ async create(payload, options = {}) {
666
+ return await this.resend.post("/segments", payload, options);
667
+ }
668
+ async list(options = {}) {
669
+ const queryString = buildPaginationQuery(options);
670
+ const url = queryString ? `/segments?${queryString}` : "/segments";
671
+ return await this.resend.get(url);
672
+ }
673
+ async get(id) {
674
+ return await this.resend.get(`/segments/${id}`);
675
+ }
676
+ async remove(id) {
677
+ return await this.resend.delete(`/segments/${id}`);
678
+ }
679
+ };
680
+ //#endregion
681
+ //#region src/common/utils/get-pagination-query-properties.ts
682
+ function getPaginationQueryProperties(options = {}) {
683
+ const query = new URLSearchParams();
684
+ if (options.before) query.set("before", options.before);
685
+ if (options.after) query.set("after", options.after);
686
+ if (options.limit) query.set("limit", options.limit.toString());
687
+ return query.size > 0 ? `?${query.toString()}` : "";
688
+ }
689
+ //#endregion
690
+ //#region src/common/utils/parse-template-to-api-options.ts
691
+ function parseVariables(variables) {
692
+ return variables?.map((variable) => ({
693
+ key: variable.key,
694
+ type: variable.type,
695
+ fallback_value: variable.fallbackValue
696
+ }));
697
+ }
698
+ function parseTemplateToApiOptions(template) {
699
+ return {
700
+ name: "name" in template ? template.name : void 0,
701
+ subject: template.subject,
702
+ html: template.html,
703
+ text: template.text,
704
+ alias: template.alias,
705
+ from: template.from,
706
+ reply_to: template.replyTo,
707
+ variables: parseVariables(template.variables)
708
+ };
709
+ }
710
+ //#endregion
711
+ //#region src/templates/chainable-template-result.ts
712
+ var ChainableTemplateResult = class {
713
+ constructor(promise, publishFn) {
714
+ this.promise = promise;
715
+ this.publishFn = publishFn;
716
+ }
717
+ then(onfulfilled, onrejected) {
718
+ return this.promise.then(onfulfilled, onrejected);
719
+ }
720
+ async publish() {
721
+ const { data, error } = await this.promise;
722
+ if (error) return {
723
+ data: null,
724
+ headers: null,
725
+ error
726
+ };
727
+ return this.publishFn(data.id);
728
+ }
729
+ };
730
+ //#endregion
731
+ //#region src/templates/templates.ts
732
+ var Templates = class {
733
+ constructor(resend) {
734
+ this.resend = resend;
735
+ }
736
+ create(payload) {
737
+ return new ChainableTemplateResult(this.performCreate(payload), this.publish.bind(this));
738
+ }
739
+ async performCreate(payload) {
740
+ if (payload.react) {
741
+ if (!this.renderAsync) try {
742
+ const { renderAsync } = await import("@react-email/render");
743
+ this.renderAsync = renderAsync;
744
+ } catch {
745
+ throw new Error("Failed to render React component. Make sure to install `@react-email/render`");
746
+ }
747
+ payload.html = await this.renderAsync(payload.react);
748
+ }
749
+ return this.resend.post("/templates", parseTemplateToApiOptions(payload));
750
+ }
751
+ async remove(identifier) {
752
+ return await this.resend.delete(`/templates/${identifier}`);
753
+ }
754
+ async get(identifier) {
755
+ return await this.resend.get(`/templates/${identifier}`);
756
+ }
757
+ async list(options = {}) {
758
+ return this.resend.get(`/templates${getPaginationQueryProperties(options)}`);
759
+ }
760
+ duplicate(identifier) {
761
+ return new ChainableTemplateResult(this.resend.post(`/templates/${identifier}/duplicate`), this.publish.bind(this));
762
+ }
763
+ async publish(identifier) {
764
+ return await this.resend.post(`/templates/${identifier}/publish`);
765
+ }
766
+ async update(identifier, payload) {
767
+ return await this.resend.patch(`/templates/${identifier}`, parseTemplateToApiOptions(payload));
768
+ }
769
+ };
770
+ //#endregion
771
+ //#region src/topics/topics.ts
772
+ var Topics = class {
773
+ constructor(resend) {
774
+ this.resend = resend;
775
+ }
776
+ async create(payload) {
777
+ const { defaultSubscription, ...body } = payload;
778
+ return await this.resend.post("/topics", {
779
+ ...body,
780
+ default_subscription: defaultSubscription
781
+ });
782
+ }
783
+ async list() {
784
+ return await this.resend.get("/topics");
785
+ }
786
+ async get(id) {
787
+ if (!id) return {
788
+ data: null,
789
+ headers: null,
790
+ error: {
791
+ message: "Missing `id` field.",
792
+ statusCode: null,
793
+ name: "missing_required_field"
794
+ }
795
+ };
796
+ return await this.resend.get(`/topics/${id}`);
797
+ }
798
+ async update(payload) {
799
+ if (!payload.id) return {
800
+ data: null,
801
+ headers: null,
802
+ error: {
803
+ message: "Missing `id` field.",
804
+ statusCode: null,
805
+ name: "missing_required_field"
806
+ }
807
+ };
808
+ return await this.resend.patch(`/topics/${payload.id}`, payload);
809
+ }
810
+ async remove(id) {
811
+ if (!id) return {
812
+ data: null,
813
+ headers: null,
814
+ error: {
815
+ message: "Missing `id` field.",
816
+ statusCode: null,
817
+ name: "missing_required_field"
818
+ }
819
+ };
820
+ return await this.resend.delete(`/topics/${id}`);
821
+ }
822
+ };
823
+ //#endregion
824
+ //#region src/webhooks/webhooks.ts
825
+ var Webhooks = class {
826
+ constructor(resend) {
827
+ this.resend = resend;
828
+ }
829
+ async create(payload, options = {}) {
830
+ return await this.resend.post("/webhooks", payload, options);
831
+ }
832
+ async get(id) {
833
+ return await this.resend.get(`/webhooks/${id}`);
834
+ }
835
+ async list(options = {}) {
836
+ const queryString = buildPaginationQuery(options);
837
+ const url = queryString ? `/webhooks?${queryString}` : "/webhooks";
838
+ return await this.resend.get(url);
839
+ }
840
+ async update(id, payload) {
841
+ return await this.resend.patch(`/webhooks/${id}`, payload);
842
+ }
843
+ async remove(id) {
844
+ return await this.resend.delete(`/webhooks/${id}`);
845
+ }
846
+ verify(payload) {
847
+ return new Webhook(payload.webhookSecret).verify(payload.payload, {
848
+ "svix-id": payload.headers.id,
849
+ "svix-timestamp": payload.headers.timestamp,
850
+ "svix-signature": payload.headers.signature
851
+ });
852
+ }
853
+ };
854
+ //#endregion
855
+ //#region src/resend.ts
856
+ const defaultBaseUrl = "https://api.resend.com";
857
+ const defaultUserAgent = `resend-node:${version}`;
858
+ const baseUrl = typeof process !== "undefined" && process.env ? process.env.RESEND_BASE_URL || defaultBaseUrl : defaultBaseUrl;
859
+ const userAgent = typeof process !== "undefined" && process.env ? process.env.RESEND_USER_AGENT || defaultUserAgent : defaultUserAgent;
860
+ var Resend = class {
861
+ constructor(key) {
862
+ this.key = key;
863
+ this.apiKeys = new ApiKeys(this);
864
+ this.segments = new Segments(this);
865
+ this.audiences = this.segments;
866
+ this.batch = new Batch(this);
867
+ this.broadcasts = new Broadcasts(this);
868
+ this.contacts = new Contacts(this);
869
+ this.contactProperties = new ContactProperties(this);
870
+ this.domains = new Domains(this);
871
+ this.emails = new Emails(this);
872
+ this.webhooks = new Webhooks(this);
873
+ this.templates = new Templates(this);
874
+ this.topics = new Topics(this);
875
+ if (!key) {
876
+ if (typeof process !== "undefined" && process.env) this.key = process.env.RESEND_API_KEY;
877
+ if (!this.key) throw new Error("Missing API key. Pass it to the constructor `new Resend(\"re_123\")`");
878
+ }
879
+ this.headers = new Headers({
880
+ Authorization: `Bearer ${this.key}`,
881
+ "User-Agent": userAgent,
882
+ "Content-Type": "application/json"
883
+ });
884
+ }
885
+ async fetchRequest(path, options = {}) {
886
+ try {
887
+ const response = await fetch(`${baseUrl}${path}`, options);
888
+ if (!response.ok) try {
889
+ const rawError = await response.text();
890
+ return {
891
+ data: null,
892
+ error: JSON.parse(rawError),
893
+ headers: Object.fromEntries(response.headers.entries())
894
+ };
895
+ } catch (err) {
896
+ if (err instanceof SyntaxError) return {
897
+ data: null,
898
+ error: {
899
+ name: "application_error",
900
+ statusCode: response.status,
901
+ message: "Internal server error. We are unable to process your request right now, please try again later."
902
+ },
903
+ headers: Object.fromEntries(response.headers.entries())
904
+ };
905
+ const error = {
906
+ message: response.statusText,
907
+ statusCode: response.status,
908
+ name: "application_error"
909
+ };
910
+ if (err instanceof Error) return {
911
+ data: null,
912
+ error: {
913
+ ...error,
914
+ message: err.message
915
+ },
916
+ headers: Object.fromEntries(response.headers.entries())
917
+ };
918
+ return {
919
+ data: null,
920
+ error,
921
+ headers: Object.fromEntries(response.headers.entries())
922
+ };
923
+ }
924
+ return {
925
+ data: await response.json(),
926
+ error: null,
927
+ headers: Object.fromEntries(response.headers.entries())
928
+ };
929
+ } catch {
930
+ return {
931
+ data: null,
932
+ error: {
933
+ name: "application_error",
934
+ statusCode: null,
935
+ message: "Unable to fetch data. The request could not be resolved."
936
+ },
937
+ headers: null
938
+ };
939
+ }
940
+ }
941
+ async post(path, entity, options = {}) {
942
+ const headers = new Headers(this.headers);
943
+ if (options.headers) for (const [key, value] of new Headers(options.headers).entries()) headers.set(key, value);
944
+ if (options.idempotencyKey) headers.set("Idempotency-Key", options.idempotencyKey);
945
+ const requestOptions = {
946
+ method: "POST",
947
+ body: JSON.stringify(entity),
948
+ ...options,
949
+ headers
950
+ };
951
+ return this.fetchRequest(path, requestOptions);
952
+ }
953
+ async get(path, options = {}) {
954
+ const headers = new Headers(this.headers);
955
+ if (options.headers) for (const [key, value] of new Headers(options.headers).entries()) headers.set(key, value);
956
+ const requestOptions = {
957
+ method: "GET",
958
+ ...options,
959
+ headers
960
+ };
961
+ return this.fetchRequest(path, requestOptions);
962
+ }
963
+ async put(path, entity, options = {}) {
964
+ const headers = new Headers(this.headers);
965
+ if (options.headers) for (const [key, value] of new Headers(options.headers).entries()) headers.set(key, value);
966
+ const requestOptions = {
967
+ method: "PUT",
968
+ body: JSON.stringify(entity),
969
+ ...options,
970
+ headers
971
+ };
972
+ return this.fetchRequest(path, requestOptions);
973
+ }
974
+ async patch(path, entity, options = {}) {
975
+ const headers = new Headers(this.headers);
976
+ if (options.headers) for (const [key, value] of new Headers(options.headers).entries()) headers.set(key, value);
977
+ const requestOptions = {
978
+ method: "PATCH",
979
+ body: JSON.stringify(entity),
980
+ ...options,
981
+ headers
982
+ };
983
+ return this.fetchRequest(path, requestOptions);
984
+ }
985
+ async delete(path, query) {
986
+ const requestOptions = {
987
+ method: "DELETE",
988
+ body: JSON.stringify(query),
989
+ headers: this.headers
990
+ };
991
+ return this.fetchRequest(path, requestOptions);
992
+ }
993
+ };
994
+ //#endregion
995
+ export { Resend };