supersendtx 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +105 -4
- package/dist/index.js +137 -7
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -8,10 +8,24 @@ type SendEmailParams = {
|
|
|
8
8
|
subject: string;
|
|
9
9
|
html?: string;
|
|
10
10
|
text?: string;
|
|
11
|
-
replyTo?: string;
|
|
12
|
-
reply_to?: string;
|
|
11
|
+
replyTo?: string | string[];
|
|
12
|
+
reply_to?: string | string[];
|
|
13
13
|
cc?: string | string[];
|
|
14
14
|
bcc?: string | string[];
|
|
15
|
+
tags?: Array<{
|
|
16
|
+
name: string;
|
|
17
|
+
value: string;
|
|
18
|
+
}> | Record<string, string>;
|
|
19
|
+
headers?: Record<string, string>;
|
|
20
|
+
tag?: string;
|
|
21
|
+
attachments?: Array<{
|
|
22
|
+
name: string;
|
|
23
|
+
content_type: string;
|
|
24
|
+
data: string;
|
|
25
|
+
content_id?: string;
|
|
26
|
+
}>;
|
|
27
|
+
scheduledAt?: string | Date;
|
|
28
|
+
scheduled_at?: string | Date;
|
|
15
29
|
/** Optional Idempotency-Key (24h TTL). */
|
|
16
30
|
idempotencyKey?: string;
|
|
17
31
|
};
|
|
@@ -19,14 +33,38 @@ type SendEmailResult = {
|
|
|
19
33
|
id: string;
|
|
20
34
|
status: string;
|
|
21
35
|
};
|
|
36
|
+
type BatchSendEmailResult = {
|
|
37
|
+
data: Array<{
|
|
38
|
+
index: number;
|
|
39
|
+
id?: string;
|
|
40
|
+
status?: string;
|
|
41
|
+
error?: {
|
|
42
|
+
message: string;
|
|
43
|
+
code?: string;
|
|
44
|
+
details?: unknown;
|
|
45
|
+
status_code?: number;
|
|
46
|
+
};
|
|
47
|
+
}>;
|
|
48
|
+
};
|
|
49
|
+
type UpdateEmailParams = {
|
|
50
|
+
scheduledAt?: string | Date;
|
|
51
|
+
scheduled_at?: string | Date;
|
|
52
|
+
cancel?: boolean;
|
|
53
|
+
};
|
|
22
54
|
type EmailListItem = {
|
|
23
55
|
id: string;
|
|
24
56
|
from: string;
|
|
25
57
|
to: string[];
|
|
58
|
+
cc: string[];
|
|
59
|
+
bcc: string[];
|
|
60
|
+
reply_to: string[];
|
|
26
61
|
subject: string;
|
|
27
62
|
status: string;
|
|
28
63
|
last_event: string | null;
|
|
29
64
|
bounce_reason: string | null;
|
|
65
|
+
tags: unknown;
|
|
66
|
+
scheduled_at: string | null;
|
|
67
|
+
cancelled_at: string | null;
|
|
30
68
|
created_at: string;
|
|
31
69
|
sent_at: string | null;
|
|
32
70
|
delivered_at: string | null;
|
|
@@ -71,7 +109,7 @@ type CreateApiKeyResult = {
|
|
|
71
109
|
token: string;
|
|
72
110
|
created_at: string;
|
|
73
111
|
};
|
|
74
|
-
type WebhookEventType = 'email.delivered' | 'email.bounced';
|
|
112
|
+
type WebhookEventType = 'email.sent' | 'email.delivered' | 'email.delivery_delayed' | 'email.bounced' | 'email.complained' | 'email.opened' | 'email.clicked' | 'email.failed' | 'email.suppressed' | 'email.scheduled';
|
|
75
113
|
type WebhookEndpoint = {
|
|
76
114
|
id: string;
|
|
77
115
|
url: string;
|
|
@@ -84,10 +122,37 @@ type CreateWebhookParams = {
|
|
|
84
122
|
url: string;
|
|
85
123
|
events?: WebhookEventType[];
|
|
86
124
|
};
|
|
125
|
+
type UpdateWebhookParams = {
|
|
126
|
+
url?: string;
|
|
127
|
+
events?: WebhookEventType[];
|
|
128
|
+
enabled?: boolean;
|
|
129
|
+
};
|
|
87
130
|
type WebhookEndpointWithSecret = {
|
|
88
131
|
webhook: WebhookEndpoint;
|
|
89
132
|
secret: string;
|
|
90
133
|
};
|
|
134
|
+
type Suppression = {
|
|
135
|
+
id: string;
|
|
136
|
+
email: string;
|
|
137
|
+
reason: string | null;
|
|
138
|
+
source: string;
|
|
139
|
+
created_at: string;
|
|
140
|
+
updated_at: string;
|
|
141
|
+
};
|
|
142
|
+
type ListSuppressionsParams = {
|
|
143
|
+
limit?: number;
|
|
144
|
+
cursor?: string;
|
|
145
|
+
email?: string;
|
|
146
|
+
};
|
|
147
|
+
type ListSuppressionsResult = {
|
|
148
|
+
data: Suppression[];
|
|
149
|
+
has_more: boolean;
|
|
150
|
+
next_cursor: string | null;
|
|
151
|
+
};
|
|
152
|
+
type CreateSuppressionParams = {
|
|
153
|
+
email: string;
|
|
154
|
+
reason?: string;
|
|
155
|
+
};
|
|
91
156
|
type SuperSendTXOptions = {
|
|
92
157
|
baseUrl?: string;
|
|
93
158
|
fetch?: typeof fetch;
|
|
@@ -99,6 +164,8 @@ type Domain = {
|
|
|
99
164
|
status: DomainStatus | string;
|
|
100
165
|
created_at: string;
|
|
101
166
|
verified_at: string | null;
|
|
167
|
+
open_tracking?: boolean;
|
|
168
|
+
click_tracking?: boolean;
|
|
102
169
|
};
|
|
103
170
|
type DnsRecord = {
|
|
104
171
|
type: string;
|
|
@@ -197,6 +264,10 @@ declare class EmailsResource {
|
|
|
197
264
|
email: EmailListItem;
|
|
198
265
|
}>;
|
|
199
266
|
send(params: SendEmailParams): Promise<SendEmailResult>;
|
|
267
|
+
batch(emails: SendEmailParams[]): Promise<BatchSendEmailResult>;
|
|
268
|
+
update(id: string, params: UpdateEmailParams): Promise<SendEmailResult>;
|
|
269
|
+
cancel(id: string): Promise<SendEmailResult>;
|
|
270
|
+
private serializeSendParams;
|
|
200
271
|
}
|
|
201
272
|
|
|
202
273
|
declare class KeysResource {
|
|
@@ -209,6 +280,19 @@ declare class KeysResource {
|
|
|
209
280
|
}>;
|
|
210
281
|
}
|
|
211
282
|
|
|
283
|
+
declare class SuppressionsResource {
|
|
284
|
+
private readonly client;
|
|
285
|
+
constructor(client: SuperSendTX);
|
|
286
|
+
list(params?: ListSuppressionsParams): Promise<ListSuppressionsResult>;
|
|
287
|
+
create(params: CreateSuppressionParams): Promise<{
|
|
288
|
+
suppression: Suppression;
|
|
289
|
+
}>;
|
|
290
|
+
/** Remove by suppression id or email address. */
|
|
291
|
+
remove(idOrEmail: string): Promise<{
|
|
292
|
+
ok: boolean;
|
|
293
|
+
}>;
|
|
294
|
+
}
|
|
295
|
+
|
|
212
296
|
declare class WebhooksResource {
|
|
213
297
|
private readonly client;
|
|
214
298
|
constructor(client: SuperSendTX);
|
|
@@ -220,10 +304,18 @@ declare class WebhooksResource {
|
|
|
220
304
|
has_more: boolean;
|
|
221
305
|
next_cursor: string | null;
|
|
222
306
|
}>;
|
|
307
|
+
get(id: string): Promise<{
|
|
308
|
+
webhook: WebhookEndpoint;
|
|
309
|
+
}>;
|
|
223
310
|
create(params: CreateWebhookParams): Promise<WebhookEndpointWithSecret>;
|
|
311
|
+
update(id: string, params: UpdateWebhookParams): Promise<{
|
|
312
|
+
webhook: WebhookEndpoint;
|
|
313
|
+
}>;
|
|
224
314
|
delete(id: string): Promise<{
|
|
225
315
|
ok: boolean;
|
|
226
316
|
}>;
|
|
317
|
+
/** Verify an incoming webhook signature (same as `verifyWebhookSignature`). */
|
|
318
|
+
verify(secret: string, payload: string, header: string | null | undefined, toleranceSec?: number): boolean;
|
|
227
319
|
}
|
|
228
320
|
|
|
229
321
|
declare const DEFAULT_API_BASE_URL = "https://api.supersendtx.com";
|
|
@@ -234,6 +326,7 @@ declare class SuperSendTX {
|
|
|
234
326
|
readonly emails: EmailsResource;
|
|
235
327
|
readonly webhooks: WebhooksResource;
|
|
236
328
|
readonly apiKeys: KeysResource;
|
|
329
|
+
readonly suppressions: SuppressionsResource;
|
|
237
330
|
constructor(apiKey: string, options?: SuperSendTXOptions);
|
|
238
331
|
get baseUrl(): string;
|
|
239
332
|
get fetchImpl(): typeof fetch;
|
|
@@ -252,6 +345,14 @@ declare class SuperSendTXError extends Error {
|
|
|
252
345
|
static fromResponse(status: number, body: ApiErrorBody): SuperSendTXError;
|
|
253
346
|
}
|
|
254
347
|
|
|
348
|
+
declare function signWebhookPayload(secret: string, payload: string, timestamp: number): string;
|
|
349
|
+
declare function buildSignatureHeader(secret: string, payload: string, timestamp?: number): string;
|
|
350
|
+
/**
|
|
351
|
+
* Verify a SuperSend TX webhook signature header (`SuperSendTX-Signature`).
|
|
352
|
+
* Expects HMAC-SHA256 over `${timestamp}.${rawBody}` with the endpoint secret.
|
|
353
|
+
*/
|
|
354
|
+
declare function verifyWebhookSignature(secret: string, payload: string, header: string | null | undefined, toleranceSec?: number): boolean;
|
|
355
|
+
|
|
255
356
|
/** Merge `include:host` into an existing SPF record (or create a minimal one). */
|
|
256
357
|
declare function mergeSpfInclude(existing: string | null | undefined, includeHost: string): string;
|
|
257
358
|
|
|
@@ -282,4 +383,4 @@ declare function applyDnsRecords(input: {
|
|
|
282
383
|
fetchImpl?: typeof fetch;
|
|
283
384
|
}): Promise<ApplyDnsResult>;
|
|
284
385
|
|
|
285
|
-
export { type ApiErrorCode, type ApiKey, type ApiKeyScope, type ApplyDnsParams, type ApplyDnsRecordResult$1 as ApplyDnsRecordResult, type ApplyDnsResult$1 as ApplyDnsResult, type CreateApiKeyParams, type CreateApiKeyResult, type CreateDomainParams, type CreateDomainResult, type CreateWebhookParams, DEFAULT_API_BASE_URL, type DnsProviderName$1 as DnsProviderName, type DnsRecord, type Domain, type DomainStatus, type EmailListItem, type ListApiKeysParams, type ListApiKeysResult, type ListEmailsParams, type ListEmailsResult, type SendEmailParams, type SendEmailResult, SuperSendTX, SuperSendTXError, type SuperSendTXOptions, type VerifyDomainResult, type WebhookEndpoint, type WebhookEndpointWithSecret, type WebhookEventType, applyDnsRecords, mergeSpfInclude };
|
|
386
|
+
export { type ApiErrorCode, type ApiKey, type ApiKeyScope, type ApplyDnsParams, type ApplyDnsRecordResult$1 as ApplyDnsRecordResult, type ApplyDnsResult$1 as ApplyDnsResult, type BatchSendEmailResult, type CreateApiKeyParams, type CreateApiKeyResult, type CreateDomainParams, type CreateDomainResult, type CreateSuppressionParams, type CreateWebhookParams, DEFAULT_API_BASE_URL, type DnsProviderName$1 as DnsProviderName, type DnsRecord, type Domain, type DomainStatus, type EmailListItem, type ListApiKeysParams, type ListApiKeysResult, type ListEmailsParams, type ListEmailsResult, type ListSuppressionsParams, type ListSuppressionsResult, type SendEmailParams, type SendEmailResult, SuperSendTX, SuperSendTXError, type SuperSendTXOptions, type Suppression, type UpdateEmailParams, type UpdateWebhookParams, type VerifyDomainResult, type WebhookEndpoint, type WebhookEndpointWithSecret, type WebhookEventType, applyDnsRecords, buildSignatureHeader, mergeSpfInclude, signWebhookPayload, verifyWebhookSignature };
|
package/dist/index.js
CHANGED
|
@@ -427,12 +427,20 @@ var EmailsResource = class {
|
|
|
427
427
|
to: params.to,
|
|
428
428
|
subject: params.subject
|
|
429
429
|
};
|
|
430
|
-
if (params.html) payload.html = params.html;
|
|
431
|
-
if (params.text) payload.text = params.text;
|
|
430
|
+
if (params.html !== void 0) payload.html = params.html;
|
|
431
|
+
if (params.text !== void 0) payload.text = params.text;
|
|
432
432
|
const replyTo = params.replyTo ?? params.reply_to;
|
|
433
|
-
if (replyTo) payload.reply_to = replyTo;
|
|
434
|
-
if (params.cc) payload.cc = params.cc;
|
|
435
|
-
if (params.bcc) payload.bcc = params.bcc;
|
|
433
|
+
if (replyTo !== void 0) payload.reply_to = replyTo;
|
|
434
|
+
if (params.cc !== void 0) payload.cc = params.cc;
|
|
435
|
+
if (params.bcc !== void 0) payload.bcc = params.bcc;
|
|
436
|
+
if (params.tags !== void 0) payload.tags = params.tags;
|
|
437
|
+
if (params.headers !== void 0) payload.headers = params.headers;
|
|
438
|
+
if (params.tag !== void 0) payload.tag = params.tag;
|
|
439
|
+
if (params.attachments !== void 0) payload.attachments = params.attachments;
|
|
440
|
+
const scheduledAt = params.scheduledAt ?? params.scheduled_at;
|
|
441
|
+
if (scheduledAt !== void 0) {
|
|
442
|
+
payload.scheduled_at = scheduledAt instanceof Date ? scheduledAt.toISOString() : scheduledAt;
|
|
443
|
+
}
|
|
436
444
|
const headers = {};
|
|
437
445
|
if (params.idempotencyKey) {
|
|
438
446
|
headers["Idempotency-Key"] = params.idempotencyKey;
|
|
@@ -443,6 +451,49 @@ var EmailsResource = class {
|
|
|
443
451
|
body: JSON.stringify(payload)
|
|
444
452
|
});
|
|
445
453
|
}
|
|
454
|
+
async batch(emails) {
|
|
455
|
+
return this.client.request("/emails/batch", {
|
|
456
|
+
method: "POST",
|
|
457
|
+
body: JSON.stringify({ emails: emails.map((email) => this.serializeSendParams(email)) })
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
async update(id, params) {
|
|
461
|
+
const payload = {};
|
|
462
|
+
if (params.cancel !== void 0) payload.cancel = params.cancel;
|
|
463
|
+
const scheduledAt = params.scheduledAt ?? params.scheduled_at;
|
|
464
|
+
if (scheduledAt !== void 0) {
|
|
465
|
+
payload.scheduled_at = scheduledAt instanceof Date ? scheduledAt.toISOString() : scheduledAt;
|
|
466
|
+
}
|
|
467
|
+
return this.client.request(`/emails/${encodeURIComponent(id)}`, {
|
|
468
|
+
method: "PATCH",
|
|
469
|
+
body: JSON.stringify(payload)
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
async cancel(id) {
|
|
473
|
+
return this.update(id, { cancel: true });
|
|
474
|
+
}
|
|
475
|
+
serializeSendParams(params) {
|
|
476
|
+
const payload = {
|
|
477
|
+
from: params.from,
|
|
478
|
+
to: params.to,
|
|
479
|
+
subject: params.subject
|
|
480
|
+
};
|
|
481
|
+
if (params.html !== void 0) payload.html = params.html;
|
|
482
|
+
if (params.text !== void 0) payload.text = params.text;
|
|
483
|
+
const replyTo = params.replyTo ?? params.reply_to;
|
|
484
|
+
if (replyTo !== void 0) payload.reply_to = replyTo;
|
|
485
|
+
if (params.cc !== void 0) payload.cc = params.cc;
|
|
486
|
+
if (params.bcc !== void 0) payload.bcc = params.bcc;
|
|
487
|
+
if (params.tags !== void 0) payload.tags = params.tags;
|
|
488
|
+
if (params.headers !== void 0) payload.headers = params.headers;
|
|
489
|
+
if (params.tag !== void 0) payload.tag = params.tag;
|
|
490
|
+
if (params.attachments !== void 0) payload.attachments = params.attachments;
|
|
491
|
+
const scheduledAt = params.scheduledAt ?? params.scheduled_at;
|
|
492
|
+
if (scheduledAt !== void 0) {
|
|
493
|
+
payload.scheduled_at = scheduledAt instanceof Date ? scheduledAt.toISOString() : scheduledAt;
|
|
494
|
+
}
|
|
495
|
+
return payload;
|
|
496
|
+
}
|
|
446
497
|
};
|
|
447
498
|
|
|
448
499
|
// src/keys.ts
|
|
@@ -475,7 +526,69 @@ var KeysResource = class {
|
|
|
475
526
|
}
|
|
476
527
|
};
|
|
477
528
|
|
|
478
|
-
// src/
|
|
529
|
+
// src/suppressions.ts
|
|
530
|
+
var SuppressionsResource = class {
|
|
531
|
+
constructor(client) {
|
|
532
|
+
this.client = client;
|
|
533
|
+
}
|
|
534
|
+
async list(params = {}) {
|
|
535
|
+
const search = new URLSearchParams();
|
|
536
|
+
if (params.limit != null) search.set("limit", String(params.limit));
|
|
537
|
+
if (params.cursor) search.set("cursor", params.cursor);
|
|
538
|
+
if (params.email) search.set("email", params.email);
|
|
539
|
+
const query = search.toString();
|
|
540
|
+
return this.client.request(`/suppressions${query ? `?${query}` : ""}`, { method: "GET" });
|
|
541
|
+
}
|
|
542
|
+
async create(params) {
|
|
543
|
+
return this.client.request("/suppressions", {
|
|
544
|
+
method: "POST",
|
|
545
|
+
body: JSON.stringify(params)
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
/** Remove by suppression id or email address. */
|
|
549
|
+
async remove(idOrEmail) {
|
|
550
|
+
if (idOrEmail.includes("@")) {
|
|
551
|
+
return this.client.request(`/suppressions?email=${encodeURIComponent(idOrEmail)}`, {
|
|
552
|
+
method: "DELETE"
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
return this.client.request(`/suppressions/${encodeURIComponent(idOrEmail)}`, {
|
|
556
|
+
method: "DELETE"
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
// src/webhooks/verify.ts
|
|
562
|
+
import { createHmac, timingSafeEqual } from "crypto";
|
|
563
|
+
function signWebhookPayload(secret, payload, timestamp) {
|
|
564
|
+
const signed = `${timestamp}.${payload}`;
|
|
565
|
+
return createHmac("sha256", secret).update(signed).digest("hex");
|
|
566
|
+
}
|
|
567
|
+
function buildSignatureHeader(secret, payload, timestamp = Math.floor(Date.now() / 1e3)) {
|
|
568
|
+
const signature = signWebhookPayload(secret, payload, timestamp);
|
|
569
|
+
return `t=${timestamp},v1=${signature}`;
|
|
570
|
+
}
|
|
571
|
+
function verifyWebhookSignature(secret, payload, header, toleranceSec = 300) {
|
|
572
|
+
if (!header) return false;
|
|
573
|
+
const parts = Object.fromEntries(
|
|
574
|
+
header.split(",").map((part) => {
|
|
575
|
+
const [key, value] = part.trim().split("=");
|
|
576
|
+
return [key, value];
|
|
577
|
+
})
|
|
578
|
+
);
|
|
579
|
+
const timestamp = Number(parts.t);
|
|
580
|
+
const signature = parts.v1;
|
|
581
|
+
if (!timestamp || !signature) return false;
|
|
582
|
+
if (Math.abs(Math.floor(Date.now() / 1e3) - timestamp) > toleranceSec) return false;
|
|
583
|
+
const expected = signWebhookPayload(secret, payload, timestamp);
|
|
584
|
+
try {
|
|
585
|
+
return timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
|
|
586
|
+
} catch {
|
|
587
|
+
return false;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// src/webhooks/index.ts
|
|
479
592
|
var WebhooksResource = class {
|
|
480
593
|
constructor(client) {
|
|
481
594
|
this.client = client;
|
|
@@ -487,15 +600,28 @@ var WebhooksResource = class {
|
|
|
487
600
|
const query = search.toString();
|
|
488
601
|
return this.client.request(`/webhooks${query ? `?${query}` : ""}`, { method: "GET" });
|
|
489
602
|
}
|
|
603
|
+
async get(id) {
|
|
604
|
+
return this.client.request(`/webhooks/${encodeURIComponent(id)}`, { method: "GET" });
|
|
605
|
+
}
|
|
490
606
|
async create(params) {
|
|
491
607
|
return this.client.request("/webhooks", {
|
|
492
608
|
method: "POST",
|
|
493
609
|
body: JSON.stringify(params)
|
|
494
610
|
});
|
|
495
611
|
}
|
|
612
|
+
async update(id, params) {
|
|
613
|
+
return this.client.request(`/webhooks/${encodeURIComponent(id)}`, {
|
|
614
|
+
method: "PATCH",
|
|
615
|
+
body: JSON.stringify(params)
|
|
616
|
+
});
|
|
617
|
+
}
|
|
496
618
|
async delete(id) {
|
|
497
619
|
return this.client.request(`/webhooks/${id}`, { method: "DELETE" });
|
|
498
620
|
}
|
|
621
|
+
/** Verify an incoming webhook signature (same as `verifyWebhookSignature`). */
|
|
622
|
+
verify(secret, payload, header, toleranceSec = 300) {
|
|
623
|
+
return verifyWebhookSignature(secret, payload, header, toleranceSec);
|
|
624
|
+
}
|
|
499
625
|
};
|
|
500
626
|
|
|
501
627
|
// src/client.ts
|
|
@@ -511,6 +637,7 @@ var SuperSendTX = class {
|
|
|
511
637
|
this.emails = new EmailsResource(this);
|
|
512
638
|
this.webhooks = new WebhooksResource(this);
|
|
513
639
|
this.apiKeys = new KeysResource(this);
|
|
640
|
+
this.suppressions = new SuppressionsResource(this);
|
|
514
641
|
}
|
|
515
642
|
get baseUrl() {
|
|
516
643
|
return (this.options.baseUrl || DEFAULT_API_BASE_URL).replace(/\/$/, "");
|
|
@@ -539,5 +666,8 @@ export {
|
|
|
539
666
|
SuperSendTX,
|
|
540
667
|
SuperSendTXError,
|
|
541
668
|
applyDnsRecords,
|
|
542
|
-
|
|
669
|
+
buildSignatureHeader,
|
|
670
|
+
mergeSpfInclude,
|
|
671
|
+
signWebhookPayload,
|
|
672
|
+
verifyWebhookSignature
|
|
543
673
|
};
|