@eusend_dev/sdk 0.9.3 → 0.11.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/README.md +2 -2
- package/dist/index.cjs +8 -2
- package/dist/index.d.cts +53 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +53 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +8 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,8 +58,8 @@ console.log(data?.id) // 9a8b7c6d-5e4f-4a3b-8c1d-0e9f8a7b6c5d (UUID)
|
|
|
58
58
|
| `templateId` | `string` | ID of a saved template |
|
|
59
59
|
| `variables` | `Record<string, unknown>` | Template variable substitutions |
|
|
60
60
|
| `headers` | `Record<string, string>` | Custom email headers, written into the outbound message. Header names and values may not contain line breaks. |
|
|
61
|
-
| `trackOpens` | `boolean` | Track open events
|
|
62
|
-
| `trackClicks` | `boolean` | Track click events
|
|
61
|
+
| `trackOpens` | `boolean` | Track open events. Omit to use your organization default |
|
|
62
|
+
| `trackClicks` | `boolean` | Track click events. Omit to use your organization default |
|
|
63
63
|
|
|
64
64
|
At least one of `html`, `react`, `text`, or `templateId` is required.
|
|
65
65
|
|
package/dist/index.cjs
CHANGED
|
@@ -45,6 +45,7 @@ async function toApiPayload(options) {
|
|
|
45
45
|
template_id: options.templateId,
|
|
46
46
|
variables: options.variables,
|
|
47
47
|
headers: options.headers,
|
|
48
|
+
tags: options.tags,
|
|
48
49
|
track_opens: options.trackOpens,
|
|
49
50
|
track_clicks: options.trackClicks,
|
|
50
51
|
attachments: options.attachments?.map((a) => ({
|
|
@@ -74,6 +75,7 @@ var Emails = class {
|
|
|
74
75
|
if (options.status) params.set("status", options.status);
|
|
75
76
|
if (options.from) params.set("from", options.from);
|
|
76
77
|
if (options.to) params.set("to", options.to);
|
|
78
|
+
for (const tag of options.tag == null ? [] : [options.tag].flat()) params.append("tag", tag);
|
|
77
79
|
const qs = params.toString();
|
|
78
80
|
const res = await this.client.get(qs ? `/emails?${qs}` : "/emails");
|
|
79
81
|
if (res.error) return res;
|
|
@@ -357,7 +359,9 @@ var Broadcasts = class {
|
|
|
357
359
|
subject: options.subject,
|
|
358
360
|
html,
|
|
359
361
|
template_id: options.templateId,
|
|
360
|
-
template_variables: options.templateVariables
|
|
362
|
+
template_variables: options.templateVariables,
|
|
363
|
+
track_opens: options.trackOpens,
|
|
364
|
+
track_clicks: options.trackClicks
|
|
361
365
|
});
|
|
362
366
|
}
|
|
363
367
|
async list() {
|
|
@@ -382,7 +386,9 @@ var Broadcasts = class {
|
|
|
382
386
|
html,
|
|
383
387
|
template_id: options.templateId,
|
|
384
388
|
template_variables: options.templateVariables,
|
|
385
|
-
scheduled_at: options.scheduledAt
|
|
389
|
+
scheduled_at: options.scheduledAt,
|
|
390
|
+
track_opens: options.trackOpens,
|
|
391
|
+
track_clicks: options.trackClicks
|
|
386
392
|
});
|
|
387
393
|
}
|
|
388
394
|
async send(id, options = {}) {
|
package/dist/index.d.cts
CHANGED
|
@@ -48,6 +48,22 @@ interface Attachment {
|
|
|
48
48
|
*/
|
|
49
49
|
contentId?: string;
|
|
50
50
|
}
|
|
51
|
+
/** A single tag in the `[{ name, value }]` form, for Resend-compatible payloads. */
|
|
52
|
+
interface EmailTag {
|
|
53
|
+
name: string;
|
|
54
|
+
value: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Labels attached to a send, used to filter your email log and to route webhook events.
|
|
58
|
+
*
|
|
59
|
+
* Accepts either a plain object (`{ category: 'password_reset' }`) or the
|
|
60
|
+
* `[{ name, value }]` array form, so a payload written against Resend works unchanged.
|
|
61
|
+
* Responses and webhook payloads always return the object form.
|
|
62
|
+
*
|
|
63
|
+
* Names and values may contain ASCII letters, numbers, underscores and dashes; up to 10
|
|
64
|
+
* tags per email.
|
|
65
|
+
*/
|
|
66
|
+
type EmailTags = Record<string, string> | EmailTag[];
|
|
51
67
|
interface SendEmailOptions {
|
|
52
68
|
/**
|
|
53
69
|
* Sender address. Accepts a bare email (`onboarding@eusend.dev`) or a display-name
|
|
@@ -70,6 +86,12 @@ interface SendEmailOptions {
|
|
|
70
86
|
templateId?: string;
|
|
71
87
|
variables?: Record<string, unknown>;
|
|
72
88
|
headers?: Record<string, string>;
|
|
89
|
+
/**
|
|
90
|
+
* Labels for log filtering and webhook routing, e.g.
|
|
91
|
+
* `{ category: 'password_reset', tier: 'pro' }`. Returned on every `email.*` webhook
|
|
92
|
+
* event for this send.
|
|
93
|
+
*/
|
|
94
|
+
tags?: EmailTags;
|
|
73
95
|
trackOpens?: boolean;
|
|
74
96
|
trackClicks?: boolean;
|
|
75
97
|
/** File attachments. Up to 20 per message, 10 MB combined. */
|
|
@@ -126,6 +148,8 @@ interface Email {
|
|
|
126
148
|
html: string | null;
|
|
127
149
|
text: string | null;
|
|
128
150
|
status: EmailStatus;
|
|
151
|
+
/** Always the object form, `{}` when the send carried no tags. */
|
|
152
|
+
tags: Record<string, string>;
|
|
129
153
|
testMode: boolean;
|
|
130
154
|
templateId: string | null;
|
|
131
155
|
/** Set only for scheduled sends. */
|
|
@@ -153,6 +177,8 @@ interface EmailListItem {
|
|
|
153
177
|
to: string[];
|
|
154
178
|
subject: string;
|
|
155
179
|
status: EmailStatus;
|
|
180
|
+
/** Always the object form, `{}` when the send carried no tags. */
|
|
181
|
+
tags: Record<string, string>;
|
|
156
182
|
testMode: boolean;
|
|
157
183
|
createdAt: string;
|
|
158
184
|
}
|
|
@@ -162,6 +188,11 @@ interface ListEmailsOptions {
|
|
|
162
188
|
status?: EmailStatus;
|
|
163
189
|
from?: string;
|
|
164
190
|
to?: string;
|
|
191
|
+
/**
|
|
192
|
+
* Filter by tag. `'category:password_reset'` matches that exact pair; a bare
|
|
193
|
+
* `'category'` matches any email carrying the tag. Pass an array to require several.
|
|
194
|
+
*/
|
|
195
|
+
tag?: string | string[];
|
|
165
196
|
}
|
|
166
197
|
interface ListEmailsResponse {
|
|
167
198
|
data: EmailListItem[];
|
|
@@ -487,6 +518,16 @@ interface CreateBroadcastOptions {
|
|
|
487
518
|
react?: ReactEmailElement;
|
|
488
519
|
templateId?: string;
|
|
489
520
|
templateVariables?: Record<string, string>;
|
|
521
|
+
/**
|
|
522
|
+
* Embed the open-tracking pixel for this broadcast. Omit to use your organization's
|
|
523
|
+
* default (Settings → General → Email tracking); `false` always wins over it.
|
|
524
|
+
*/
|
|
525
|
+
trackOpens?: boolean;
|
|
526
|
+
/**
|
|
527
|
+
* Rewrite links so clicks are recorded. Omit to use your organization's default;
|
|
528
|
+
* `false` leaves the original URLs untouched in the delivered mail.
|
|
529
|
+
*/
|
|
530
|
+
trackClicks?: boolean;
|
|
490
531
|
}
|
|
491
532
|
interface UpdateBroadcastOptions {
|
|
492
533
|
name?: string;
|
|
@@ -501,6 +542,16 @@ interface UpdateBroadcastOptions {
|
|
|
501
542
|
templateId?: string | null;
|
|
502
543
|
templateVariables?: Record<string, string> | null;
|
|
503
544
|
scheduledAt?: string | null;
|
|
545
|
+
/**
|
|
546
|
+
* Embed the open-tracking pixel for this broadcast. Omit to use your organization's
|
|
547
|
+
* default (Settings → General → Email tracking); `false` always wins over it.
|
|
548
|
+
*/
|
|
549
|
+
trackOpens?: boolean;
|
|
550
|
+
/**
|
|
551
|
+
* Rewrite links so clicks are recorded. Omit to use your organization's default;
|
|
552
|
+
* `false` leaves the original URLs untouched in the delivered mail.
|
|
553
|
+
*/
|
|
554
|
+
trackClicks?: boolean;
|
|
504
555
|
}
|
|
505
556
|
interface SendBroadcastOptions {
|
|
506
557
|
scheduledAt?: string;
|
|
@@ -516,6 +567,8 @@ interface Broadcast {
|
|
|
516
567
|
templateId: string | null;
|
|
517
568
|
templateVariables: Record<string, string> | null;
|
|
518
569
|
scheduledAt: string | null;
|
|
570
|
+
trackOpens: boolean;
|
|
571
|
+
trackClicks: boolean;
|
|
519
572
|
createdAt: string;
|
|
520
573
|
updatedAt: string;
|
|
521
574
|
}
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/interfaces.ts","../src/react-render.ts","../src/emails.ts","../src/batch.ts","../src/domains.ts","../src/api-keys.ts","../src/audiences.ts","../src/templates.ts","../src/webhooks.ts","../src/broadcasts.ts","../src/suppressions.ts","../src/eusend.ts"],"mappings":";KAAY;UAuBK;EACf;EACA;EACA,MAAM;;KAGI,eAAe;EACrB,MAAM;EAAG;EAAa,SAAS;;EAC/B;EAAY,OAAO;EAAa,SAAS;;;;KC5BnC;WACD;WACA;WACA;;;;KCFC;KAYA;UAQK;;EAEf;;;;;;EAMA,mBAAmB;;;;;;EAMnB;;EAEA;;;;;EAKA
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/interfaces.ts","../src/react-render.ts","../src/emails.ts","../src/batch.ts","../src/domains.ts","../src/api-keys.ts","../src/audiences.ts","../src/templates.ts","../src/webhooks.ts","../src/broadcasts.ts","../src/suppressions.ts","../src/eusend.ts"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -48,6 +48,22 @@ interface Attachment {
|
|
|
48
48
|
*/
|
|
49
49
|
contentId?: string;
|
|
50
50
|
}
|
|
51
|
+
/** A single tag in the `[{ name, value }]` form, for Resend-compatible payloads. */
|
|
52
|
+
interface EmailTag {
|
|
53
|
+
name: string;
|
|
54
|
+
value: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Labels attached to a send, used to filter your email log and to route webhook events.
|
|
58
|
+
*
|
|
59
|
+
* Accepts either a plain object (`{ category: 'password_reset' }`) or the
|
|
60
|
+
* `[{ name, value }]` array form, so a payload written against Resend works unchanged.
|
|
61
|
+
* Responses and webhook payloads always return the object form.
|
|
62
|
+
*
|
|
63
|
+
* Names and values may contain ASCII letters, numbers, underscores and dashes; up to 10
|
|
64
|
+
* tags per email.
|
|
65
|
+
*/
|
|
66
|
+
type EmailTags = Record<string, string> | EmailTag[];
|
|
51
67
|
interface SendEmailOptions {
|
|
52
68
|
/**
|
|
53
69
|
* Sender address. Accepts a bare email (`onboarding@eusend.dev`) or a display-name
|
|
@@ -70,6 +86,12 @@ interface SendEmailOptions {
|
|
|
70
86
|
templateId?: string;
|
|
71
87
|
variables?: Record<string, unknown>;
|
|
72
88
|
headers?: Record<string, string>;
|
|
89
|
+
/**
|
|
90
|
+
* Labels for log filtering and webhook routing, e.g.
|
|
91
|
+
* `{ category: 'password_reset', tier: 'pro' }`. Returned on every `email.*` webhook
|
|
92
|
+
* event for this send.
|
|
93
|
+
*/
|
|
94
|
+
tags?: EmailTags;
|
|
73
95
|
trackOpens?: boolean;
|
|
74
96
|
trackClicks?: boolean;
|
|
75
97
|
/** File attachments. Up to 20 per message, 10 MB combined. */
|
|
@@ -126,6 +148,8 @@ interface Email {
|
|
|
126
148
|
html: string | null;
|
|
127
149
|
text: string | null;
|
|
128
150
|
status: EmailStatus;
|
|
151
|
+
/** Always the object form, `{}` when the send carried no tags. */
|
|
152
|
+
tags: Record<string, string>;
|
|
129
153
|
testMode: boolean;
|
|
130
154
|
templateId: string | null;
|
|
131
155
|
/** Set only for scheduled sends. */
|
|
@@ -153,6 +177,8 @@ interface EmailListItem {
|
|
|
153
177
|
to: string[];
|
|
154
178
|
subject: string;
|
|
155
179
|
status: EmailStatus;
|
|
180
|
+
/** Always the object form, `{}` when the send carried no tags. */
|
|
181
|
+
tags: Record<string, string>;
|
|
156
182
|
testMode: boolean;
|
|
157
183
|
createdAt: string;
|
|
158
184
|
}
|
|
@@ -162,6 +188,11 @@ interface ListEmailsOptions {
|
|
|
162
188
|
status?: EmailStatus;
|
|
163
189
|
from?: string;
|
|
164
190
|
to?: string;
|
|
191
|
+
/**
|
|
192
|
+
* Filter by tag. `'category:password_reset'` matches that exact pair; a bare
|
|
193
|
+
* `'category'` matches any email carrying the tag. Pass an array to require several.
|
|
194
|
+
*/
|
|
195
|
+
tag?: string | string[];
|
|
165
196
|
}
|
|
166
197
|
interface ListEmailsResponse {
|
|
167
198
|
data: EmailListItem[];
|
|
@@ -487,6 +518,16 @@ interface CreateBroadcastOptions {
|
|
|
487
518
|
react?: ReactEmailElement;
|
|
488
519
|
templateId?: string;
|
|
489
520
|
templateVariables?: Record<string, string>;
|
|
521
|
+
/**
|
|
522
|
+
* Embed the open-tracking pixel for this broadcast. Omit to use your organization's
|
|
523
|
+
* default (Settings → General → Email tracking); `false` always wins over it.
|
|
524
|
+
*/
|
|
525
|
+
trackOpens?: boolean;
|
|
526
|
+
/**
|
|
527
|
+
* Rewrite links so clicks are recorded. Omit to use your organization's default;
|
|
528
|
+
* `false` leaves the original URLs untouched in the delivered mail.
|
|
529
|
+
*/
|
|
530
|
+
trackClicks?: boolean;
|
|
490
531
|
}
|
|
491
532
|
interface UpdateBroadcastOptions {
|
|
492
533
|
name?: string;
|
|
@@ -501,6 +542,16 @@ interface UpdateBroadcastOptions {
|
|
|
501
542
|
templateId?: string | null;
|
|
502
543
|
templateVariables?: Record<string, string> | null;
|
|
503
544
|
scheduledAt?: string | null;
|
|
545
|
+
/**
|
|
546
|
+
* Embed the open-tracking pixel for this broadcast. Omit to use your organization's
|
|
547
|
+
* default (Settings → General → Email tracking); `false` always wins over it.
|
|
548
|
+
*/
|
|
549
|
+
trackOpens?: boolean;
|
|
550
|
+
/**
|
|
551
|
+
* Rewrite links so clicks are recorded. Omit to use your organization's default;
|
|
552
|
+
* `false` leaves the original URLs untouched in the delivered mail.
|
|
553
|
+
*/
|
|
554
|
+
trackClicks?: boolean;
|
|
504
555
|
}
|
|
505
556
|
interface SendBroadcastOptions {
|
|
506
557
|
scheduledAt?: string;
|
|
@@ -516,6 +567,8 @@ interface Broadcast {
|
|
|
516
567
|
templateId: string | null;
|
|
517
568
|
templateVariables: Record<string, string> | null;
|
|
518
569
|
scheduledAt: string | null;
|
|
570
|
+
trackOpens: boolean;
|
|
571
|
+
trackClicks: boolean;
|
|
519
572
|
createdAt: string;
|
|
520
573
|
updatedAt: string;
|
|
521
574
|
}
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/interfaces.ts","../src/react-render.ts","../src/emails.ts","../src/batch.ts","../src/domains.ts","../src/api-keys.ts","../src/audiences.ts","../src/templates.ts","../src/webhooks.ts","../src/broadcasts.ts","../src/suppressions.ts","../src/eusend.ts"],"mappings":";KAAY;UAuBK;EACf;EACA;EACA,MAAM;;KAGI,eAAe;EACrB,MAAM;EAAG;EAAa,SAAS;;EAC/B;EAAY,OAAO;EAAa,SAAS;;;;KC5BnC;WACD;WACA;WACA;;;;KCFC;KAYA;UAQK;;EAEf;;;;;;EAMA,mBAAmB;;;;;;EAMnB;;EAEA;;;;;EAKA
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/interfaces.ts","../src/react-render.ts","../src/emails.ts","../src/batch.ts","../src/domains.ts","../src/api-keys.ts","../src/audiences.ts","../src/templates.ts","../src/webhooks.ts","../src/broadcasts.ts","../src/suppressions.ts","../src/eusend.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -44,6 +44,7 @@ async function toApiPayload(options) {
|
|
|
44
44
|
template_id: options.templateId,
|
|
45
45
|
variables: options.variables,
|
|
46
46
|
headers: options.headers,
|
|
47
|
+
tags: options.tags,
|
|
47
48
|
track_opens: options.trackOpens,
|
|
48
49
|
track_clicks: options.trackClicks,
|
|
49
50
|
attachments: options.attachments?.map((a) => ({
|
|
@@ -73,6 +74,7 @@ var Emails = class {
|
|
|
73
74
|
if (options.status) params.set("status", options.status);
|
|
74
75
|
if (options.from) params.set("from", options.from);
|
|
75
76
|
if (options.to) params.set("to", options.to);
|
|
77
|
+
for (const tag of options.tag == null ? [] : [options.tag].flat()) params.append("tag", tag);
|
|
76
78
|
const qs = params.toString();
|
|
77
79
|
const res = await this.client.get(qs ? `/emails?${qs}` : "/emails");
|
|
78
80
|
if (res.error) return res;
|
|
@@ -356,7 +358,9 @@ var Broadcasts = class {
|
|
|
356
358
|
subject: options.subject,
|
|
357
359
|
html,
|
|
358
360
|
template_id: options.templateId,
|
|
359
|
-
template_variables: options.templateVariables
|
|
361
|
+
template_variables: options.templateVariables,
|
|
362
|
+
track_opens: options.trackOpens,
|
|
363
|
+
track_clicks: options.trackClicks
|
|
360
364
|
});
|
|
361
365
|
}
|
|
362
366
|
async list() {
|
|
@@ -381,7 +385,9 @@ var Broadcasts = class {
|
|
|
381
385
|
html,
|
|
382
386
|
template_id: options.templateId,
|
|
383
387
|
template_variables: options.templateVariables,
|
|
384
|
-
scheduled_at: options.scheduledAt
|
|
388
|
+
scheduled_at: options.scheduledAt,
|
|
389
|
+
track_opens: options.trackOpens,
|
|
390
|
+
track_clicks: options.trackClicks
|
|
385
391
|
});
|
|
386
392
|
}
|
|
387
393
|
async send(id, options = {}) {
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/react-render.ts","../src/emails.ts","../src/batch.ts","../src/domains.ts","../src/api-keys.ts","../src/audiences.ts","../src/templates.ts","../src/webhooks.ts","../src/broadcasts.ts","../src/suppressions.ts","../src/eusend.ts"],"sourcesContent":["// Minimal structural type so the SDK doesn't take a hard dependency on `react`.\n// Real React elements assignable to this; users who pass `react:` are expected to\n// have `react` and `@react-email/render` installed (declared as optional peers).\nexport type ReactEmailElement = {\n readonly type: unknown;\n readonly props: unknown;\n readonly key: string | number | null;\n};\n\nlet renderPromise: Promise<(element: ReactEmailElement) => Promise<string>> | null = null;\n\nasync function getRender(): Promise<(element: ReactEmailElement) => Promise<string>> {\n if (!renderPromise) {\n renderPromise = (async () => {\n try {\n const mod = (await import('@react-email/render')) as {\n render: (element: unknown, options?: { plainText?: boolean }) => Promise<string> | string;\n };\n return (element: ReactEmailElement) => Promise.resolve(mod.render(element));\n } catch {\n throw new Error(\n \"Passing `react:` requires `@react-email/render` and `react` to be installed. \" +\n 'Run: npm install @react-email/render react',\n );\n }\n })();\n }\n return renderPromise;\n}\n\nexport async function renderReactEmail(element: ReactEmailElement): Promise<string> {\n const render = await getRender();\n return render(element);\n}\n","import type { Eusend } from './eusend';\nimport type { EusendErrorCode, EusendResponse } from './interfaces';\nimport { renderReactEmail, type ReactEmailElement } from './react-render';\n\nexport type EmailStatus =\n | 'queued'\n | 'scheduled'\n | 'canceled'\n | 'sending'\n | 'sent'\n | 'delivered'\n | 'bounced'\n | 'complained'\n | 'suppressed'\n | 'failed';\n\nexport type EmailEventType =\n | 'sent'\n | 'delivered'\n | 'opened'\n | 'clicked'\n | 'bounced'\n | 'complained';\n\nexport interface Attachment {\n /** Name the recipient sees for the file, e.g. `invoice.pdf`. */\n filename: string;\n /**\n * File contents. A base64-encoded string (sent as-is) or raw bytes\n * (`Uint8Array`/`Buffer`), which the SDK base64-encodes for you. Provide either\n * `content` or `path`, not both.\n */\n content?: string | Uint8Array;\n /**\n * A URL the server fetches at send time to attach the file. Use instead of\n * `content` when the bytes live on a public URL. Provide either `content` or `path`,\n * not both.\n */\n path?: string;\n /** MIME type, e.g. `application/pdf`. Inferred from the filename when omitted. */\n contentType?: string;\n /**\n * Content-ID for an inline attachment. Set it to reference the file from your\n * HTML with `<img src=\"cid:<contentId>\">` instead of showing it as a download.\n */\n contentId?: string;\n}\n\nexport interface SendEmailOptions {\n /**\n * Sender address. Accepts a bare email (`onboarding@eusend.dev`) or a display-name\n * form (`Acme <onboarding@eusend.dev>`). The domain must be verified on your account.\n */\n from: string;\n to: string | string[];\n cc?: string | string[];\n bcc?: string | string[];\n replyTo?: string | string[];\n subject?: string;\n html?: string;\n text?: string;\n /**\n * A React Email component. The SDK renders it to HTML locally before sending\n * — the JSX source never travels over the wire. Requires `@react-email/render`\n * and `react` as peer dependencies. Ignored when `html` is also provided.\n */\n react?: ReactEmailElement;\n templateId?: string;\n variables?: Record<string, unknown>;\n headers?: Record<string, string>;\n trackOpens?: boolean;\n trackClicks?: boolean;\n /** File attachments. Up to 20 per message, 10 MB combined. */\n attachments?: Attachment[];\n /**\n * Schedule the send for a future time, at most 30 days out. Accepts a `Date`, an\n * ISO 8601 string, or a natural-language time like `\"in 1 hour\"` or `\"tomorrow at\n * 9am\"` (parsed server-side, same as Resend). Relative phrasings resolve against the\n * server clock in UTC — pass an offset-qualified ISO string when you need an exact\n * instant. The email is created with status `scheduled`; reschedule it with\n * `emails.update()` or call `emails.cancel()` any time before it sends.\n */\n scheduledAt?: string | Date;\n}\n\nexport interface SendEmailRequestOptions {\n idempotencyKey?: string;\n}\n\nexport interface SendEmailResponse {\n id: string;\n}\n\n/**\n * Per-item outcome of a batch send, positionally mapped to the input array:\n * `data[i]` describes `emails[i]`. Items that were queued carry `{ id }`; items\n * that could not be queued carry `{ error, code }` (e.g. an unverified sender\n * domain, all recipients suppressed, or an exhausted send quota). Branch on the\n * presence of `id`.\n */\nexport type BatchItemResult =\n | { id: string; error?: never; code?: never }\n | { id?: never; error: string; code: EusendErrorCode };\n\nexport interface BatchSendResponse {\n data: BatchItemResult[];\n}\n\nexport interface EmailEvent {\n id: string;\n type: EmailEventType;\n metadata: Record<string, unknown>;\n createdAt: string;\n}\n\nexport interface Email {\n id: string;\n from: string;\n to: string[];\n cc: string[];\n bcc: string[];\n replyTo: string[];\n subject: string;\n html: string | null;\n text: string | null;\n status: EmailStatus;\n testMode: boolean;\n templateId: string | null;\n /** Set only for scheduled sends. */\n scheduledAt: string | null;\n createdAt: string;\n events: EmailEvent[];\n}\n\nexport interface UpdateEmailOptions {\n /** The new send time, at most 30 days out — a `Date`, an ISO 8601 string, or natural\n * language like `\"in 1 hour\"` (parsed server-side, same as `emails.send`). */\n scheduledAt: string | Date;\n}\n\nexport interface UpdateEmailResponse {\n id: string;\n status: 'scheduled';\n scheduledAt: string;\n}\n\nexport interface CancelEmailResponse {\n id: string;\n status: 'canceled';\n}\n\nexport interface EmailListItem {\n id: string;\n from: string;\n to: string[];\n subject: string;\n status: EmailStatus;\n testMode: boolean;\n createdAt: string;\n}\n\nexport interface ListEmailsOptions {\n limit?: number;\n cursor?: string;\n status?: EmailStatus;\n from?: string;\n to?: string;\n}\n\nexport interface ListEmailsResponse {\n data: EmailListItem[];\n nextCursor: string | null;\n}\n\nasync function resolveHtml(options: SendEmailOptions): Promise<string | undefined> {\n if (options.html) return options.html;\n if (options.react) return renderReactEmail(options.react);\n return undefined;\n}\n\nfunction encodeAttachmentContent(content: string | Uint8Array): string {\n // A string is assumed to already be base64. Raw bytes are encoded here.\n if (typeof content === 'string') return content;\n if (typeof Buffer !== 'undefined') return Buffer.from(content).toString('base64');\n let binary = '';\n for (const byte of content) binary += String.fromCharCode(byte);\n return btoa(binary);\n}\n\nfunction toIsoString(value: string | Date): string {\n return value instanceof Date ? value.toISOString() : value;\n}\n\nexport async function toApiPayload(options: SendEmailOptions) {\n const html = await resolveHtml(options);\n return {\n from: options.from,\n to: options.to,\n cc: options.cc,\n bcc: options.bcc,\n reply_to: options.replyTo,\n subject: options.subject,\n html,\n text: options.text,\n template_id: options.templateId,\n variables: options.variables,\n headers: options.headers,\n track_opens: options.trackOpens,\n track_clicks: options.trackClicks,\n attachments: options.attachments?.map((a) => ({\n filename: a.filename,\n content: a.content === undefined ? undefined : encodeAttachmentContent(a.content),\n path: a.path,\n content_type: a.contentType,\n content_id: a.contentId,\n })),\n scheduled_at: options.scheduledAt ? toIsoString(options.scheduledAt) : undefined,\n };\n}\n\nexport class Emails {\n constructor(private readonly client: Eusend) {}\n\n async send(\n options: SendEmailOptions,\n requestOptions?: SendEmailRequestOptions,\n ): Promise<EusendResponse<SendEmailResponse>> {\n const extraHeaders: Record<string, string> = {};\n if (requestOptions?.idempotencyKey) {\n extraHeaders['Idempotency-Key'] = requestOptions.idempotencyKey;\n }\n const payload = await toApiPayload(options);\n return this.client.post<SendEmailResponse>('/emails', payload, extraHeaders);\n }\n\n async list(options: ListEmailsOptions = {}): Promise<EusendResponse<ListEmailsResponse>> {\n const params = new URLSearchParams();\n if (options.limit != null) params.set('limit', String(options.limit));\n if (options.cursor) params.set('cursor', options.cursor);\n if (options.status) params.set('status', options.status);\n if (options.from) params.set('from', options.from);\n if (options.to) params.set('to', options.to);\n const qs = params.toString();\n\n const res = await this.client.get<{ data: EmailListItem[]; next_cursor: string | null }>(\n qs ? `/emails?${qs}` : '/emails',\n );\n if (res.error) return res;\n return {\n data: { data: res.data.data, nextCursor: res.data.next_cursor },\n error: null,\n headers: res.headers,\n };\n }\n\n get(id: string): Promise<EusendResponse<Email>> {\n return this.client.get<Email>(`/emails/${id}`);\n }\n\n /** Reschedule a scheduled email. Fails once the email has started sending. */\n async update(\n id: string,\n options: UpdateEmailOptions,\n ): Promise<EusendResponse<UpdateEmailResponse>> {\n const res = await this.client.patch<{ id: string; status: 'scheduled'; scheduled_at: string }>(\n `/emails/${id}`,\n { scheduled_at: toIsoString(options.scheduledAt) },\n );\n if (res.error) return res;\n return {\n data: { id: res.data.id, status: res.data.status, scheduledAt: res.data.scheduled_at },\n error: null,\n headers: res.headers,\n };\n }\n\n /** Cancel a scheduled email. Fails once the email has started sending. */\n cancel(id: string): Promise<EusendResponse<CancelEmailResponse>> {\n return this.client.post<CancelEmailResponse>(`/emails/${id}/cancel`, undefined);\n }\n}\n","import type { Eusend } from './eusend';\nimport type { EusendResponse } from './interfaces';\nimport { toApiPayload, type SendEmailOptions, type BatchSendResponse } from './emails';\n\n/**\n * Batch sending — `eusend.batch.send([...])`. The method path mirrors Resend's\n * `resend.batch.send([...])`, so migrating is a mechanical `resend` → `eusend` rename.\n * The HTTP body is a top-level array of email objects (POST /emails/batch), up to 100\n * per request. As with Resend, attachments and `scheduledAt` are not supported on the\n * batch endpoint — send those individually via `emails.send`.\n *\n * The response maps positionally to the input: `data[i]` is `{ id }` when\n * `emails[i]` was queued, or `{ error, code }` when it was not (unverified\n * domain, suppressed recipients, exhausted quota, …) — failed items never fail\n * the whole batch, so branch on the presence of `id` per item.\n */\nexport class Batch {\n constructor(private readonly client: Eusend) {}\n\n async send(emails: SendEmailOptions[]): Promise<EusendResponse<BatchSendResponse>> {\n const payloads = await Promise.all(emails.map(toApiPayload));\n return this.client.post<BatchSendResponse>('/emails/batch', payloads);\n }\n}\n","import type { Eusend } from './eusend';\nimport type { EusendResponse } from './interfaces';\n\nexport type DomainStatus = 'pending' | 'verified' | 'failed';\n\nexport interface DnsRecord {\n type: string;\n name: string;\n value: string;\n /** MX records only. */\n priority?: number;\n /**\n * `authentication` — required before the domain can send.\n * `policy` — recommended; absence weakens but does not block.\n * `alignment` — optional; publishing all of them enables Return-Path SPF alignment.\n */\n purpose?: string;\n description?: string;\n}\n\nexport interface CreateDomainResponse {\n id: string;\n name: string;\n /**\n * Every record to publish, in presentation order. Prefer this over the individual\n * keys below — it is the only place the optional Return-Path alignment records appear.\n */\n records: DnsRecord[];\n dkim: DnsRecord;\n dmarc: DnsRecord;\n}\n\nexport interface DomainListItem {\n id: string;\n name: string;\n status: DomainStatus;\n createdAt: string;\n}\n\nexport interface Domain {\n id: string;\n name: string;\n dkimPublicKey: string;\n dkimSelector: string;\n status: DomainStatus;\n createdAt: string;\n verifiedAt: string | null;\n}\n\nexport class Domains {\n constructor(private readonly client: Eusend) {}\n\n create(name: string): Promise<EusendResponse<CreateDomainResponse>> {\n return this.client.post<CreateDomainResponse>('/domains', { name });\n }\n\n list(): Promise<EusendResponse<DomainListItem[]>> {\n return this.client.get<DomainListItem[]>('/domains');\n }\n\n get(id: string): Promise<EusendResponse<Domain>> {\n return this.client.get<Domain>(`/domains/${id}`);\n }\n\n delete(id: string): Promise<EusendResponse<{ message: string }>> {\n return this.client.delete<{ message: string }>(`/domains/${id}`);\n }\n\n verify(id: string): Promise<EusendResponse<{ message: string }>> {\n return this.client.post<{ message: string }>(`/domains/${id}/verify`);\n }\n}\n","import type { Eusend } from './eusend';\nimport type { EusendResponse } from './interfaces';\n\n/**\n * What a key may reach. `full_access` is every resource; `sending_access` is limited to\n * sending email (and rescheduling or canceling a scheduled send).\n */\nexport type ApiKeyPermission = 'full_access' | 'sending_access';\n\nexport interface CreateApiKeyOptions {\n name: string;\n testMode?: boolean;\n /** Defaults to `full_access`. */\n permission?: ApiKeyPermission;\n /**\n * Restrict the key to sending from a single domain. Only valid together with\n * `permission: 'sending_access'`; omit for any verified domain.\n */\n domainId?: string;\n}\n\nexport interface CreateApiKeyResponse {\n id: string;\n name: string;\n key: string;\n prefix: string;\n testMode: boolean;\n permission: ApiKeyPermission;\n domainId: string | null;\n domainName: string | null;\n createdAt: string;\n}\n\nexport interface ApiKey {\n id: string;\n name: string;\n prefix: string;\n testMode: boolean;\n permission: ApiKeyPermission;\n domainId: string | null;\n domainName: string | null;\n createdAt: string;\n lastUsedAt: string | null;\n}\n\ntype CreateApiKeyApiResponse = {\n id: string;\n name: string;\n key: string;\n prefix: string;\n test_mode: boolean;\n permission: ApiKeyPermission;\n domain_id: string | null;\n domain_name: string | null;\n created_at: string;\n};\n\nexport class ApiKeys {\n constructor(private readonly client: Eusend) {}\n\n async create(options: CreateApiKeyOptions): Promise<EusendResponse<CreateApiKeyResponse>> {\n const res = await this.client.post<CreateApiKeyApiResponse>('/api-keys', {\n name: options.name,\n test_mode: options.testMode ?? false,\n permission: options.permission ?? 'full_access',\n ...(options.domainId ? { domain_id: options.domainId } : {}),\n });\n if (res.error) return res;\n return {\n data: {\n id: res.data.id,\n name: res.data.name,\n key: res.data.key,\n prefix: res.data.prefix,\n testMode: res.data.test_mode,\n permission: res.data.permission,\n domainId: res.data.domain_id,\n domainName: res.data.domain_name,\n createdAt: res.data.created_at,\n },\n error: null,\n headers: res.headers,\n };\n }\n\n list(): Promise<EusendResponse<ApiKey[]>> {\n return this.client.get<ApiKey[]>('/api-keys');\n }\n\n delete(id: string): Promise<EusendResponse<{ message: string }>> {\n return this.client.delete<{ message: string }>(`/api-keys/${id}`);\n }\n}\n","import type { Eusend } from './eusend';\nimport type { EusendResponse } from './interfaces';\n\nexport type ContactStatus = 'subscribed' | 'unsubscribed';\n\nexport interface Audience {\n id: string;\n name: string;\n organizationId: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface AudienceListItem {\n id: string;\n name: string;\n createdAt: string;\n contactCount: number;\n}\n\nexport interface Contact {\n id: string;\n audienceId: string;\n email: string;\n firstName: string | null;\n lastName: string | null;\n status: ContactStatus;\n unsubscribedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CreateContactOptions {\n email: string;\n firstName?: string;\n lastName?: string;\n}\n\nexport interface UpdateContactOptions {\n firstName?: string;\n lastName?: string;\n unsubscribed?: boolean;\n}\n\nexport interface ListContactsOptions {\n limit?: number;\n cursor?: string;\n search?: string;\n subscribed?: boolean;\n}\n\nexport interface ListContactsResponse {\n data: Contact[];\n nextCursor: string | null;\n}\n\nexport interface BatchCreateContactsOptions {\n contacts: CreateContactOptions[];\n}\n\nexport class Audiences {\n constructor(private readonly client: Eusend) {}\n\n create(name: string): Promise<EusendResponse<Audience>> {\n return this.client.post<Audience>('/audiences', { name });\n }\n\n async list(): Promise<EusendResponse<AudienceListItem[]>> {\n const res = await this.client.get<{ data: AudienceListItem[] }>('/audiences');\n if (res.error) return res;\n return { data: res.data.data, error: null, headers: res.headers };\n }\n\n delete(id: string): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(`/audiences/${id}`);\n }\n\n createContact(\n audienceId: string,\n options: CreateContactOptions,\n ): Promise<EusendResponse<Contact>> {\n return this.client.post<Contact>(`/audiences/${audienceId}/contacts`, {\n email: options.email,\n first_name: options.firstName,\n last_name: options.lastName,\n });\n }\n\n async listContacts(\n audienceId: string,\n options: ListContactsOptions = {},\n ): Promise<EusendResponse<ListContactsResponse>> {\n const params = new URLSearchParams();\n if (options.limit != null) params.set('limit', String(options.limit));\n if (options.cursor) params.set('cursor', options.cursor);\n if (options.search) params.set('search', options.search);\n if (options.subscribed != null) params.set('subscribed', String(options.subscribed));\n const qs = params.toString();\n return this.client.get<ListContactsResponse>(\n qs ? `/audiences/${audienceId}/contacts?${qs}` : `/audiences/${audienceId}/contacts`,\n );\n }\n\n getContact(audienceId: string, contactId: string): Promise<EusendResponse<Contact>> {\n return this.client.get<Contact>(`/audiences/${audienceId}/contacts/${contactId}`);\n }\n\n updateContact(\n audienceId: string,\n contactId: string,\n options: UpdateContactOptions,\n ): Promise<EusendResponse<Contact>> {\n return this.client.patch<Contact>(`/audiences/${audienceId}/contacts/${contactId}`, {\n first_name: options.firstName,\n last_name: options.lastName,\n unsubscribed: options.unsubscribed,\n });\n }\n\n deleteContact(\n audienceId: string,\n contactId: string,\n ): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(\n `/audiences/${audienceId}/contacts/${contactId}`,\n );\n }\n\n /**\n * Upsert up to 1000 contacts in one call. Addresses are lowercased and\n * de-duplicated server-side; `count` is the number of rows written and\n * `duplicates` how many repeated addresses were collapsed to get there.\n */\n batchCreateContacts(\n audienceId: string,\n options: BatchCreateContactsOptions,\n ): Promise<EusendResponse<{ count: number; duplicates: number }>> {\n return this.client.post<{ count: number; duplicates: number }>(`/audiences/${audienceId}/contacts/batch`, {\n contacts: options.contacts.map((c) => ({\n email: c.email,\n first_name: c.firstName,\n last_name: c.lastName,\n })),\n });\n }\n}\n","import type { Eusend } from './eusend';\nimport type { EusendResponse } from './interfaces';\nimport { renderReactEmail, type ReactEmailElement } from './react-render';\n\ninterface TemplateHtmlOrReact {\n /**\n * A React Email component. The SDK renders it to HTML locally before sending.\n * Requires `@react-email/render` and `react` as peer dependencies.\n * Ignored when `html` is also provided.\n */\n react?: ReactEmailElement;\n}\n\nexport interface CreateTemplateOptions extends TemplateHtmlOrReact {\n name: string;\n subject: string;\n html?: string;\n}\n\nexport interface UpdateTemplateOptions extends TemplateHtmlOrReact {\n name?: string;\n subject?: string;\n html?: string;\n}\n\nexport interface Template {\n id: string;\n name: string;\n subject: string;\n html: string | null;\n reactSource: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface TemplateListItem {\n id: string;\n name: string;\n subject: string;\n createdAt: string;\n updatedAt: string;\n}\n\nasync function resolveTemplateHtml(\n options: TemplateHtmlOrReact & { html?: string },\n): Promise<string | undefined> {\n if (options.html) return options.html;\n if (options.react) return renderReactEmail(options.react);\n return undefined;\n}\n\nexport class Templates {\n constructor(private readonly client: Eusend) {}\n\n async create(options: CreateTemplateOptions): Promise<EusendResponse<Template>> {\n const html = await resolveTemplateHtml(options);\n if (!html) {\n return {\n data: null,\n error: {\n message: 'Either html or react is required',\n statusCode: null,\n name: 'VALIDATION_ERROR',\n },\n headers: null,\n };\n }\n return this.client.post<Template>('/templates', {\n name: options.name,\n subject: options.subject,\n html,\n });\n }\n\n async list(): Promise<EusendResponse<TemplateListItem[]>> {\n const res = await this.client.get<{ data: TemplateListItem[] }>('/templates');\n if (res.error) return res;\n return { data: res.data.data, error: null, headers: res.headers };\n }\n\n get(id: string): Promise<EusendResponse<Template>> {\n return this.client.get<Template>(`/templates/${id}`);\n }\n\n async update(id: string, options: UpdateTemplateOptions): Promise<EusendResponse<Template>> {\n const html = await resolveTemplateHtml(options);\n return this.client.patch<Template>(`/templates/${id}`, {\n name: options.name,\n subject: options.subject,\n html,\n });\n }\n\n delete(id: string): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(`/templates/${id}`);\n }\n}\n","import type { Eusend } from './eusend';\nimport type { EusendResponse } from './interfaces';\n\nexport type WebhookEvent =\n | 'email.sent'\n | 'email.delivered'\n | 'email.bounced'\n | 'email.complained'\n | 'email.opened'\n | 'email.clicked'\n | '*';\n\nexport interface CreateWebhookOptions {\n url: string;\n events: WebhookEvent[];\n}\n\nexport interface UpdateWebhookOptions {\n url?: string;\n events?: WebhookEvent[];\n}\n\nexport interface WebhookDelivery {\n id: string;\n webhookId: string;\n emailId: string | null;\n eventType: string;\n payload: Record<string, unknown>;\n status: 'pending' | 'success' | 'failed';\n responseStatus: number | null;\n attempts: number;\n createdAt: string;\n lastAttemptAt: string | null;\n}\n\nexport interface Webhook {\n id: string;\n url: string;\n events: WebhookEvent[];\n createdAt: string;\n}\n\nexport interface WebhookWithDeliveries extends Webhook {\n deliveries: WebhookDelivery[];\n}\n\nexport interface CreateWebhookResponse extends Webhook {\n secret: string;\n}\n\nexport class Webhooks {\n constructor(private readonly client: Eusend) {}\n\n create(options: CreateWebhookOptions): Promise<EusendResponse<CreateWebhookResponse>> {\n return this.client.post<CreateWebhookResponse>('/webhooks', {\n url: options.url,\n events: options.events,\n });\n }\n\n async list(): Promise<EusendResponse<Webhook[]>> {\n const res = await this.client.get<{ data: Webhook[] }>('/webhooks');\n if (res.error) return res;\n return { data: res.data.data, error: null, headers: res.headers };\n }\n\n get(id: string): Promise<EusendResponse<WebhookWithDeliveries>> {\n return this.client.get<WebhookWithDeliveries>(`/webhooks/${id}`);\n }\n\n update(id: string, options: UpdateWebhookOptions): Promise<EusendResponse<Webhook>> {\n return this.client.patch<Webhook>(`/webhooks/${id}`, {\n url: options.url,\n events: options.events,\n });\n }\n\n delete(id: string): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(`/webhooks/${id}`);\n }\n}\n","import type { Eusend } from './eusend';\nimport type { EusendResponse } from './interfaces';\nimport { renderReactEmail, type ReactEmailElement } from './react-render';\n\n/**\n * `held` is a list send stopped part-way pending review. Unlike `paused` it cannot be\n * resumed by sending again — `send()` returns BROADCAST_HELD until the review clears.\n */\nexport type BroadcastStatus =\n | 'draft'\n | 'scheduled'\n | 'sending'\n | 'sent'\n | 'paused'\n | 'held'\n | 'cancelled';\n\nexport interface CreateBroadcastOptions {\n name: string;\n audienceId: string;\n /**\n * Sender address. Accepts a bare email (`onboarding@eusend.dev`) or a display-name\n * form (`Acme <onboarding@eusend.dev>`). The domain must be verified on your account.\n */\n from: string;\n subject: string;\n html?: string;\n /**\n * A React Email component. The SDK renders it to HTML locally before sending —\n * the JSX source never travels over the wire. Requires `@react-email/render`\n * and `react` as peer dependencies. Ignored when `html` is also provided.\n */\n react?: ReactEmailElement;\n templateId?: string;\n templateVariables?: Record<string, string>;\n}\n\nexport interface UpdateBroadcastOptions {\n name?: string;\n audienceId?: string;\n from?: string;\n subject?: string;\n html?: string;\n /**\n * See `react` on CreateBroadcastOptions. Rendered to HTML locally before sending.\n */\n react?: ReactEmailElement;\n templateId?: string | null;\n templateVariables?: Record<string, string> | null;\n scheduledAt?: string | null;\n}\n\nexport interface SendBroadcastOptions {\n scheduledAt?: string;\n}\n\nexport interface Broadcast {\n id: string;\n name: string;\n status: BroadcastStatus;\n audienceId: string;\n fromAddress: string;\n subject: string;\n html: string | null;\n templateId: string | null;\n templateVariables: Record<string, string> | null;\n scheduledAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface BroadcastListItem {\n id: string;\n name: string;\n status: BroadcastStatus;\n audienceId: string;\n fromAddress: string;\n subject: string;\n recipientCount: number | null;\n sentCount: number | null;\n scheduledAt: string | null;\n startedAt: string | null;\n completedAt: string | null;\n createdAt: string;\n audienceName: string | null;\n}\n\nexport interface BroadcastDetail extends Broadcast {\n recipientCount: number | null;\n sentCount: number | null;\n startedAt: string | null;\n completedAt: string | null;\n stats: Record<string, number>;\n}\n\nexport interface SendBroadcastResponse {\n id: string;\n status: 'sending' | 'scheduled';\n scheduledAt: string | null;\n}\n\nasync function resolveBroadcastHtml(\n options: { html?: string; react?: ReactEmailElement },\n): Promise<string | undefined> {\n if (options.html) return options.html;\n if (options.react) return renderReactEmail(options.react);\n return undefined;\n}\n\nexport class Broadcasts {\n constructor(private readonly client: Eusend) {}\n\n async create(options: CreateBroadcastOptions): Promise<EusendResponse<Broadcast>> {\n const html = await resolveBroadcastHtml(options);\n return this.client.post<Broadcast>('/broadcasts', {\n name: options.name,\n audience_id: options.audienceId,\n from: options.from,\n subject: options.subject,\n html,\n template_id: options.templateId,\n template_variables: options.templateVariables,\n });\n }\n\n async list(): Promise<EusendResponse<BroadcastListItem[]>> {\n const res = await this.client.get<{ data: BroadcastListItem[] }>('/broadcasts');\n if (res.error) return res;\n return { data: res.data.data, error: null, headers: res.headers };\n }\n\n get(id: string): Promise<EusendResponse<BroadcastDetail>> {\n return this.client.get<BroadcastDetail>(`/broadcasts/${id}`);\n }\n\n async update(id: string, options: UpdateBroadcastOptions): Promise<EusendResponse<Broadcast>> {\n const html = await resolveBroadcastHtml(options);\n return this.client.patch<Broadcast>(`/broadcasts/${id}`, {\n name: options.name,\n audience_id: options.audienceId,\n from: options.from,\n subject: options.subject,\n html,\n template_id: options.templateId,\n template_variables: options.templateVariables,\n scheduled_at: options.scheduledAt,\n });\n }\n\n async send(\n id: string,\n options: SendBroadcastOptions = {},\n ): Promise<EusendResponse<SendBroadcastResponse>> {\n // This endpoint is the one broadcast response that comes back snake_cased, so\n // map it rather than exposing a `scheduledAt` that is always undefined.\n const res = await this.client.post<{\n id: string;\n status: 'sending' | 'scheduled';\n scheduled_at: string | null;\n }>(`/broadcasts/${id}/send`, {\n scheduled_at: options.scheduledAt,\n });\n if (res.error) return res;\n return {\n data: { id: res.data.id, status: res.data.status, scheduledAt: res.data.scheduled_at },\n error: null,\n headers: res.headers,\n };\n }\n\n cancel(id: string): Promise<EusendResponse<Broadcast>> {\n return this.client.post<Broadcast>(`/broadcasts/${id}/cancel`);\n }\n\n delete(id: string): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(`/broadcasts/${id}`);\n }\n}\n","import type { Eusend } from './eusend';\nimport type { EusendResponse } from './interfaces';\n\nexport type SuppressionReason = 'bounce' | 'complaint' | 'manual';\n\nexport interface SuppressionEntry {\n id: string;\n email: string;\n reason: SuppressionReason;\n created_at: string;\n}\n\nexport interface ListSuppressionsOptions {\n /** Filter to addresses containing this substring. Pass a domain (\"@acme.com\") to see every suppressed address there. */\n email?: string;\n reason?: SuppressionReason;\n limit?: number;\n cursor?: string;\n}\n\nexport interface ListSuppressionsResponse {\n data: SuppressionEntry[];\n next_cursor: string | null;\n}\n\nexport interface CreateSuppressionOptions {\n email: string;\n /** Defaults to 'manual'. An add never overwrites the reason an address is already suppressed for. */\n reason?: SuppressionReason;\n}\n\n/** An item in an import — a bare address, or an address with the reason it was suppressed. */\nexport type SuppressionImportItem = string | { email: string; reason?: SuppressionReason };\n\nexport interface ImportSuppressionsResponse {\n /** Entries written. */\n count: number;\n /** Entries that were already on the list. */\n already_suppressed: number;\n /** Repeated addresses in the payload, collapsed before the write. */\n duplicates: number;\n}\n\n/**\n * The addresses your organization will not send to.\n *\n * Hard bounces and spam complaints are added automatically; these methods cover the\n * addresses you manage yourself. Suppression applies to live sending only — test-mode\n * keys can read the list but not modify it.\n */\nexport class Suppressions {\n constructor(private readonly client: Eusend) {}\n\n list(options: ListSuppressionsOptions = {}): Promise<EusendResponse<ListSuppressionsResponse>> {\n const params = new URLSearchParams();\n if (options.email) params.set('email', options.email);\n if (options.reason) params.set('reason', options.reason);\n if (options.limit != null) params.set('limit', String(options.limit));\n if (options.cursor) params.set('cursor', options.cursor);\n const qs = params.toString();\n return this.client.get<ListSuppressionsResponse>(\n qs ? `/suppressions?${qs}` : '/suppressions',\n );\n }\n\n /**\n * Suppress an address. If it is already suppressed the existing entry is returned\n * unchanged — a manual add never rewrites a real bounce or complaint.\n */\n create(options: CreateSuppressionOptions): Promise<EusendResponse<SuppressionEntry>> {\n return this.client.post<SuppressionEntry>('/suppressions', {\n email: options.email,\n reason: options.reason,\n });\n }\n\n /**\n * Import up to 1000 addresses in one call — for carrying a suppression list over from\n * another provider before your first send. Items may be bare addresses or objects.\n */\n import(emails: SuppressionImportItem[]): Promise<EusendResponse<ImportSuppressionsResponse>> {\n return this.client.post<ImportSuppressionsResponse>('/suppressions/batch', { emails });\n }\n\n /**\n * Un-suppress by entry id or by address, making the address sendable again.\n *\n * Removing an address that hard-bounced or complained is what damages a sender's\n * reputation when done in bulk — remove an entry when the address was fixed or the\n * complaint was a mistake, not to retry a failing list.\n */\n remove(idOrEmail: string): Promise<EusendResponse<{ deleted: number }>> {\n return this.client.delete<{ deleted: number }>(\n `/suppressions/${encodeURIComponent(idOrEmail)}`,\n );\n }\n\n /** The whole list as CSV (`email,reason,created_at`), for backup or migration. */\n export(): Promise<EusendResponse<string>> {\n return this.client.fetchRequest<string>('/suppressions/export', { method: 'GET' }, {}, 'text');\n }\n}\n","import type { EusendError, EusendResponse } from './interfaces'\nimport { Emails } from './emails'\nimport { Batch } from './batch'\nimport { Domains } from './domains'\nimport { ApiKeys } from './api-keys'\nimport { Audiences } from './audiences'\nimport { Templates } from './templates'\nimport { Webhooks } from './webhooks'\nimport { Broadcasts } from './broadcasts'\nimport { Suppressions } from './suppressions'\n\nconst DEFAULT_BASE_URL = 'https://api.eusend.dev'\nconst SDK_VERSION = '0.8.0'\n\nexport interface EusendOptions {\n baseUrl?: string\n}\n\nexport class Eusend {\n readonly baseUrl: string\n private readonly apiKey: string\n\n readonly emails: Emails\n /** Batch sending — `client.batch.send([...])`. Mirrors Resend's `resend.batch.send()`. */\n readonly batch: Batch\n readonly domains: Domains\n readonly apiKeys: ApiKeys\n readonly audiences: Audiences\n readonly templates: Templates\n readonly webhooks: Webhooks\n readonly broadcasts: Broadcasts\n readonly suppressions: Suppressions\n\n constructor(key?: string, options?: EusendOptions) {\n const apiKey =\n key ?? (typeof process !== 'undefined' ? process.env['EUSEND_API_KEY'] : undefined)\n if (!apiKey) {\n throw new Error(\n 'Missing Eusend API key. Pass it to the constructor or set the EUSEND_API_KEY environment variable.',\n )\n }\n this.apiKey = apiKey\n this.baseUrl = options?.baseUrl ?? DEFAULT_BASE_URL\n\n this.emails = new Emails(this)\n this.batch = new Batch(this)\n this.domains = new Domains(this)\n this.apiKeys = new ApiKeys(this)\n this.audiences = new Audiences(this)\n this.templates = new Templates(this)\n this.webhooks = new Webhooks(this)\n this.broadcasts = new Broadcasts(this)\n this.suppressions = new Suppressions(this)\n }\n\n async fetchRequest<T>(\n path: string,\n init: RequestInit = {},\n extraHeaders: Record<string, string> = {},\n // Not every successful endpoint answers with JSON — the suppression export returns\n // CSV. Parsing that as JSON throws inside the try below, which would surface a\n // perfectly good download as \"Network request failed\".\n parse: 'json' | 'text' = 'json',\n ): Promise<EusendResponse<T>> {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': `eusend-node/${SDK_VERSION}`,\n ...extraHeaders,\n }\n\n try {\n const res = await fetch(`${this.baseUrl}${path}`, { ...init, headers })\n const responseHeaders = Object.fromEntries(res.headers.entries())\n\n if (!res.ok) {\n let error: EusendError\n try {\n const json = (await res.json()) as { error?: string; code?: string }\n error = {\n message: json.error ?? 'Unknown error',\n statusCode: res.status,\n name: (json.code as EusendError['name']) ?? 'INTERNAL_ERROR',\n }\n } catch {\n error = { message: 'Request failed', statusCode: res.status, name: 'INTERNAL_ERROR' }\n }\n return { data: null, error, headers: responseHeaders }\n }\n\n if (res.status === 204 || res.headers.get('content-length') === '0') {\n return { data: {} as T, error: null, headers: responseHeaders }\n }\n\n const data = (parse === 'text' ? await res.text() : await res.json()) as T\n return { data, error: null, headers: responseHeaders }\n } catch {\n return {\n data: null,\n error: {\n message: 'Network request failed. The request could not be resolved.',\n statusCode: null,\n name: 'application_error',\n },\n headers: null,\n }\n }\n }\n\n get<T>(path: string, extraHeaders?: Record<string, string>): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(path, { method: 'GET' }, extraHeaders)\n }\n\n post<T>(\n path: string,\n body?: unknown,\n extraHeaders?: Record<string, string>,\n ): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(\n path,\n { method: 'POST', body: body != null ? JSON.stringify(body) : undefined },\n extraHeaders,\n )\n }\n\n patch<T>(path: string, body?: unknown): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(path, {\n method: 'PATCH',\n body: body != null ? JSON.stringify(body) : undefined,\n })\n }\n\n delete<T>(path: string): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(path, { method: 'DELETE' })\n }\n}\n"],"mappings":";AASA,IAAI,gBAAiF;AAErF,eAAe,YAAsE;CACnF,IAAI,CAAC,eACH,iBAAiB,YAAY;EAC3B,IAAI;GACF,MAAM,MAAO,MAAM,OAAO;GAG1B,QAAQ,YAA+B,QAAQ,QAAQ,IAAI,OAAO,OAAO,CAAC;EAC5E,QAAQ;GACN,MAAM,IAAI,MACR,yHAEF;EACF;CACF,EAAA,CAAG;CAEL,OAAO;AACT;AAEA,eAAsB,iBAAiB,SAA6C;CAElF,QAAO,MADc,UAAU,EAAA,CACjB,OAAO;AACvB;;;AC6IA,eAAe,YAAY,SAAwD;CACjF,IAAI,QAAQ,MAAM,OAAO,QAAQ;CACjC,IAAI,QAAQ,OAAO,OAAO,iBAAiB,QAAQ,KAAK;AAE1D;AAEA,SAAS,wBAAwB,SAAsC;CAErE,IAAI,OAAO,YAAY,UAAU,OAAO;CACxC,IAAI,OAAO,WAAW,aAAa,OAAO,OAAO,KAAK,OAAO,CAAC,CAAC,SAAS,QAAQ;CAChF,IAAI,SAAS;CACb,KAAK,MAAM,QAAQ,SAAS,UAAU,OAAO,aAAa,IAAI;CAC9D,OAAO,KAAK,MAAM;AACpB;AAEA,SAAS,YAAY,OAA8B;CACjD,OAAO,iBAAiB,OAAO,MAAM,YAAY,IAAI;AACvD;AAEA,eAAsB,aAAa,SAA2B;CAC5D,MAAM,OAAO,MAAM,YAAY,OAAO;CACtC,OAAO;EACL,MAAM,QAAQ;EACd,IAAI,QAAQ;EACZ,IAAI,QAAQ;EACZ,KAAK,QAAQ;EACb,UAAU,QAAQ;EAClB,SAAS,QAAQ;EACjB;EACA,MAAM,QAAQ;EACd,aAAa,QAAQ;EACrB,WAAW,QAAQ;EACnB,SAAS,QAAQ;EACjB,aAAa,QAAQ;EACrB,cAAc,QAAQ;EACtB,aAAa,QAAQ,aAAa,KAAK,OAAO;GAC5C,UAAU,EAAE;GACZ,SAAS,EAAE,YAAY,KAAA,IAAY,KAAA,IAAY,wBAAwB,EAAE,OAAO;GAChF,MAAM,EAAE;GACR,cAAc,EAAE;GAChB,YAAY,EAAE;EAChB,EAAE;EACF,cAAc,QAAQ,cAAc,YAAY,QAAQ,WAAW,IAAI,KAAA;CACzE;AACF;AAEA,IAAa,SAAb,MAAoB;CAClB,YAAY,QAAiC;EAAhB,KAAA,SAAA;CAAiB;CAE9C,MAAM,KACJ,SACA,gBAC4C;EAC5C,MAAM,eAAuC,CAAC;EAC9C,IAAI,gBAAgB,gBAClB,aAAa,qBAAqB,eAAe;EAEnD,MAAM,UAAU,MAAM,aAAa,OAAO;EAC1C,OAAO,KAAK,OAAO,KAAwB,WAAW,SAAS,YAAY;CAC7E;CAEA,MAAM,KAAK,UAA6B,CAAC,GAAgD;EACvF,MAAM,SAAS,IAAI,gBAAgB;EACnC,IAAI,QAAQ,SAAS,MAAM,OAAO,IAAI,SAAS,OAAO,QAAQ,KAAK,CAAC;EACpE,IAAI,QAAQ,QAAQ,OAAO,IAAI,UAAU,QAAQ,MAAM;EACvD,IAAI,QAAQ,QAAQ,OAAO,IAAI,UAAU,QAAQ,MAAM;EACvD,IAAI,QAAQ,MAAM,OAAO,IAAI,QAAQ,QAAQ,IAAI;EACjD,IAAI,QAAQ,IAAI,OAAO,IAAI,MAAM,QAAQ,EAAE;EAC3C,MAAM,KAAK,OAAO,SAAS;EAE3B,MAAM,MAAM,MAAM,KAAK,OAAO,IAC5B,KAAK,WAAW,OAAO,SACzB;EACA,IAAI,IAAI,OAAO,OAAO;EACtB,OAAO;GACL,MAAM;IAAE,MAAM,IAAI,KAAK;IAAM,YAAY,IAAI,KAAK;GAAY;GAC9D,OAAO;GACP,SAAS,IAAI;EACf;CACF;CAEA,IAAI,IAA4C;EAC9C,OAAO,KAAK,OAAO,IAAW,WAAW,IAAI;CAC/C;;CAGA,MAAM,OACJ,IACA,SAC8C;EAC9C,MAAM,MAAM,MAAM,KAAK,OAAO,MAC5B,WAAW,MACX,EAAE,cAAc,YAAY,QAAQ,WAAW,EAAE,CACnD;EACA,IAAI,IAAI,OAAO,OAAO;EACtB,OAAO;GACL,MAAM;IAAE,IAAI,IAAI,KAAK;IAAI,QAAQ,IAAI,KAAK;IAAQ,aAAa,IAAI,KAAK;GAAa;GACrF,OAAO;GACP,SAAS,IAAI;EACf;CACF;;CAGA,OAAO,IAA0D;EAC/D,OAAO,KAAK,OAAO,KAA0B,WAAW,GAAG,UAAU,KAAA,CAAS;CAChF;AACF;;;;;;;;;;;;;;;ACxQA,IAAa,QAAb,MAAmB;CACjB,YAAY,QAAiC;EAAhB,KAAA,SAAA;CAAiB;CAE9C,MAAM,KAAK,QAAwE;EACjF,MAAM,WAAW,MAAM,QAAQ,IAAI,OAAO,IAAI,YAAY,CAAC;EAC3D,OAAO,KAAK,OAAO,KAAwB,iBAAiB,QAAQ;CACtE;AACF;;;AC0BA,IAAa,UAAb,MAAqB;CACnB,YAAY,QAAiC;EAAhB,KAAA,SAAA;CAAiB;CAE9C,OAAO,MAA6D;EAClE,OAAO,KAAK,OAAO,KAA2B,YAAY,EAAE,KAAK,CAAC;CACpE;CAEA,OAAkD;EAChD,OAAO,KAAK,OAAO,IAAsB,UAAU;CACrD;CAEA,IAAI,IAA6C;EAC/C,OAAO,KAAK,OAAO,IAAY,YAAY,IAAI;CACjD;CAEA,OAAO,IAA0D;EAC/D,OAAO,KAAK,OAAO,OAA4B,YAAY,IAAI;CACjE;CAEA,OAAO,IAA0D;EAC/D,OAAO,KAAK,OAAO,KAA0B,YAAY,GAAG,QAAQ;CACtE;AACF;;;ACdA,IAAa,UAAb,MAAqB;CACnB,YAAY,QAAiC;EAAhB,KAAA,SAAA;CAAiB;CAE9C,MAAM,OAAO,SAA6E;EACxF,MAAM,MAAM,MAAM,KAAK,OAAO,KAA8B,aAAa;GACvE,MAAM,QAAQ;GACd,WAAW,QAAQ,YAAY;GAC/B,YAAY,QAAQ,cAAc;GAClC,GAAI,QAAQ,WAAW,EAAE,WAAW,QAAQ,SAAS,IAAI,CAAC;EAC5D,CAAC;EACD,IAAI,IAAI,OAAO,OAAO;EACtB,OAAO;GACL,MAAM;IACJ,IAAI,IAAI,KAAK;IACb,MAAM,IAAI,KAAK;IACf,KAAK,IAAI,KAAK;IACd,QAAQ,IAAI,KAAK;IACjB,UAAU,IAAI,KAAK;IACnB,YAAY,IAAI,KAAK;IACrB,UAAU,IAAI,KAAK;IACnB,YAAY,IAAI,KAAK;IACrB,WAAW,IAAI,KAAK;GACtB;GACA,OAAO;GACP,SAAS,IAAI;EACf;CACF;CAEA,OAA0C;EACxC,OAAO,KAAK,OAAO,IAAc,WAAW;CAC9C;CAEA,OAAO,IAA0D;EAC/D,OAAO,KAAK,OAAO,OAA4B,aAAa,IAAI;CAClE;AACF;;;AChCA,IAAa,YAAb,MAAuB;CACrB,YAAY,QAAiC;EAAhB,KAAA,SAAA;CAAiB;CAE9C,OAAO,MAAiD;EACtD,OAAO,KAAK,OAAO,KAAe,cAAc,EAAE,KAAK,CAAC;CAC1D;CAEA,MAAM,OAAoD;EACxD,MAAM,MAAM,MAAM,KAAK,OAAO,IAAkC,YAAY;EAC5E,IAAI,IAAI,OAAO,OAAO;EACtB,OAAO;GAAE,MAAM,IAAI,KAAK;GAAM,OAAO;GAAM,SAAS,IAAI;EAAQ;CAClE;CAEA,OAAO,IAA4D;EACjE,OAAO,KAAK,OAAO,OAA8B,cAAc,IAAI;CACrE;CAEA,cACE,YACA,SACkC;EAClC,OAAO,KAAK,OAAO,KAAc,cAAc,WAAW,YAAY;GACpE,OAAO,QAAQ;GACf,YAAY,QAAQ;GACpB,WAAW,QAAQ;EACrB,CAAC;CACH;CAEA,MAAM,aACJ,YACA,UAA+B,CAAC,GACe;EAC/C,MAAM,SAAS,IAAI,gBAAgB;EACnC,IAAI,QAAQ,SAAS,MAAM,OAAO,IAAI,SAAS,OAAO,QAAQ,KAAK,CAAC;EACpE,IAAI,QAAQ,QAAQ,OAAO,IAAI,UAAU,QAAQ,MAAM;EACvD,IAAI,QAAQ,QAAQ,OAAO,IAAI,UAAU,QAAQ,MAAM;EACvD,IAAI,QAAQ,cAAc,MAAM,OAAO,IAAI,cAAc,OAAO,QAAQ,UAAU,CAAC;EACnF,MAAM,KAAK,OAAO,SAAS;EAC3B,OAAO,KAAK,OAAO,IACjB,KAAK,cAAc,WAAW,YAAY,OAAO,cAAc,WAAW,UAC5E;CACF;CAEA,WAAW,YAAoB,WAAqD;EAClF,OAAO,KAAK,OAAO,IAAa,cAAc,WAAW,YAAY,WAAW;CAClF;CAEA,cACE,YACA,WACA,SACkC;EAClC,OAAO,KAAK,OAAO,MAAe,cAAc,WAAW,YAAY,aAAa;GAClF,YAAY,QAAQ;GACpB,WAAW,QAAQ;GACnB,cAAc,QAAQ;EACxB,CAAC;CACH;CAEA,cACE,YACA,WACgD;EAChD,OAAO,KAAK,OAAO,OACjB,cAAc,WAAW,YAAY,WACvC;CACF;;;;;;CAOA,oBACE,YACA,SACgE;EAChE,OAAO,KAAK,OAAO,KAA4C,cAAc,WAAW,kBAAkB,EACxG,UAAU,QAAQ,SAAS,KAAK,OAAO;GACrC,OAAO,EAAE;GACT,YAAY,EAAE;GACd,WAAW,EAAE;EACf,EAAE,EACJ,CAAC;CACH;AACF;;;ACtGA,eAAe,oBACb,SAC6B;CAC7B,IAAI,QAAQ,MAAM,OAAO,QAAQ;CACjC,IAAI,QAAQ,OAAO,OAAO,iBAAiB,QAAQ,KAAK;AAE1D;AAEA,IAAa,YAAb,MAAuB;CACrB,YAAY,QAAiC;EAAhB,KAAA,SAAA;CAAiB;CAE9C,MAAM,OAAO,SAAmE;EAC9E,MAAM,OAAO,MAAM,oBAAoB,OAAO;EAC9C,IAAI,CAAC,MACH,OAAO;GACL,MAAM;GACN,OAAO;IACL,SAAS;IACT,YAAY;IACZ,MAAM;GACR;GACA,SAAS;EACX;EAEF,OAAO,KAAK,OAAO,KAAe,cAAc;GAC9C,MAAM,QAAQ;GACd,SAAS,QAAQ;GACjB;EACF,CAAC;CACH;CAEA,MAAM,OAAoD;EACxD,MAAM,MAAM,MAAM,KAAK,OAAO,IAAkC,YAAY;EAC5E,IAAI,IAAI,OAAO,OAAO;EACtB,OAAO;GAAE,MAAM,IAAI,KAAK;GAAM,OAAO;GAAM,SAAS,IAAI;EAAQ;CAClE;CAEA,IAAI,IAA+C;EACjD,OAAO,KAAK,OAAO,IAAc,cAAc,IAAI;CACrD;CAEA,MAAM,OAAO,IAAY,SAAmE;EAC1F,MAAM,OAAO,MAAM,oBAAoB,OAAO;EAC9C,OAAO,KAAK,OAAO,MAAgB,cAAc,MAAM;GACrD,MAAM,QAAQ;GACd,SAAS,QAAQ;GACjB;EACF,CAAC;CACH;CAEA,OAAO,IAA4D;EACjE,OAAO,KAAK,OAAO,OAA8B,cAAc,IAAI;CACrE;AACF;;;AC9CA,IAAa,WAAb,MAAsB;CACpB,YAAY,QAAiC;EAAhB,KAAA,SAAA;CAAiB;CAE9C,OAAO,SAA+E;EACpF,OAAO,KAAK,OAAO,KAA4B,aAAa;GAC1D,KAAK,QAAQ;GACb,QAAQ,QAAQ;EAClB,CAAC;CACH;CAEA,MAAM,OAA2C;EAC/C,MAAM,MAAM,MAAM,KAAK,OAAO,IAAyB,WAAW;EAClE,IAAI,IAAI,OAAO,OAAO;EACtB,OAAO;GAAE,MAAM,IAAI,KAAK;GAAM,OAAO;GAAM,SAAS,IAAI;EAAQ;CAClE;CAEA,IAAI,IAA4D;EAC9D,OAAO,KAAK,OAAO,IAA2B,aAAa,IAAI;CACjE;CAEA,OAAO,IAAY,SAAiE;EAClF,OAAO,KAAK,OAAO,MAAe,aAAa,MAAM;GACnD,KAAK,QAAQ;GACb,QAAQ,QAAQ;EAClB,CAAC;CACH;CAEA,OAAO,IAA4D;EACjE,OAAO,KAAK,OAAO,OAA8B,aAAa,IAAI;CACpE;AACF;;;ACqBA,eAAe,qBACb,SAC6B;CAC7B,IAAI,QAAQ,MAAM,OAAO,QAAQ;CACjC,IAAI,QAAQ,OAAO,OAAO,iBAAiB,QAAQ,KAAK;AAE1D;AAEA,IAAa,aAAb,MAAwB;CACtB,YAAY,QAAiC;EAAhB,KAAA,SAAA;CAAiB;CAE9C,MAAM,OAAO,SAAqE;EAChF,MAAM,OAAO,MAAM,qBAAqB,OAAO;EAC/C,OAAO,KAAK,OAAO,KAAgB,eAAe;GAChD,MAAM,QAAQ;GACd,aAAa,QAAQ;GACrB,MAAM,QAAQ;GACd,SAAS,QAAQ;GACjB;GACA,aAAa,QAAQ;GACrB,oBAAoB,QAAQ;EAC9B,CAAC;CACH;CAEA,MAAM,OAAqD;EACzD,MAAM,MAAM,MAAM,KAAK,OAAO,IAAmC,aAAa;EAC9E,IAAI,IAAI,OAAO,OAAO;EACtB,OAAO;GAAE,MAAM,IAAI,KAAK;GAAM,OAAO;GAAM,SAAS,IAAI;EAAQ;CAClE;CAEA,IAAI,IAAsD;EACxD,OAAO,KAAK,OAAO,IAAqB,eAAe,IAAI;CAC7D;CAEA,MAAM,OAAO,IAAY,SAAqE;EAC5F,MAAM,OAAO,MAAM,qBAAqB,OAAO;EAC/C,OAAO,KAAK,OAAO,MAAiB,eAAe,MAAM;GACvD,MAAM,QAAQ;GACd,aAAa,QAAQ;GACrB,MAAM,QAAQ;GACd,SAAS,QAAQ;GACjB;GACA,aAAa,QAAQ;GACrB,oBAAoB,QAAQ;GAC5B,cAAc,QAAQ;EACxB,CAAC;CACH;CAEA,MAAM,KACJ,IACA,UAAgC,CAAC,GACe;EAGhD,MAAM,MAAM,MAAM,KAAK,OAAO,KAI3B,eAAe,GAAG,QAAQ,EAC3B,cAAc,QAAQ,YACxB,CAAC;EACD,IAAI,IAAI,OAAO,OAAO;EACtB,OAAO;GACL,MAAM;IAAE,IAAI,IAAI,KAAK;IAAI,QAAQ,IAAI,KAAK;IAAQ,aAAa,IAAI,KAAK;GAAa;GACrF,OAAO;GACP,SAAS,IAAI;EACf;CACF;CAEA,OAAO,IAAgD;EACrD,OAAO,KAAK,OAAO,KAAgB,eAAe,GAAG,QAAQ;CAC/D;CAEA,OAAO,IAA4D;EACjE,OAAO,KAAK,OAAO,OAA8B,eAAe,IAAI;CACtE;AACF;;;;;;;;;;AC/HA,IAAa,eAAb,MAA0B;CACxB,YAAY,QAAiC;EAAhB,KAAA,SAAA;CAAiB;CAE9C,KAAK,UAAmC,CAAC,GAAsD;EAC7F,MAAM,SAAS,IAAI,gBAAgB;EACnC,IAAI,QAAQ,OAAO,OAAO,IAAI,SAAS,QAAQ,KAAK;EACpD,IAAI,QAAQ,QAAQ,OAAO,IAAI,UAAU,QAAQ,MAAM;EACvD,IAAI,QAAQ,SAAS,MAAM,OAAO,IAAI,SAAS,OAAO,QAAQ,KAAK,CAAC;EACpE,IAAI,QAAQ,QAAQ,OAAO,IAAI,UAAU,QAAQ,MAAM;EACvD,MAAM,KAAK,OAAO,SAAS;EAC3B,OAAO,KAAK,OAAO,IACjB,KAAK,iBAAiB,OAAO,eAC/B;CACF;;;;;CAMA,OAAO,SAA8E;EACnF,OAAO,KAAK,OAAO,KAAuB,iBAAiB;GACzD,OAAO,QAAQ;GACf,QAAQ,QAAQ;EAClB,CAAC;CACH;;;;;CAMA,OAAO,QAAsF;EAC3F,OAAO,KAAK,OAAO,KAAiC,uBAAuB,EAAE,OAAO,CAAC;CACvF;;;;;;;;CASA,OAAO,WAAiE;EACtE,OAAO,KAAK,OAAO,OACjB,iBAAiB,mBAAmB,SAAS,GAC/C;CACF;;CAGA,SAA0C;EACxC,OAAO,KAAK,OAAO,aAAqB,wBAAwB,EAAE,QAAQ,MAAM,GAAG,CAAC,GAAG,MAAM;CAC/F;AACF;;;AC1FA,MAAM,mBAAmB;AACzB,MAAM,cAAc;AAMpB,IAAa,SAAb,MAAoB;CAelB,YAAY,KAAc,SAAyB;EACjD,MAAM,SACJ,QAAQ,OAAO,YAAY,cAAc,QAAQ,IAAI,oBAAoB,KAAA;EAC3E,IAAI,CAAC,QACH,MAAM,IAAI,MACR,oGACF;EAEF,KAAK,SAAS;EACd,KAAK,UAAU,SAAS,WAAW;EAEnC,KAAK,SAAS,IAAI,OAAO,IAAI;EAC7B,KAAK,QAAQ,IAAI,MAAM,IAAI;EAC3B,KAAK,UAAU,IAAI,QAAQ,IAAI;EAC/B,KAAK,UAAU,IAAI,QAAQ,IAAI;EAC/B,KAAK,YAAY,IAAI,UAAU,IAAI;EACnC,KAAK,YAAY,IAAI,UAAU,IAAI;EACnC,KAAK,WAAW,IAAI,SAAS,IAAI;EACjC,KAAK,aAAa,IAAI,WAAW,IAAI;EACrC,KAAK,eAAe,IAAI,aAAa,IAAI;CAC3C;CAEA,MAAM,aACJ,MACA,OAAoB,CAAC,GACrB,eAAuC,CAAC,GAIxC,QAAyB,QACG;EAC5B,MAAM,UAAkC;GACtC,eAAe,UAAU,KAAK;GAC9B,gBAAgB;GAChB,cAAc,eAAe;GAC7B,GAAG;EACL;EAEA,IAAI;GACF,MAAM,MAAM,MAAM,MAAM,GAAG,KAAK,UAAU,QAAQ;IAAE,GAAG;IAAM;GAAQ,CAAC;GACtE,MAAM,kBAAkB,OAAO,YAAY,IAAI,QAAQ,QAAQ,CAAC;GAEhE,IAAI,CAAC,IAAI,IAAI;IACX,IAAI;IACJ,IAAI;KACF,MAAM,OAAQ,MAAM,IAAI,KAAK;KAC7B,QAAQ;MACN,SAAS,KAAK,SAAS;MACvB,YAAY,IAAI;MAChB,MAAO,KAAK,QAAgC;KAC9C;IACF,QAAQ;KACN,QAAQ;MAAE,SAAS;MAAkB,YAAY,IAAI;MAAQ,MAAM;KAAiB;IACtF;IACA,OAAO;KAAE,MAAM;KAAM;KAAO,SAAS;IAAgB;GACvD;GAEA,IAAI,IAAI,WAAW,OAAO,IAAI,QAAQ,IAAI,gBAAgB,MAAM,KAC9D,OAAO;IAAE,MAAM,CAAC;IAAQ,OAAO;IAAM,SAAS;GAAgB;GAIhE,OAAO;IAAE,MADK,UAAU,SAAS,MAAM,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK;IACpD,OAAO;IAAM,SAAS;GAAgB;EACvD,QAAQ;GACN,OAAO;IACL,MAAM;IACN,OAAO;KACL,SAAS;KACT,YAAY;KACZ,MAAM;IACR;IACA,SAAS;GACX;EACF;CACF;CAEA,IAAO,MAAc,cAAmE;EACtF,OAAO,KAAK,aAAgB,MAAM,EAAE,QAAQ,MAAM,GAAG,YAAY;CACnE;CAEA,KACE,MACA,MACA,cAC4B;EAC5B,OAAO,KAAK,aACV,MACA;GAAE,QAAQ;GAAQ,MAAM,QAAQ,OAAO,KAAK,UAAU,IAAI,IAAI,KAAA;EAAU,GACxE,YACF;CACF;CAEA,MAAS,MAAc,MAA4C;EACjE,OAAO,KAAK,aAAgB,MAAM;GAChC,QAAQ;GACR,MAAM,QAAQ,OAAO,KAAK,UAAU,IAAI,IAAI,KAAA;EAC9C,CAAC;CACH;CAEA,OAAU,MAA0C;EAClD,OAAO,KAAK,aAAgB,MAAM,EAAE,QAAQ,SAAS,CAAC;CACxD;AACF"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/react-render.ts","../src/emails.ts","../src/batch.ts","../src/domains.ts","../src/api-keys.ts","../src/audiences.ts","../src/templates.ts","../src/webhooks.ts","../src/broadcasts.ts","../src/suppressions.ts","../src/eusend.ts"],"sourcesContent":["// Minimal structural type so the SDK doesn't take a hard dependency on `react`.\n// Real React elements assignable to this; users who pass `react:` are expected to\n// have `react` and `@react-email/render` installed (declared as optional peers).\nexport type ReactEmailElement = {\n readonly type: unknown;\n readonly props: unknown;\n readonly key: string | number | null;\n};\n\nlet renderPromise: Promise<(element: ReactEmailElement) => Promise<string>> | null = null;\n\nasync function getRender(): Promise<(element: ReactEmailElement) => Promise<string>> {\n if (!renderPromise) {\n renderPromise = (async () => {\n try {\n const mod = (await import('@react-email/render')) as {\n render: (element: unknown, options?: { plainText?: boolean }) => Promise<string> | string;\n };\n return (element: ReactEmailElement) => Promise.resolve(mod.render(element));\n } catch {\n throw new Error(\n \"Passing `react:` requires `@react-email/render` and `react` to be installed. \" +\n 'Run: npm install @react-email/render react',\n );\n }\n })();\n }\n return renderPromise;\n}\n\nexport async function renderReactEmail(element: ReactEmailElement): Promise<string> {\n const render = await getRender();\n return render(element);\n}\n","import type { Eusend } from './eusend';\nimport type { EusendErrorCode, EusendResponse } from './interfaces';\nimport { renderReactEmail, type ReactEmailElement } from './react-render';\n\nexport type EmailStatus =\n | 'queued'\n | 'scheduled'\n | 'canceled'\n | 'sending'\n | 'sent'\n | 'delivered'\n | 'bounced'\n | 'complained'\n | 'suppressed'\n | 'failed';\n\nexport type EmailEventType =\n | 'sent'\n | 'delivered'\n | 'opened'\n | 'clicked'\n | 'bounced'\n | 'complained';\n\nexport interface Attachment {\n /** Name the recipient sees for the file, e.g. `invoice.pdf`. */\n filename: string;\n /**\n * File contents. A base64-encoded string (sent as-is) or raw bytes\n * (`Uint8Array`/`Buffer`), which the SDK base64-encodes for you. Provide either\n * `content` or `path`, not both.\n */\n content?: string | Uint8Array;\n /**\n * A URL the server fetches at send time to attach the file. Use instead of\n * `content` when the bytes live on a public URL. Provide either `content` or `path`,\n * not both.\n */\n path?: string;\n /** MIME type, e.g. `application/pdf`. Inferred from the filename when omitted. */\n contentType?: string;\n /**\n * Content-ID for an inline attachment. Set it to reference the file from your\n * HTML with `<img src=\"cid:<contentId>\">` instead of showing it as a download.\n */\n contentId?: string;\n}\n\n/** A single tag in the `[{ name, value }]` form, for Resend-compatible payloads. */\nexport interface EmailTag {\n name: string;\n value: string;\n}\n\n/**\n * Labels attached to a send, used to filter your email log and to route webhook events.\n *\n * Accepts either a plain object (`{ category: 'password_reset' }`) or the\n * `[{ name, value }]` array form, so a payload written against Resend works unchanged.\n * Responses and webhook payloads always return the object form.\n *\n * Names and values may contain ASCII letters, numbers, underscores and dashes; up to 10\n * tags per email.\n */\nexport type EmailTags = Record<string, string> | EmailTag[];\n\nexport interface SendEmailOptions {\n /**\n * Sender address. Accepts a bare email (`onboarding@eusend.dev`) or a display-name\n * form (`Acme <onboarding@eusend.dev>`). The domain must be verified on your account.\n */\n from: string;\n to: string | string[];\n cc?: string | string[];\n bcc?: string | string[];\n replyTo?: string | string[];\n subject?: string;\n html?: string;\n text?: string;\n /**\n * A React Email component. The SDK renders it to HTML locally before sending\n * — the JSX source never travels over the wire. Requires `@react-email/render`\n * and `react` as peer dependencies. Ignored when `html` is also provided.\n */\n react?: ReactEmailElement;\n templateId?: string;\n variables?: Record<string, unknown>;\n headers?: Record<string, string>;\n /**\n * Labels for log filtering and webhook routing, e.g.\n * `{ category: 'password_reset', tier: 'pro' }`. Returned on every `email.*` webhook\n * event for this send.\n */\n tags?: EmailTags;\n trackOpens?: boolean;\n trackClicks?: boolean;\n /** File attachments. Up to 20 per message, 10 MB combined. */\n attachments?: Attachment[];\n /**\n * Schedule the send for a future time, at most 30 days out. Accepts a `Date`, an\n * ISO 8601 string, or a natural-language time like `\"in 1 hour\"` or `\"tomorrow at\n * 9am\"` (parsed server-side, same as Resend). Relative phrasings resolve against the\n * server clock in UTC — pass an offset-qualified ISO string when you need an exact\n * instant. The email is created with status `scheduled`; reschedule it with\n * `emails.update()` or call `emails.cancel()` any time before it sends.\n */\n scheduledAt?: string | Date;\n}\n\nexport interface SendEmailRequestOptions {\n idempotencyKey?: string;\n}\n\nexport interface SendEmailResponse {\n id: string;\n}\n\n/**\n * Per-item outcome of a batch send, positionally mapped to the input array:\n * `data[i]` describes `emails[i]`. Items that were queued carry `{ id }`; items\n * that could not be queued carry `{ error, code }` (e.g. an unverified sender\n * domain, all recipients suppressed, or an exhausted send quota). Branch on the\n * presence of `id`.\n */\nexport type BatchItemResult =\n | { id: string; error?: never; code?: never }\n | { id?: never; error: string; code: EusendErrorCode };\n\nexport interface BatchSendResponse {\n data: BatchItemResult[];\n}\n\nexport interface EmailEvent {\n id: string;\n type: EmailEventType;\n metadata: Record<string, unknown>;\n createdAt: string;\n}\n\nexport interface Email {\n id: string;\n from: string;\n to: string[];\n cc: string[];\n bcc: string[];\n replyTo: string[];\n subject: string;\n html: string | null;\n text: string | null;\n status: EmailStatus;\n /** Always the object form, `{}` when the send carried no tags. */\n tags: Record<string, string>;\n testMode: boolean;\n templateId: string | null;\n /** Set only for scheduled sends. */\n scheduledAt: string | null;\n createdAt: string;\n events: EmailEvent[];\n}\n\nexport interface UpdateEmailOptions {\n /** The new send time, at most 30 days out — a `Date`, an ISO 8601 string, or natural\n * language like `\"in 1 hour\"` (parsed server-side, same as `emails.send`). */\n scheduledAt: string | Date;\n}\n\nexport interface UpdateEmailResponse {\n id: string;\n status: 'scheduled';\n scheduledAt: string;\n}\n\nexport interface CancelEmailResponse {\n id: string;\n status: 'canceled';\n}\n\nexport interface EmailListItem {\n id: string;\n from: string;\n to: string[];\n subject: string;\n status: EmailStatus;\n /** Always the object form, `{}` when the send carried no tags. */\n tags: Record<string, string>;\n testMode: boolean;\n createdAt: string;\n}\n\nexport interface ListEmailsOptions {\n limit?: number;\n cursor?: string;\n status?: EmailStatus;\n from?: string;\n to?: string;\n /**\n * Filter by tag. `'category:password_reset'` matches that exact pair; a bare\n * `'category'` matches any email carrying the tag. Pass an array to require several.\n */\n tag?: string | string[];\n}\n\nexport interface ListEmailsResponse {\n data: EmailListItem[];\n nextCursor: string | null;\n}\n\nasync function resolveHtml(options: SendEmailOptions): Promise<string | undefined> {\n if (options.html) return options.html;\n if (options.react) return renderReactEmail(options.react);\n return undefined;\n}\n\nfunction encodeAttachmentContent(content: string | Uint8Array): string {\n // A string is assumed to already be base64. Raw bytes are encoded here.\n if (typeof content === 'string') return content;\n if (typeof Buffer !== 'undefined') return Buffer.from(content).toString('base64');\n let binary = '';\n for (const byte of content) binary += String.fromCharCode(byte);\n return btoa(binary);\n}\n\nfunction toIsoString(value: string | Date): string {\n return value instanceof Date ? value.toISOString() : value;\n}\n\nexport async function toApiPayload(options: SendEmailOptions) {\n const html = await resolveHtml(options);\n return {\n from: options.from,\n to: options.to,\n cc: options.cc,\n bcc: options.bcc,\n reply_to: options.replyTo,\n subject: options.subject,\n html,\n text: options.text,\n template_id: options.templateId,\n variables: options.variables,\n headers: options.headers,\n tags: options.tags,\n track_opens: options.trackOpens,\n track_clicks: options.trackClicks,\n attachments: options.attachments?.map((a) => ({\n filename: a.filename,\n content: a.content === undefined ? undefined : encodeAttachmentContent(a.content),\n path: a.path,\n content_type: a.contentType,\n content_id: a.contentId,\n })),\n scheduled_at: options.scheduledAt ? toIsoString(options.scheduledAt) : undefined,\n };\n}\n\nexport class Emails {\n constructor(private readonly client: Eusend) {}\n\n async send(\n options: SendEmailOptions,\n requestOptions?: SendEmailRequestOptions,\n ): Promise<EusendResponse<SendEmailResponse>> {\n const extraHeaders: Record<string, string> = {};\n if (requestOptions?.idempotencyKey) {\n extraHeaders['Idempotency-Key'] = requestOptions.idempotencyKey;\n }\n const payload = await toApiPayload(options);\n return this.client.post<SendEmailResponse>('/emails', payload, extraHeaders);\n }\n\n async list(options: ListEmailsOptions = {}): Promise<EusendResponse<ListEmailsResponse>> {\n const params = new URLSearchParams();\n if (options.limit != null) params.set('limit', String(options.limit));\n if (options.cursor) params.set('cursor', options.cursor);\n if (options.status) params.set('status', options.status);\n if (options.from) params.set('from', options.from);\n if (options.to) params.set('to', options.to);\n // Repeated `tag` params, one per filter — the API ANDs them.\n for (const tag of options.tag == null ? [] : [options.tag].flat()) {\n params.append('tag', tag);\n }\n const qs = params.toString();\n\n const res = await this.client.get<{ data: EmailListItem[]; next_cursor: string | null }>(\n qs ? `/emails?${qs}` : '/emails',\n );\n if (res.error) return res;\n return {\n data: { data: res.data.data, nextCursor: res.data.next_cursor },\n error: null,\n headers: res.headers,\n };\n }\n\n get(id: string): Promise<EusendResponse<Email>> {\n return this.client.get<Email>(`/emails/${id}`);\n }\n\n /** Reschedule a scheduled email. Fails once the email has started sending. */\n async update(\n id: string,\n options: UpdateEmailOptions,\n ): Promise<EusendResponse<UpdateEmailResponse>> {\n const res = await this.client.patch<{ id: string; status: 'scheduled'; scheduled_at: string }>(\n `/emails/${id}`,\n { scheduled_at: toIsoString(options.scheduledAt) },\n );\n if (res.error) return res;\n return {\n data: { id: res.data.id, status: res.data.status, scheduledAt: res.data.scheduled_at },\n error: null,\n headers: res.headers,\n };\n }\n\n /** Cancel a scheduled email. Fails once the email has started sending. */\n cancel(id: string): Promise<EusendResponse<CancelEmailResponse>> {\n return this.client.post<CancelEmailResponse>(`/emails/${id}/cancel`, undefined);\n }\n}\n","import type { Eusend } from './eusend';\nimport type { EusendResponse } from './interfaces';\nimport { toApiPayload, type SendEmailOptions, type BatchSendResponse } from './emails';\n\n/**\n * Batch sending — `eusend.batch.send([...])`. The method path mirrors Resend's\n * `resend.batch.send([...])`, so migrating is a mechanical `resend` → `eusend` rename.\n * The HTTP body is a top-level array of email objects (POST /emails/batch), up to 100\n * per request. As with Resend, attachments and `scheduledAt` are not supported on the\n * batch endpoint — send those individually via `emails.send`.\n *\n * The response maps positionally to the input: `data[i]` is `{ id }` when\n * `emails[i]` was queued, or `{ error, code }` when it was not (unverified\n * domain, suppressed recipients, exhausted quota, …) — failed items never fail\n * the whole batch, so branch on the presence of `id` per item.\n */\nexport class Batch {\n constructor(private readonly client: Eusend) {}\n\n async send(emails: SendEmailOptions[]): Promise<EusendResponse<BatchSendResponse>> {\n const payloads = await Promise.all(emails.map(toApiPayload));\n return this.client.post<BatchSendResponse>('/emails/batch', payloads);\n }\n}\n","import type { Eusend } from './eusend';\nimport type { EusendResponse } from './interfaces';\n\nexport type DomainStatus = 'pending' | 'verified' | 'failed';\n\nexport interface DnsRecord {\n type: string;\n name: string;\n value: string;\n /** MX records only. */\n priority?: number;\n /**\n * `authentication` — required before the domain can send.\n * `policy` — recommended; absence weakens but does not block.\n * `alignment` — optional; publishing all of them enables Return-Path SPF alignment.\n */\n purpose?: string;\n description?: string;\n}\n\nexport interface CreateDomainResponse {\n id: string;\n name: string;\n /**\n * Every record to publish, in presentation order. Prefer this over the individual\n * keys below — it is the only place the optional Return-Path alignment records appear.\n */\n records: DnsRecord[];\n dkim: DnsRecord;\n dmarc: DnsRecord;\n}\n\nexport interface DomainListItem {\n id: string;\n name: string;\n status: DomainStatus;\n createdAt: string;\n}\n\nexport interface Domain {\n id: string;\n name: string;\n dkimPublicKey: string;\n dkimSelector: string;\n status: DomainStatus;\n createdAt: string;\n verifiedAt: string | null;\n}\n\nexport class Domains {\n constructor(private readonly client: Eusend) {}\n\n create(name: string): Promise<EusendResponse<CreateDomainResponse>> {\n return this.client.post<CreateDomainResponse>('/domains', { name });\n }\n\n list(): Promise<EusendResponse<DomainListItem[]>> {\n return this.client.get<DomainListItem[]>('/domains');\n }\n\n get(id: string): Promise<EusendResponse<Domain>> {\n return this.client.get<Domain>(`/domains/${id}`);\n }\n\n delete(id: string): Promise<EusendResponse<{ message: string }>> {\n return this.client.delete<{ message: string }>(`/domains/${id}`);\n }\n\n verify(id: string): Promise<EusendResponse<{ message: string }>> {\n return this.client.post<{ message: string }>(`/domains/${id}/verify`);\n }\n}\n","import type { Eusend } from './eusend';\nimport type { EusendResponse } from './interfaces';\n\n/**\n * What a key may reach. `full_access` is every resource; `sending_access` is limited to\n * sending email (and rescheduling or canceling a scheduled send).\n */\nexport type ApiKeyPermission = 'full_access' | 'sending_access';\n\nexport interface CreateApiKeyOptions {\n name: string;\n testMode?: boolean;\n /** Defaults to `full_access`. */\n permission?: ApiKeyPermission;\n /**\n * Restrict the key to sending from a single domain. Only valid together with\n * `permission: 'sending_access'`; omit for any verified domain.\n */\n domainId?: string;\n}\n\nexport interface CreateApiKeyResponse {\n id: string;\n name: string;\n key: string;\n prefix: string;\n testMode: boolean;\n permission: ApiKeyPermission;\n domainId: string | null;\n domainName: string | null;\n createdAt: string;\n}\n\nexport interface ApiKey {\n id: string;\n name: string;\n prefix: string;\n testMode: boolean;\n permission: ApiKeyPermission;\n domainId: string | null;\n domainName: string | null;\n createdAt: string;\n lastUsedAt: string | null;\n}\n\ntype CreateApiKeyApiResponse = {\n id: string;\n name: string;\n key: string;\n prefix: string;\n test_mode: boolean;\n permission: ApiKeyPermission;\n domain_id: string | null;\n domain_name: string | null;\n created_at: string;\n};\n\nexport class ApiKeys {\n constructor(private readonly client: Eusend) {}\n\n async create(options: CreateApiKeyOptions): Promise<EusendResponse<CreateApiKeyResponse>> {\n const res = await this.client.post<CreateApiKeyApiResponse>('/api-keys', {\n name: options.name,\n test_mode: options.testMode ?? false,\n permission: options.permission ?? 'full_access',\n ...(options.domainId ? { domain_id: options.domainId } : {}),\n });\n if (res.error) return res;\n return {\n data: {\n id: res.data.id,\n name: res.data.name,\n key: res.data.key,\n prefix: res.data.prefix,\n testMode: res.data.test_mode,\n permission: res.data.permission,\n domainId: res.data.domain_id,\n domainName: res.data.domain_name,\n createdAt: res.data.created_at,\n },\n error: null,\n headers: res.headers,\n };\n }\n\n list(): Promise<EusendResponse<ApiKey[]>> {\n return this.client.get<ApiKey[]>('/api-keys');\n }\n\n delete(id: string): Promise<EusendResponse<{ message: string }>> {\n return this.client.delete<{ message: string }>(`/api-keys/${id}`);\n }\n}\n","import type { Eusend } from './eusend';\nimport type { EusendResponse } from './interfaces';\n\nexport type ContactStatus = 'subscribed' | 'unsubscribed';\n\nexport interface Audience {\n id: string;\n name: string;\n organizationId: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface AudienceListItem {\n id: string;\n name: string;\n createdAt: string;\n contactCount: number;\n}\n\nexport interface Contact {\n id: string;\n audienceId: string;\n email: string;\n firstName: string | null;\n lastName: string | null;\n status: ContactStatus;\n unsubscribedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CreateContactOptions {\n email: string;\n firstName?: string;\n lastName?: string;\n}\n\nexport interface UpdateContactOptions {\n firstName?: string;\n lastName?: string;\n unsubscribed?: boolean;\n}\n\nexport interface ListContactsOptions {\n limit?: number;\n cursor?: string;\n search?: string;\n subscribed?: boolean;\n}\n\nexport interface ListContactsResponse {\n data: Contact[];\n nextCursor: string | null;\n}\n\nexport interface BatchCreateContactsOptions {\n contacts: CreateContactOptions[];\n}\n\nexport class Audiences {\n constructor(private readonly client: Eusend) {}\n\n create(name: string): Promise<EusendResponse<Audience>> {\n return this.client.post<Audience>('/audiences', { name });\n }\n\n async list(): Promise<EusendResponse<AudienceListItem[]>> {\n const res = await this.client.get<{ data: AudienceListItem[] }>('/audiences');\n if (res.error) return res;\n return { data: res.data.data, error: null, headers: res.headers };\n }\n\n delete(id: string): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(`/audiences/${id}`);\n }\n\n createContact(\n audienceId: string,\n options: CreateContactOptions,\n ): Promise<EusendResponse<Contact>> {\n return this.client.post<Contact>(`/audiences/${audienceId}/contacts`, {\n email: options.email,\n first_name: options.firstName,\n last_name: options.lastName,\n });\n }\n\n async listContacts(\n audienceId: string,\n options: ListContactsOptions = {},\n ): Promise<EusendResponse<ListContactsResponse>> {\n const params = new URLSearchParams();\n if (options.limit != null) params.set('limit', String(options.limit));\n if (options.cursor) params.set('cursor', options.cursor);\n if (options.search) params.set('search', options.search);\n if (options.subscribed != null) params.set('subscribed', String(options.subscribed));\n const qs = params.toString();\n return this.client.get<ListContactsResponse>(\n qs ? `/audiences/${audienceId}/contacts?${qs}` : `/audiences/${audienceId}/contacts`,\n );\n }\n\n getContact(audienceId: string, contactId: string): Promise<EusendResponse<Contact>> {\n return this.client.get<Contact>(`/audiences/${audienceId}/contacts/${contactId}`);\n }\n\n updateContact(\n audienceId: string,\n contactId: string,\n options: UpdateContactOptions,\n ): Promise<EusendResponse<Contact>> {\n return this.client.patch<Contact>(`/audiences/${audienceId}/contacts/${contactId}`, {\n first_name: options.firstName,\n last_name: options.lastName,\n unsubscribed: options.unsubscribed,\n });\n }\n\n deleteContact(\n audienceId: string,\n contactId: string,\n ): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(\n `/audiences/${audienceId}/contacts/${contactId}`,\n );\n }\n\n /**\n * Upsert up to 1000 contacts in one call. Addresses are lowercased and\n * de-duplicated server-side; `count` is the number of rows written and\n * `duplicates` how many repeated addresses were collapsed to get there.\n */\n batchCreateContacts(\n audienceId: string,\n options: BatchCreateContactsOptions,\n ): Promise<EusendResponse<{ count: number; duplicates: number }>> {\n return this.client.post<{ count: number; duplicates: number }>(`/audiences/${audienceId}/contacts/batch`, {\n contacts: options.contacts.map((c) => ({\n email: c.email,\n first_name: c.firstName,\n last_name: c.lastName,\n })),\n });\n }\n}\n","import type { Eusend } from './eusend';\nimport type { EusendResponse } from './interfaces';\nimport { renderReactEmail, type ReactEmailElement } from './react-render';\n\ninterface TemplateHtmlOrReact {\n /**\n * A React Email component. The SDK renders it to HTML locally before sending.\n * Requires `@react-email/render` and `react` as peer dependencies.\n * Ignored when `html` is also provided.\n */\n react?: ReactEmailElement;\n}\n\nexport interface CreateTemplateOptions extends TemplateHtmlOrReact {\n name: string;\n subject: string;\n html?: string;\n}\n\nexport interface UpdateTemplateOptions extends TemplateHtmlOrReact {\n name?: string;\n subject?: string;\n html?: string;\n}\n\nexport interface Template {\n id: string;\n name: string;\n subject: string;\n html: string | null;\n reactSource: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface TemplateListItem {\n id: string;\n name: string;\n subject: string;\n createdAt: string;\n updatedAt: string;\n}\n\nasync function resolveTemplateHtml(\n options: TemplateHtmlOrReact & { html?: string },\n): Promise<string | undefined> {\n if (options.html) return options.html;\n if (options.react) return renderReactEmail(options.react);\n return undefined;\n}\n\nexport class Templates {\n constructor(private readonly client: Eusend) {}\n\n async create(options: CreateTemplateOptions): Promise<EusendResponse<Template>> {\n const html = await resolveTemplateHtml(options);\n if (!html) {\n return {\n data: null,\n error: {\n message: 'Either html or react is required',\n statusCode: null,\n name: 'VALIDATION_ERROR',\n },\n headers: null,\n };\n }\n return this.client.post<Template>('/templates', {\n name: options.name,\n subject: options.subject,\n html,\n });\n }\n\n async list(): Promise<EusendResponse<TemplateListItem[]>> {\n const res = await this.client.get<{ data: TemplateListItem[] }>('/templates');\n if (res.error) return res;\n return { data: res.data.data, error: null, headers: res.headers };\n }\n\n get(id: string): Promise<EusendResponse<Template>> {\n return this.client.get<Template>(`/templates/${id}`);\n }\n\n async update(id: string, options: UpdateTemplateOptions): Promise<EusendResponse<Template>> {\n const html = await resolveTemplateHtml(options);\n return this.client.patch<Template>(`/templates/${id}`, {\n name: options.name,\n subject: options.subject,\n html,\n });\n }\n\n delete(id: string): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(`/templates/${id}`);\n }\n}\n","import type { Eusend } from './eusend';\nimport type { EusendResponse } from './interfaces';\n\nexport type WebhookEvent =\n | 'email.sent'\n | 'email.delivered'\n | 'email.bounced'\n | 'email.complained'\n | 'email.opened'\n | 'email.clicked'\n | '*';\n\nexport interface CreateWebhookOptions {\n url: string;\n events: WebhookEvent[];\n}\n\nexport interface UpdateWebhookOptions {\n url?: string;\n events?: WebhookEvent[];\n}\n\nexport interface WebhookDelivery {\n id: string;\n webhookId: string;\n emailId: string | null;\n eventType: string;\n payload: Record<string, unknown>;\n status: 'pending' | 'success' | 'failed';\n responseStatus: number | null;\n attempts: number;\n createdAt: string;\n lastAttemptAt: string | null;\n}\n\nexport interface Webhook {\n id: string;\n url: string;\n events: WebhookEvent[];\n createdAt: string;\n}\n\nexport interface WebhookWithDeliveries extends Webhook {\n deliveries: WebhookDelivery[];\n}\n\nexport interface CreateWebhookResponse extends Webhook {\n secret: string;\n}\n\nexport class Webhooks {\n constructor(private readonly client: Eusend) {}\n\n create(options: CreateWebhookOptions): Promise<EusendResponse<CreateWebhookResponse>> {\n return this.client.post<CreateWebhookResponse>('/webhooks', {\n url: options.url,\n events: options.events,\n });\n }\n\n async list(): Promise<EusendResponse<Webhook[]>> {\n const res = await this.client.get<{ data: Webhook[] }>('/webhooks');\n if (res.error) return res;\n return { data: res.data.data, error: null, headers: res.headers };\n }\n\n get(id: string): Promise<EusendResponse<WebhookWithDeliveries>> {\n return this.client.get<WebhookWithDeliveries>(`/webhooks/${id}`);\n }\n\n update(id: string, options: UpdateWebhookOptions): Promise<EusendResponse<Webhook>> {\n return this.client.patch<Webhook>(`/webhooks/${id}`, {\n url: options.url,\n events: options.events,\n });\n }\n\n delete(id: string): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(`/webhooks/${id}`);\n }\n}\n","import type { Eusend } from './eusend';\nimport type { EusendResponse } from './interfaces';\nimport { renderReactEmail, type ReactEmailElement } from './react-render';\n\n/**\n * `held` is a list send stopped part-way pending review. Unlike `paused` it cannot be\n * resumed by sending again — `send()` returns BROADCAST_HELD until the review clears.\n */\nexport type BroadcastStatus =\n | 'draft'\n | 'scheduled'\n | 'sending'\n | 'sent'\n | 'paused'\n | 'held'\n | 'cancelled';\n\nexport interface CreateBroadcastOptions {\n name: string;\n audienceId: string;\n /**\n * Sender address. Accepts a bare email (`onboarding@eusend.dev`) or a display-name\n * form (`Acme <onboarding@eusend.dev>`). The domain must be verified on your account.\n */\n from: string;\n subject: string;\n html?: string;\n /**\n * A React Email component. The SDK renders it to HTML locally before sending —\n * the JSX source never travels over the wire. Requires `@react-email/render`\n * and `react` as peer dependencies. Ignored when `html` is also provided.\n */\n react?: ReactEmailElement;\n templateId?: string;\n templateVariables?: Record<string, string>;\n /**\n * Embed the open-tracking pixel for this broadcast. Omit to use your organization's\n * default (Settings → General → Email tracking); `false` always wins over it.\n */\n trackOpens?: boolean;\n /**\n * Rewrite links so clicks are recorded. Omit to use your organization's default;\n * `false` leaves the original URLs untouched in the delivered mail.\n */\n trackClicks?: boolean;\n}\n\nexport interface UpdateBroadcastOptions {\n name?: string;\n audienceId?: string;\n from?: string;\n subject?: string;\n html?: string;\n /**\n * See `react` on CreateBroadcastOptions. Rendered to HTML locally before sending.\n */\n react?: ReactEmailElement;\n templateId?: string | null;\n templateVariables?: Record<string, string> | null;\n scheduledAt?: string | null;\n /**\n * Embed the open-tracking pixel for this broadcast. Omit to use your organization's\n * default (Settings → General → Email tracking); `false` always wins over it.\n */\n trackOpens?: boolean;\n /**\n * Rewrite links so clicks are recorded. Omit to use your organization's default;\n * `false` leaves the original URLs untouched in the delivered mail.\n */\n trackClicks?: boolean;\n}\n\nexport interface SendBroadcastOptions {\n scheduledAt?: string;\n}\n\nexport interface Broadcast {\n id: string;\n name: string;\n status: BroadcastStatus;\n audienceId: string;\n fromAddress: string;\n subject: string;\n html: string | null;\n templateId: string | null;\n templateVariables: Record<string, string> | null;\n scheduledAt: string | null;\n trackOpens: boolean;\n trackClicks: boolean;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface BroadcastListItem {\n id: string;\n name: string;\n status: BroadcastStatus;\n audienceId: string;\n fromAddress: string;\n subject: string;\n recipientCount: number | null;\n sentCount: number | null;\n scheduledAt: string | null;\n startedAt: string | null;\n completedAt: string | null;\n createdAt: string;\n audienceName: string | null;\n}\n\nexport interface BroadcastDetail extends Broadcast {\n recipientCount: number | null;\n sentCount: number | null;\n startedAt: string | null;\n completedAt: string | null;\n stats: Record<string, number>;\n}\n\nexport interface SendBroadcastResponse {\n id: string;\n status: 'sending' | 'scheduled';\n scheduledAt: string | null;\n}\n\nasync function resolveBroadcastHtml(\n options: { html?: string; react?: ReactEmailElement },\n): Promise<string | undefined> {\n if (options.html) return options.html;\n if (options.react) return renderReactEmail(options.react);\n return undefined;\n}\n\nexport class Broadcasts {\n constructor(private readonly client: Eusend) {}\n\n async create(options: CreateBroadcastOptions): Promise<EusendResponse<Broadcast>> {\n const html = await resolveBroadcastHtml(options);\n return this.client.post<Broadcast>('/broadcasts', {\n name: options.name,\n audience_id: options.audienceId,\n from: options.from,\n subject: options.subject,\n html,\n template_id: options.templateId,\n template_variables: options.templateVariables,\n track_opens: options.trackOpens,\n track_clicks: options.trackClicks,\n });\n }\n\n async list(): Promise<EusendResponse<BroadcastListItem[]>> {\n const res = await this.client.get<{ data: BroadcastListItem[] }>('/broadcasts');\n if (res.error) return res;\n return { data: res.data.data, error: null, headers: res.headers };\n }\n\n get(id: string): Promise<EusendResponse<BroadcastDetail>> {\n return this.client.get<BroadcastDetail>(`/broadcasts/${id}`);\n }\n\n async update(id: string, options: UpdateBroadcastOptions): Promise<EusendResponse<Broadcast>> {\n const html = await resolveBroadcastHtml(options);\n return this.client.patch<Broadcast>(`/broadcasts/${id}`, {\n name: options.name,\n audience_id: options.audienceId,\n from: options.from,\n subject: options.subject,\n html,\n template_id: options.templateId,\n template_variables: options.templateVariables,\n scheduled_at: options.scheduledAt,\n track_opens: options.trackOpens,\n track_clicks: options.trackClicks,\n });\n }\n\n async send(\n id: string,\n options: SendBroadcastOptions = {},\n ): Promise<EusendResponse<SendBroadcastResponse>> {\n // This endpoint is the one broadcast response that comes back snake_cased, so\n // map it rather than exposing a `scheduledAt` that is always undefined.\n const res = await this.client.post<{\n id: string;\n status: 'sending' | 'scheduled';\n scheduled_at: string | null;\n }>(`/broadcasts/${id}/send`, {\n scheduled_at: options.scheduledAt,\n });\n if (res.error) return res;\n return {\n data: { id: res.data.id, status: res.data.status, scheduledAt: res.data.scheduled_at },\n error: null,\n headers: res.headers,\n };\n }\n\n cancel(id: string): Promise<EusendResponse<Broadcast>> {\n return this.client.post<Broadcast>(`/broadcasts/${id}/cancel`);\n }\n\n delete(id: string): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(`/broadcasts/${id}`);\n }\n}\n","import type { Eusend } from './eusend';\nimport type { EusendResponse } from './interfaces';\n\nexport type SuppressionReason = 'bounce' | 'complaint' | 'manual';\n\nexport interface SuppressionEntry {\n id: string;\n email: string;\n reason: SuppressionReason;\n created_at: string;\n}\n\nexport interface ListSuppressionsOptions {\n /** Filter to addresses containing this substring. Pass a domain (\"@acme.com\") to see every suppressed address there. */\n email?: string;\n reason?: SuppressionReason;\n limit?: number;\n cursor?: string;\n}\n\nexport interface ListSuppressionsResponse {\n data: SuppressionEntry[];\n next_cursor: string | null;\n}\n\nexport interface CreateSuppressionOptions {\n email: string;\n /** Defaults to 'manual'. An add never overwrites the reason an address is already suppressed for. */\n reason?: SuppressionReason;\n}\n\n/** An item in an import — a bare address, or an address with the reason it was suppressed. */\nexport type SuppressionImportItem = string | { email: string; reason?: SuppressionReason };\n\nexport interface ImportSuppressionsResponse {\n /** Entries written. */\n count: number;\n /** Entries that were already on the list. */\n already_suppressed: number;\n /** Repeated addresses in the payload, collapsed before the write. */\n duplicates: number;\n}\n\n/**\n * The addresses your organization will not send to.\n *\n * Hard bounces and spam complaints are added automatically; these methods cover the\n * addresses you manage yourself. Suppression applies to live sending only — test-mode\n * keys can read the list but not modify it.\n */\nexport class Suppressions {\n constructor(private readonly client: Eusend) {}\n\n list(options: ListSuppressionsOptions = {}): Promise<EusendResponse<ListSuppressionsResponse>> {\n const params = new URLSearchParams();\n if (options.email) params.set('email', options.email);\n if (options.reason) params.set('reason', options.reason);\n if (options.limit != null) params.set('limit', String(options.limit));\n if (options.cursor) params.set('cursor', options.cursor);\n const qs = params.toString();\n return this.client.get<ListSuppressionsResponse>(\n qs ? `/suppressions?${qs}` : '/suppressions',\n );\n }\n\n /**\n * Suppress an address. If it is already suppressed the existing entry is returned\n * unchanged — a manual add never rewrites a real bounce or complaint.\n */\n create(options: CreateSuppressionOptions): Promise<EusendResponse<SuppressionEntry>> {\n return this.client.post<SuppressionEntry>('/suppressions', {\n email: options.email,\n reason: options.reason,\n });\n }\n\n /**\n * Import up to 1000 addresses in one call — for carrying a suppression list over from\n * another provider before your first send. Items may be bare addresses or objects.\n */\n import(emails: SuppressionImportItem[]): Promise<EusendResponse<ImportSuppressionsResponse>> {\n return this.client.post<ImportSuppressionsResponse>('/suppressions/batch', { emails });\n }\n\n /**\n * Un-suppress by entry id or by address, making the address sendable again.\n *\n * Removing an address that hard-bounced or complained is what damages a sender's\n * reputation when done in bulk — remove an entry when the address was fixed or the\n * complaint was a mistake, not to retry a failing list.\n */\n remove(idOrEmail: string): Promise<EusendResponse<{ deleted: number }>> {\n return this.client.delete<{ deleted: number }>(\n `/suppressions/${encodeURIComponent(idOrEmail)}`,\n );\n }\n\n /** The whole list as CSV (`email,reason,created_at`), for backup or migration. */\n export(): Promise<EusendResponse<string>> {\n return this.client.fetchRequest<string>('/suppressions/export', { method: 'GET' }, {}, 'text');\n }\n}\n","import type { EusendError, EusendResponse } from './interfaces'\nimport { Emails } from './emails'\nimport { Batch } from './batch'\nimport { Domains } from './domains'\nimport { ApiKeys } from './api-keys'\nimport { Audiences } from './audiences'\nimport { Templates } from './templates'\nimport { Webhooks } from './webhooks'\nimport { Broadcasts } from './broadcasts'\nimport { Suppressions } from './suppressions'\n\nconst DEFAULT_BASE_URL = 'https://api.eusend.dev'\nconst SDK_VERSION = '0.8.0'\n\nexport interface EusendOptions {\n baseUrl?: string\n}\n\nexport class Eusend {\n readonly baseUrl: string\n private readonly apiKey: string\n\n readonly emails: Emails\n /** Batch sending — `client.batch.send([...])`. Mirrors Resend's `resend.batch.send()`. */\n readonly batch: Batch\n readonly domains: Domains\n readonly apiKeys: ApiKeys\n readonly audiences: Audiences\n readonly templates: Templates\n readonly webhooks: Webhooks\n readonly broadcasts: Broadcasts\n readonly suppressions: Suppressions\n\n constructor(key?: string, options?: EusendOptions) {\n const apiKey =\n key ?? (typeof process !== 'undefined' ? process.env['EUSEND_API_KEY'] : undefined)\n if (!apiKey) {\n throw new Error(\n 'Missing Eusend API key. Pass it to the constructor or set the EUSEND_API_KEY environment variable.',\n )\n }\n this.apiKey = apiKey\n this.baseUrl = options?.baseUrl ?? DEFAULT_BASE_URL\n\n this.emails = new Emails(this)\n this.batch = new Batch(this)\n this.domains = new Domains(this)\n this.apiKeys = new ApiKeys(this)\n this.audiences = new Audiences(this)\n this.templates = new Templates(this)\n this.webhooks = new Webhooks(this)\n this.broadcasts = new Broadcasts(this)\n this.suppressions = new Suppressions(this)\n }\n\n async fetchRequest<T>(\n path: string,\n init: RequestInit = {},\n extraHeaders: Record<string, string> = {},\n // Not every successful endpoint answers with JSON — the suppression export returns\n // CSV. Parsing that as JSON throws inside the try below, which would surface a\n // perfectly good download as \"Network request failed\".\n parse: 'json' | 'text' = 'json',\n ): Promise<EusendResponse<T>> {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': `eusend-node/${SDK_VERSION}`,\n ...extraHeaders,\n }\n\n try {\n const res = await fetch(`${this.baseUrl}${path}`, { ...init, headers })\n const responseHeaders = Object.fromEntries(res.headers.entries())\n\n if (!res.ok) {\n let error: EusendError\n try {\n const json = (await res.json()) as { error?: string; code?: string }\n error = {\n message: json.error ?? 'Unknown error',\n statusCode: res.status,\n name: (json.code as EusendError['name']) ?? 'INTERNAL_ERROR',\n }\n } catch {\n error = { message: 'Request failed', statusCode: res.status, name: 'INTERNAL_ERROR' }\n }\n return { data: null, error, headers: responseHeaders }\n }\n\n if (res.status === 204 || res.headers.get('content-length') === '0') {\n return { data: {} as T, error: null, headers: responseHeaders }\n }\n\n const data = (parse === 'text' ? await res.text() : await res.json()) as T\n return { data, error: null, headers: responseHeaders }\n } catch {\n return {\n data: null,\n error: {\n message: 'Network request failed. The request could not be resolved.',\n statusCode: null,\n name: 'application_error',\n },\n headers: null,\n }\n }\n }\n\n get<T>(path: string, extraHeaders?: Record<string, string>): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(path, { method: 'GET' }, extraHeaders)\n }\n\n post<T>(\n path: string,\n body?: unknown,\n extraHeaders?: Record<string, string>,\n ): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(\n path,\n { method: 'POST', body: body != null ? JSON.stringify(body) : undefined },\n extraHeaders,\n )\n }\n\n patch<T>(path: string, body?: unknown): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(path, {\n method: 'PATCH',\n body: body != null ? JSON.stringify(body) : undefined,\n })\n }\n\n delete<T>(path: string): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(path, { method: 'DELETE' })\n }\n}\n"],"mappings":"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"}
|