@masters-union/outbound-sdk 0.1.2 → 0.1.4
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 +29 -19
- package/dist/index.d.mts +34 -31
- package/dist/index.d.ts +34 -31
- package/dist/index.js +69 -70
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +69 -70
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,18 +11,12 @@ npm install outbound-sdk
|
|
|
11
11
|
## Quick Start
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
-
import {
|
|
14
|
+
import { Outbound } from 'outbound-sdk';
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
baseUrl: 'https://api.your-domain.com', // or set OUTBOUND_API_URL env var
|
|
19
|
-
});
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
### Send an Email
|
|
16
|
+
// Single tenant — set API key once
|
|
17
|
+
const outbound = new Outbound({ apiKey: 'mu_outbound_...' });
|
|
23
18
|
|
|
24
|
-
|
|
25
|
-
const { jobId, messageId } = await outbound.email.send({
|
|
19
|
+
const { jobId } = await outbound.email.send({
|
|
26
20
|
toEmail: 'user@example.com',
|
|
27
21
|
fromEmail: 'noreply@company.com',
|
|
28
22
|
emailSubject: 'Welcome!',
|
|
@@ -30,6 +24,22 @@ const { jobId, messageId } = await outbound.email.send({
|
|
|
30
24
|
});
|
|
31
25
|
```
|
|
32
26
|
|
|
27
|
+
### Multi-Tenant Usage
|
|
28
|
+
|
|
29
|
+
For applications that manage multiple tenants, create one client and pass the API key per call:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
const outbound = new Outbound(); // no default apiKey
|
|
33
|
+
|
|
34
|
+
const tenantAKey = 'mu_outbound_tenant_a_...';
|
|
35
|
+
const tenantBKey = 'mu_outbound_tenant_b_...';
|
|
36
|
+
|
|
37
|
+
await outbound.email.send({ toEmail: '...', ... }, { apiKey: tenantAKey });
|
|
38
|
+
await outbound.email.send({ toEmail: '...', ... }, { apiKey: tenantBKey });
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
A per-call `apiKey` always takes priority over the constructor default.
|
|
42
|
+
|
|
33
43
|
### Send Bulk Emails
|
|
34
44
|
|
|
35
45
|
```ts
|
|
@@ -113,7 +123,7 @@ const { webhook, secret } = await outbound.webhooks.create({
|
|
|
113
123
|
// Store `secret` securely for signature verification
|
|
114
124
|
|
|
115
125
|
// Verify incoming webhook
|
|
116
|
-
const isValid =
|
|
126
|
+
const isValid = Outbound.verifyWebhookSignature(rawBody, signatureHeader, secret);
|
|
117
127
|
```
|
|
118
128
|
|
|
119
129
|
### Dashboard
|
|
@@ -128,20 +138,20 @@ const quota = await outbound.dashboard.quota();
|
|
|
128
138
|
|
|
129
139
|
## Configuration
|
|
130
140
|
|
|
131
|
-
| Option |
|
|
132
|
-
|
|
133
|
-
| `apiKey` |
|
|
134
|
-
| `baseUrl` | `
|
|
135
|
-
| `timeout` |
|
|
136
|
-
| `maxRetries` |
|
|
137
|
-
| `retryDelay` |
|
|
141
|
+
| Option | Default | Description |
|
|
142
|
+
|--------|---------|-------------|
|
|
143
|
+
| `apiKey` | — | Default API key (optional if provided per call) |
|
|
144
|
+
| `baseUrl` | `https://outbound-api.mastersunion.org` | API base URL |
|
|
145
|
+
| `timeout` | `30000` | Request timeout in ms |
|
|
146
|
+
| `maxRetries` | `3` | Max retries on 429/5xx |
|
|
147
|
+
| `retryDelay` | `1000` | Initial retry delay in ms (exponential backoff) |
|
|
138
148
|
|
|
139
149
|
## Error Handling
|
|
140
150
|
|
|
141
151
|
All errors extend `OutboundError` with `statusCode`, `message`, and `details`:
|
|
142
152
|
|
|
143
153
|
```ts
|
|
144
|
-
import {
|
|
154
|
+
import { Outbound, RateLimitError, NotFoundError } from 'outbound-sdk';
|
|
145
155
|
|
|
146
156
|
try {
|
|
147
157
|
await outbound.email.send({ ... });
|
package/dist/index.d.mts
CHANGED
|
@@ -6,12 +6,15 @@ interface OutboundConfig {
|
|
|
6
6
|
retryDelay?: number;
|
|
7
7
|
}
|
|
8
8
|
interface ResolvedConfig {
|
|
9
|
-
apiKey
|
|
9
|
+
apiKey?: string;
|
|
10
10
|
baseUrl: string;
|
|
11
11
|
timeout: number;
|
|
12
12
|
maxRetries: number;
|
|
13
13
|
retryDelay: number;
|
|
14
14
|
}
|
|
15
|
+
interface RequestOverrides {
|
|
16
|
+
apiKey?: string;
|
|
17
|
+
}
|
|
15
18
|
interface SendEmailParams {
|
|
16
19
|
toEmail: string;
|
|
17
20
|
fromEmail: string;
|
|
@@ -298,10 +301,11 @@ interface QuotaResponse {
|
|
|
298
301
|
declare class HttpClient {
|
|
299
302
|
private config;
|
|
300
303
|
constructor(config: ResolvedConfig);
|
|
301
|
-
get<T>(path: string, params?: Record<string, unknown
|
|
302
|
-
post<T>(path: string, body?: unknown): Promise<T>;
|
|
303
|
-
patch<T>(path: string, body?: unknown): Promise<T>;
|
|
304
|
-
delete<T>(path: string): Promise<T>;
|
|
304
|
+
get<T>(path: string, params?: Record<string, unknown>, apiKey?: string): Promise<T>;
|
|
305
|
+
post<T>(path: string, body?: unknown, apiKey?: string): Promise<T>;
|
|
306
|
+
patch<T>(path: string, body?: unknown, apiKey?: string): Promise<T>;
|
|
307
|
+
delete<T>(path: string, apiKey?: string): Promise<T>;
|
|
308
|
+
private resolveApiKey;
|
|
305
309
|
private request;
|
|
306
310
|
private buildUrl;
|
|
307
311
|
private parseError;
|
|
@@ -311,39 +315,39 @@ declare class HttpClient {
|
|
|
311
315
|
declare class EmailResource {
|
|
312
316
|
private http;
|
|
313
317
|
constructor(http: HttpClient);
|
|
314
|
-
send(params: SendEmailParams): Promise<SendEmailResponse>;
|
|
315
|
-
bulk(params: BulkEmailParams): Promise<BulkEmailResponse>;
|
|
316
|
-
status(jobId: string): Promise<JobStatusResponse>;
|
|
318
|
+
send(params: SendEmailParams, overrides?: RequestOverrides): Promise<SendEmailResponse>;
|
|
319
|
+
bulk(params: BulkEmailParams, overrides?: RequestOverrides): Promise<BulkEmailResponse>;
|
|
320
|
+
status(jobId: string, overrides?: RequestOverrides): Promise<JobStatusResponse>;
|
|
317
321
|
}
|
|
318
322
|
|
|
319
323
|
declare class TemplatesResource {
|
|
320
324
|
private http;
|
|
321
325
|
constructor(http: HttpClient);
|
|
322
|
-
create(params: CreateTemplateParams): Promise<TemplateResponse>;
|
|
323
|
-
list(params?: ListTemplatesParams): Promise<ListTemplatesResponse>;
|
|
324
|
-
listAll(params?: Omit<ListTemplatesParams, 'page'
|
|
325
|
-
get(id: string): Promise<TemplateResponse>;
|
|
326
|
-
update(id: string, params: UpdateTemplateParams): Promise<TemplateResponse>;
|
|
327
|
-
delete(id: string): Promise<{
|
|
326
|
+
create(params: CreateTemplateParams, overrides?: RequestOverrides): Promise<TemplateResponse>;
|
|
327
|
+
list(params?: ListTemplatesParams, overrides?: RequestOverrides): Promise<ListTemplatesResponse>;
|
|
328
|
+
listAll(params?: Omit<ListTemplatesParams, 'page'>, overrides?: RequestOverrides): AsyncGenerator<Template>;
|
|
329
|
+
get(id: string, overrides?: RequestOverrides): Promise<TemplateResponse>;
|
|
330
|
+
update(id: string, params: UpdateTemplateParams, overrides?: RequestOverrides): Promise<TemplateResponse>;
|
|
331
|
+
delete(id: string, overrides?: RequestOverrides): Promise<{
|
|
328
332
|
message: string;
|
|
329
333
|
id: string;
|
|
330
334
|
}>;
|
|
331
335
|
duplicate(id: string, params?: {
|
|
332
336
|
name?: string;
|
|
333
|
-
}): Promise<TemplateResponse>;
|
|
334
|
-
preview(id: string, params?: TemplatePreviewParams): Promise<TemplatePreviewResponse>;
|
|
335
|
-
send(params: TemplateSendParams): Promise<SendEmailResponse>;
|
|
336
|
-
bulkSend(params: TemplateBulkSendParams): Promise<TemplateBulkSendResponse>;
|
|
337
|
-
stats(): Promise<TemplateStatsResponse>;
|
|
337
|
+
}, overrides?: RequestOverrides): Promise<TemplateResponse>;
|
|
338
|
+
preview(id: string, params?: TemplatePreviewParams, overrides?: RequestOverrides): Promise<TemplatePreviewResponse>;
|
|
339
|
+
send(params: TemplateSendParams, overrides?: RequestOverrides): Promise<SendEmailResponse>;
|
|
340
|
+
bulkSend(params: TemplateBulkSendParams, overrides?: RequestOverrides): Promise<TemplateBulkSendResponse>;
|
|
341
|
+
stats(overrides?: RequestOverrides): Promise<TemplateStatsResponse>;
|
|
338
342
|
}
|
|
339
343
|
|
|
340
344
|
declare class SuppressionsResource {
|
|
341
345
|
private http;
|
|
342
346
|
constructor(http: HttpClient);
|
|
343
|
-
list(params?: ListSuppressionsParams): Promise<ListSuppressionsResponse>;
|
|
344
|
-
listAll(params?: Omit<ListSuppressionsParams, 'page'
|
|
345
|
-
add(params: AddSuppressionParams): Promise<SuppressionResponse>;
|
|
346
|
-
remove(email: string): Promise<{
|
|
347
|
+
list(params?: ListSuppressionsParams, overrides?: RequestOverrides): Promise<ListSuppressionsResponse>;
|
|
348
|
+
listAll(params?: Omit<ListSuppressionsParams, 'page'>, overrides?: RequestOverrides): AsyncGenerator<Suppression>;
|
|
349
|
+
add(params: AddSuppressionParams, overrides?: RequestOverrides): Promise<SuppressionResponse>;
|
|
350
|
+
remove(email: string, overrides?: RequestOverrides): Promise<{
|
|
347
351
|
message: string;
|
|
348
352
|
}>;
|
|
349
353
|
}
|
|
@@ -351,10 +355,10 @@ declare class SuppressionsResource {
|
|
|
351
355
|
declare class WebhooksResource {
|
|
352
356
|
private http;
|
|
353
357
|
constructor(http: HttpClient);
|
|
354
|
-
create(params: CreateWebhookParams): Promise<CreateWebhookResponse>;
|
|
355
|
-
list(): Promise<ListWebhooksResponse>;
|
|
356
|
-
update(id: string, params: UpdateWebhookParams): Promise<UpdateWebhookResponse>;
|
|
357
|
-
delete(id: string): Promise<{
|
|
358
|
+
create(params: CreateWebhookParams, overrides?: RequestOverrides): Promise<CreateWebhookResponse>;
|
|
359
|
+
list(overrides?: RequestOverrides): Promise<ListWebhooksResponse>;
|
|
360
|
+
update(id: string, params: UpdateWebhookParams, overrides?: RequestOverrides): Promise<UpdateWebhookResponse>;
|
|
361
|
+
delete(id: string, overrides?: RequestOverrides): Promise<{
|
|
358
362
|
message: string;
|
|
359
363
|
id: string;
|
|
360
364
|
}>;
|
|
@@ -363,8 +367,8 @@ declare class WebhooksResource {
|
|
|
363
367
|
declare class DashboardResource {
|
|
364
368
|
private http;
|
|
365
369
|
constructor(http: HttpClient);
|
|
366
|
-
get(): Promise<DashboardResponse>;
|
|
367
|
-
quota(): Promise<QuotaResponse>;
|
|
370
|
+
get(overrides?: RequestOverrides): Promise<DashboardResponse>;
|
|
371
|
+
quota(overrides?: RequestOverrides): Promise<QuotaResponse>;
|
|
368
372
|
}
|
|
369
373
|
|
|
370
374
|
declare class Outbound {
|
|
@@ -379,7 +383,6 @@ declare class Outbound {
|
|
|
379
383
|
* Use this in your webhook handler to validate incoming requests.
|
|
380
384
|
*/
|
|
381
385
|
static verifyWebhookSignature(payload: string | Buffer, signature: string, secret: string): boolean;
|
|
382
|
-
private getEnv;
|
|
383
386
|
}
|
|
384
387
|
|
|
385
388
|
declare class OutboundError extends Error {
|
|
@@ -417,4 +420,4 @@ declare class NetworkError extends OutboundError {
|
|
|
417
420
|
constructor(message?: string);
|
|
418
421
|
}
|
|
419
422
|
|
|
420
|
-
export { type AddSuppressionParams, type Attachment, AuthenticationError, BadRequestError, type BulkEmailParams, type BulkEmailRecipient, type BulkEmailResponse, ConflictError, type CreateTemplateParams, type CreateWebhookParams, type CreateWebhookResponse, type DashboardResponse, type EmailRecipientStatus, type EmailStatus, ForbiddenError, type JobStatusResponse, type ListSuppressionsParams, type ListSuppressionsResponse, type ListTemplatesParams, type ListTemplatesResponse, type ListWebhooksResponse, NetworkError, NotFoundError, Outbound, type OutboundConfig, OutboundError, type QuotaResponse, RateLimitError, type ResolvedConfig, type SendEmailParams, type SendEmailResponse, ServerError, type Suppression, type SuppressionResponse, type Template, type TemplateBulkRecipient, type TemplateBulkSendParams, type TemplateBulkSendResponse, type TemplatePreviewParams, type TemplatePreviewResponse, type TemplateResponse, type TemplateSendParams, type TemplateStatsResponse, TimeoutError, type UpdateTemplateParams, type UpdateWebhookParams, type UpdateWebhookResponse, type Webhook, type WebhookEvent };
|
|
423
|
+
export { type AddSuppressionParams, type Attachment, AuthenticationError, BadRequestError, type BulkEmailParams, type BulkEmailRecipient, type BulkEmailResponse, ConflictError, type CreateTemplateParams, type CreateWebhookParams, type CreateWebhookResponse, type DashboardResponse, type EmailRecipientStatus, type EmailStatus, ForbiddenError, type JobStatusResponse, type ListSuppressionsParams, type ListSuppressionsResponse, type ListTemplatesParams, type ListTemplatesResponse, type ListWebhooksResponse, NetworkError, NotFoundError, Outbound, type OutboundConfig, OutboundError, type QuotaResponse, RateLimitError, type RequestOverrides, type ResolvedConfig, type SendEmailParams, type SendEmailResponse, ServerError, type Suppression, type SuppressionResponse, type Template, type TemplateBulkRecipient, type TemplateBulkSendParams, type TemplateBulkSendResponse, type TemplatePreviewParams, type TemplatePreviewResponse, type TemplateResponse, type TemplateSendParams, type TemplateStatsResponse, TimeoutError, type UpdateTemplateParams, type UpdateWebhookParams, type UpdateWebhookResponse, type Webhook, type WebhookEvent };
|
package/dist/index.d.ts
CHANGED
|
@@ -6,12 +6,15 @@ interface OutboundConfig {
|
|
|
6
6
|
retryDelay?: number;
|
|
7
7
|
}
|
|
8
8
|
interface ResolvedConfig {
|
|
9
|
-
apiKey
|
|
9
|
+
apiKey?: string;
|
|
10
10
|
baseUrl: string;
|
|
11
11
|
timeout: number;
|
|
12
12
|
maxRetries: number;
|
|
13
13
|
retryDelay: number;
|
|
14
14
|
}
|
|
15
|
+
interface RequestOverrides {
|
|
16
|
+
apiKey?: string;
|
|
17
|
+
}
|
|
15
18
|
interface SendEmailParams {
|
|
16
19
|
toEmail: string;
|
|
17
20
|
fromEmail: string;
|
|
@@ -298,10 +301,11 @@ interface QuotaResponse {
|
|
|
298
301
|
declare class HttpClient {
|
|
299
302
|
private config;
|
|
300
303
|
constructor(config: ResolvedConfig);
|
|
301
|
-
get<T>(path: string, params?: Record<string, unknown
|
|
302
|
-
post<T>(path: string, body?: unknown): Promise<T>;
|
|
303
|
-
patch<T>(path: string, body?: unknown): Promise<T>;
|
|
304
|
-
delete<T>(path: string): Promise<T>;
|
|
304
|
+
get<T>(path: string, params?: Record<string, unknown>, apiKey?: string): Promise<T>;
|
|
305
|
+
post<T>(path: string, body?: unknown, apiKey?: string): Promise<T>;
|
|
306
|
+
patch<T>(path: string, body?: unknown, apiKey?: string): Promise<T>;
|
|
307
|
+
delete<T>(path: string, apiKey?: string): Promise<T>;
|
|
308
|
+
private resolveApiKey;
|
|
305
309
|
private request;
|
|
306
310
|
private buildUrl;
|
|
307
311
|
private parseError;
|
|
@@ -311,39 +315,39 @@ declare class HttpClient {
|
|
|
311
315
|
declare class EmailResource {
|
|
312
316
|
private http;
|
|
313
317
|
constructor(http: HttpClient);
|
|
314
|
-
send(params: SendEmailParams): Promise<SendEmailResponse>;
|
|
315
|
-
bulk(params: BulkEmailParams): Promise<BulkEmailResponse>;
|
|
316
|
-
status(jobId: string): Promise<JobStatusResponse>;
|
|
318
|
+
send(params: SendEmailParams, overrides?: RequestOverrides): Promise<SendEmailResponse>;
|
|
319
|
+
bulk(params: BulkEmailParams, overrides?: RequestOverrides): Promise<BulkEmailResponse>;
|
|
320
|
+
status(jobId: string, overrides?: RequestOverrides): Promise<JobStatusResponse>;
|
|
317
321
|
}
|
|
318
322
|
|
|
319
323
|
declare class TemplatesResource {
|
|
320
324
|
private http;
|
|
321
325
|
constructor(http: HttpClient);
|
|
322
|
-
create(params: CreateTemplateParams): Promise<TemplateResponse>;
|
|
323
|
-
list(params?: ListTemplatesParams): Promise<ListTemplatesResponse>;
|
|
324
|
-
listAll(params?: Omit<ListTemplatesParams, 'page'
|
|
325
|
-
get(id: string): Promise<TemplateResponse>;
|
|
326
|
-
update(id: string, params: UpdateTemplateParams): Promise<TemplateResponse>;
|
|
327
|
-
delete(id: string): Promise<{
|
|
326
|
+
create(params: CreateTemplateParams, overrides?: RequestOverrides): Promise<TemplateResponse>;
|
|
327
|
+
list(params?: ListTemplatesParams, overrides?: RequestOverrides): Promise<ListTemplatesResponse>;
|
|
328
|
+
listAll(params?: Omit<ListTemplatesParams, 'page'>, overrides?: RequestOverrides): AsyncGenerator<Template>;
|
|
329
|
+
get(id: string, overrides?: RequestOverrides): Promise<TemplateResponse>;
|
|
330
|
+
update(id: string, params: UpdateTemplateParams, overrides?: RequestOverrides): Promise<TemplateResponse>;
|
|
331
|
+
delete(id: string, overrides?: RequestOverrides): Promise<{
|
|
328
332
|
message: string;
|
|
329
333
|
id: string;
|
|
330
334
|
}>;
|
|
331
335
|
duplicate(id: string, params?: {
|
|
332
336
|
name?: string;
|
|
333
|
-
}): Promise<TemplateResponse>;
|
|
334
|
-
preview(id: string, params?: TemplatePreviewParams): Promise<TemplatePreviewResponse>;
|
|
335
|
-
send(params: TemplateSendParams): Promise<SendEmailResponse>;
|
|
336
|
-
bulkSend(params: TemplateBulkSendParams): Promise<TemplateBulkSendResponse>;
|
|
337
|
-
stats(): Promise<TemplateStatsResponse>;
|
|
337
|
+
}, overrides?: RequestOverrides): Promise<TemplateResponse>;
|
|
338
|
+
preview(id: string, params?: TemplatePreviewParams, overrides?: RequestOverrides): Promise<TemplatePreviewResponse>;
|
|
339
|
+
send(params: TemplateSendParams, overrides?: RequestOverrides): Promise<SendEmailResponse>;
|
|
340
|
+
bulkSend(params: TemplateBulkSendParams, overrides?: RequestOverrides): Promise<TemplateBulkSendResponse>;
|
|
341
|
+
stats(overrides?: RequestOverrides): Promise<TemplateStatsResponse>;
|
|
338
342
|
}
|
|
339
343
|
|
|
340
344
|
declare class SuppressionsResource {
|
|
341
345
|
private http;
|
|
342
346
|
constructor(http: HttpClient);
|
|
343
|
-
list(params?: ListSuppressionsParams): Promise<ListSuppressionsResponse>;
|
|
344
|
-
listAll(params?: Omit<ListSuppressionsParams, 'page'
|
|
345
|
-
add(params: AddSuppressionParams): Promise<SuppressionResponse>;
|
|
346
|
-
remove(email: string): Promise<{
|
|
347
|
+
list(params?: ListSuppressionsParams, overrides?: RequestOverrides): Promise<ListSuppressionsResponse>;
|
|
348
|
+
listAll(params?: Omit<ListSuppressionsParams, 'page'>, overrides?: RequestOverrides): AsyncGenerator<Suppression>;
|
|
349
|
+
add(params: AddSuppressionParams, overrides?: RequestOverrides): Promise<SuppressionResponse>;
|
|
350
|
+
remove(email: string, overrides?: RequestOverrides): Promise<{
|
|
347
351
|
message: string;
|
|
348
352
|
}>;
|
|
349
353
|
}
|
|
@@ -351,10 +355,10 @@ declare class SuppressionsResource {
|
|
|
351
355
|
declare class WebhooksResource {
|
|
352
356
|
private http;
|
|
353
357
|
constructor(http: HttpClient);
|
|
354
|
-
create(params: CreateWebhookParams): Promise<CreateWebhookResponse>;
|
|
355
|
-
list(): Promise<ListWebhooksResponse>;
|
|
356
|
-
update(id: string, params: UpdateWebhookParams): Promise<UpdateWebhookResponse>;
|
|
357
|
-
delete(id: string): Promise<{
|
|
358
|
+
create(params: CreateWebhookParams, overrides?: RequestOverrides): Promise<CreateWebhookResponse>;
|
|
359
|
+
list(overrides?: RequestOverrides): Promise<ListWebhooksResponse>;
|
|
360
|
+
update(id: string, params: UpdateWebhookParams, overrides?: RequestOverrides): Promise<UpdateWebhookResponse>;
|
|
361
|
+
delete(id: string, overrides?: RequestOverrides): Promise<{
|
|
358
362
|
message: string;
|
|
359
363
|
id: string;
|
|
360
364
|
}>;
|
|
@@ -363,8 +367,8 @@ declare class WebhooksResource {
|
|
|
363
367
|
declare class DashboardResource {
|
|
364
368
|
private http;
|
|
365
369
|
constructor(http: HttpClient);
|
|
366
|
-
get(): Promise<DashboardResponse>;
|
|
367
|
-
quota(): Promise<QuotaResponse>;
|
|
370
|
+
get(overrides?: RequestOverrides): Promise<DashboardResponse>;
|
|
371
|
+
quota(overrides?: RequestOverrides): Promise<QuotaResponse>;
|
|
368
372
|
}
|
|
369
373
|
|
|
370
374
|
declare class Outbound {
|
|
@@ -379,7 +383,6 @@ declare class Outbound {
|
|
|
379
383
|
* Use this in your webhook handler to validate incoming requests.
|
|
380
384
|
*/
|
|
381
385
|
static verifyWebhookSignature(payload: string | Buffer, signature: string, secret: string): boolean;
|
|
382
|
-
private getEnv;
|
|
383
386
|
}
|
|
384
387
|
|
|
385
388
|
declare class OutboundError extends Error {
|
|
@@ -417,4 +420,4 @@ declare class NetworkError extends OutboundError {
|
|
|
417
420
|
constructor(message?: string);
|
|
418
421
|
}
|
|
419
422
|
|
|
420
|
-
export { type AddSuppressionParams, type Attachment, AuthenticationError, BadRequestError, type BulkEmailParams, type BulkEmailRecipient, type BulkEmailResponse, ConflictError, type CreateTemplateParams, type CreateWebhookParams, type CreateWebhookResponse, type DashboardResponse, type EmailRecipientStatus, type EmailStatus, ForbiddenError, type JobStatusResponse, type ListSuppressionsParams, type ListSuppressionsResponse, type ListTemplatesParams, type ListTemplatesResponse, type ListWebhooksResponse, NetworkError, NotFoundError, Outbound, type OutboundConfig, OutboundError, type QuotaResponse, RateLimitError, type ResolvedConfig, type SendEmailParams, type SendEmailResponse, ServerError, type Suppression, type SuppressionResponse, type Template, type TemplateBulkRecipient, type TemplateBulkSendParams, type TemplateBulkSendResponse, type TemplatePreviewParams, type TemplatePreviewResponse, type TemplateResponse, type TemplateSendParams, type TemplateStatsResponse, TimeoutError, type UpdateTemplateParams, type UpdateWebhookParams, type UpdateWebhookResponse, type Webhook, type WebhookEvent };
|
|
423
|
+
export { type AddSuppressionParams, type Attachment, AuthenticationError, BadRequestError, type BulkEmailParams, type BulkEmailRecipient, type BulkEmailResponse, ConflictError, type CreateTemplateParams, type CreateWebhookParams, type CreateWebhookResponse, type DashboardResponse, type EmailRecipientStatus, type EmailStatus, ForbiddenError, type JobStatusResponse, type ListSuppressionsParams, type ListSuppressionsResponse, type ListTemplatesParams, type ListTemplatesResponse, type ListWebhooksResponse, NetworkError, NotFoundError, Outbound, type OutboundConfig, OutboundError, type QuotaResponse, RateLimitError, type RequestOverrides, type ResolvedConfig, type SendEmailParams, type SendEmailResponse, ServerError, type Suppression, type SuppressionResponse, type Template, type TemplateBulkRecipient, type TemplateBulkSendParams, type TemplateBulkSendResponse, type TemplatePreviewParams, type TemplatePreviewResponse, type TemplateResponse, type TemplateSendParams, type TemplateStatsResponse, TimeoutError, type UpdateTemplateParams, type UpdateWebhookParams, type UpdateWebhookResponse, type Webhook, type WebhookEvent };
|
package/dist/index.js
CHANGED
|
@@ -106,19 +106,29 @@ var HttpClient = class {
|
|
|
106
106
|
constructor(config) {
|
|
107
107
|
this.config = config;
|
|
108
108
|
}
|
|
109
|
-
async get(path, params) {
|
|
110
|
-
return this.request("GET", path, { params });
|
|
109
|
+
async get(path, params, apiKey) {
|
|
110
|
+
return this.request("GET", path, { params }, apiKey);
|
|
111
111
|
}
|
|
112
|
-
async post(path, body) {
|
|
113
|
-
return this.request("POST", path, { body });
|
|
112
|
+
async post(path, body, apiKey) {
|
|
113
|
+
return this.request("POST", path, { body }, apiKey);
|
|
114
114
|
}
|
|
115
|
-
async patch(path, body) {
|
|
116
|
-
return this.request("PATCH", path, { body });
|
|
115
|
+
async patch(path, body, apiKey) {
|
|
116
|
+
return this.request("PATCH", path, { body }, apiKey);
|
|
117
117
|
}
|
|
118
|
-
async delete(path) {
|
|
119
|
-
return this.request("DELETE", path);
|
|
118
|
+
async delete(path, apiKey) {
|
|
119
|
+
return this.request("DELETE", path, void 0, apiKey);
|
|
120
120
|
}
|
|
121
|
-
|
|
121
|
+
resolveApiKey(apiKey) {
|
|
122
|
+
const key = apiKey || this.config.apiKey;
|
|
123
|
+
if (!key) {
|
|
124
|
+
throw new AuthenticationError(
|
|
125
|
+
"API key is required. Pass it to the constructor or provide it per method call."
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return key;
|
|
129
|
+
}
|
|
130
|
+
async request(method, path, options, apiKey) {
|
|
131
|
+
const resolvedKey = this.resolveApiKey(apiKey);
|
|
122
132
|
let lastError;
|
|
123
133
|
for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
|
|
124
134
|
try {
|
|
@@ -128,7 +138,7 @@ var HttpClient = class {
|
|
|
128
138
|
const response = await fetch(url, {
|
|
129
139
|
method,
|
|
130
140
|
headers: {
|
|
131
|
-
"X-Api-Key":
|
|
141
|
+
"X-Api-Key": resolvedKey,
|
|
132
142
|
"Content-Type": "application/json"
|
|
133
143
|
},
|
|
134
144
|
body: options?.body ? JSON.stringify(options.body) : void 0,
|
|
@@ -234,14 +244,14 @@ var EmailResource = class {
|
|
|
234
244
|
constructor(http) {
|
|
235
245
|
this.http = http;
|
|
236
246
|
}
|
|
237
|
-
async send(params) {
|
|
238
|
-
return this.http.post("/v1/email/send", params);
|
|
247
|
+
async send(params, overrides) {
|
|
248
|
+
return this.http.post("/v1/email/send", params, overrides?.apiKey);
|
|
239
249
|
}
|
|
240
|
-
async bulk(params) {
|
|
241
|
-
return this.http.post("/v1/email/bulk", params);
|
|
250
|
+
async bulk(params, overrides) {
|
|
251
|
+
return this.http.post("/v1/email/bulk", params, overrides?.apiKey);
|
|
242
252
|
}
|
|
243
|
-
async status(jobId) {
|
|
244
|
-
return this.http.get(`/v1/email/status/${encodeURIComponent(jobId)}
|
|
253
|
+
async status(jobId, overrides) {
|
|
254
|
+
return this.http.get(`/v1/email/status/${encodeURIComponent(jobId)}`, void 0, overrides?.apiKey);
|
|
245
255
|
}
|
|
246
256
|
};
|
|
247
257
|
|
|
@@ -250,17 +260,17 @@ var TemplatesResource = class {
|
|
|
250
260
|
constructor(http) {
|
|
251
261
|
this.http = http;
|
|
252
262
|
}
|
|
253
|
-
async create(params) {
|
|
254
|
-
return this.http.post("/v1/email-templates", params);
|
|
263
|
+
async create(params, overrides) {
|
|
264
|
+
return this.http.post("/v1/email-templates", params, overrides?.apiKey);
|
|
255
265
|
}
|
|
256
|
-
async list(params) {
|
|
257
|
-
return this.http.get("/v1/email-templates", params);
|
|
266
|
+
async list(params, overrides) {
|
|
267
|
+
return this.http.get("/v1/email-templates", params, overrides?.apiKey);
|
|
258
268
|
}
|
|
259
|
-
async *listAll(params) {
|
|
269
|
+
async *listAll(params, overrides) {
|
|
260
270
|
let page = 1;
|
|
261
271
|
const limit = params?.limit || 20;
|
|
262
272
|
while (true) {
|
|
263
|
-
const result = await this.list({ ...params, page, limit });
|
|
273
|
+
const result = await this.list({ ...params, page, limit }, overrides);
|
|
264
274
|
for (const template of result.templates) {
|
|
265
275
|
yield template;
|
|
266
276
|
}
|
|
@@ -268,29 +278,29 @@ var TemplatesResource = class {
|
|
|
268
278
|
page++;
|
|
269
279
|
}
|
|
270
280
|
}
|
|
271
|
-
async get(id) {
|
|
272
|
-
return this.http.get(`/v1/email-templates/${encodeURIComponent(id)}
|
|
281
|
+
async get(id, overrides) {
|
|
282
|
+
return this.http.get(`/v1/email-templates/${encodeURIComponent(id)}`, void 0, overrides?.apiKey);
|
|
273
283
|
}
|
|
274
|
-
async update(id, params) {
|
|
275
|
-
return this.http.patch(`/v1/email-templates/${encodeURIComponent(id)}`, params);
|
|
284
|
+
async update(id, params, overrides) {
|
|
285
|
+
return this.http.patch(`/v1/email-templates/${encodeURIComponent(id)}`, params, overrides?.apiKey);
|
|
276
286
|
}
|
|
277
|
-
async delete(id) {
|
|
278
|
-
return this.http.delete(`/v1/email-templates/${encodeURIComponent(id)}
|
|
287
|
+
async delete(id, overrides) {
|
|
288
|
+
return this.http.delete(`/v1/email-templates/${encodeURIComponent(id)}`, overrides?.apiKey);
|
|
279
289
|
}
|
|
280
|
-
async duplicate(id, params) {
|
|
281
|
-
return this.http.post(`/v1/email-templates/${encodeURIComponent(id)}/duplicate`, params);
|
|
290
|
+
async duplicate(id, params, overrides) {
|
|
291
|
+
return this.http.post(`/v1/email-templates/${encodeURIComponent(id)}/duplicate`, params, overrides?.apiKey);
|
|
282
292
|
}
|
|
283
|
-
async preview(id, params) {
|
|
284
|
-
return this.http.post(`/v1/email-templates/${encodeURIComponent(id)}/preview`, params);
|
|
293
|
+
async preview(id, params, overrides) {
|
|
294
|
+
return this.http.post(`/v1/email-templates/${encodeURIComponent(id)}/preview`, params, overrides?.apiKey);
|
|
285
295
|
}
|
|
286
|
-
async send(params) {
|
|
287
|
-
return this.http.post("/v1/email-templates/send", params);
|
|
296
|
+
async send(params, overrides) {
|
|
297
|
+
return this.http.post("/v1/email-templates/send", params, overrides?.apiKey);
|
|
288
298
|
}
|
|
289
|
-
async bulkSend(params) {
|
|
290
|
-
return this.http.post("/v1/email-templates/bulk", params);
|
|
299
|
+
async bulkSend(params, overrides) {
|
|
300
|
+
return this.http.post("/v1/email-templates/bulk", params, overrides?.apiKey);
|
|
291
301
|
}
|
|
292
|
-
async stats() {
|
|
293
|
-
return this.http.get("/v1/email-templates/stats");
|
|
302
|
+
async stats(overrides) {
|
|
303
|
+
return this.http.get("/v1/email-templates/stats", void 0, overrides?.apiKey);
|
|
294
304
|
}
|
|
295
305
|
};
|
|
296
306
|
|
|
@@ -299,14 +309,14 @@ var SuppressionsResource = class {
|
|
|
299
309
|
constructor(http) {
|
|
300
310
|
this.http = http;
|
|
301
311
|
}
|
|
302
|
-
async list(params) {
|
|
303
|
-
return this.http.get("/v1/tenants/suppressions", params);
|
|
312
|
+
async list(params, overrides) {
|
|
313
|
+
return this.http.get("/v1/tenants/suppressions", params, overrides?.apiKey);
|
|
304
314
|
}
|
|
305
|
-
async *listAll(params) {
|
|
315
|
+
async *listAll(params, overrides) {
|
|
306
316
|
let page = 1;
|
|
307
317
|
const limit = params?.limit || 50;
|
|
308
318
|
while (true) {
|
|
309
|
-
const result = await this.list({ ...params, page, limit });
|
|
319
|
+
const result = await this.list({ ...params, page, limit }, overrides);
|
|
310
320
|
for (const suppression of result.suppressions) {
|
|
311
321
|
yield suppression;
|
|
312
322
|
}
|
|
@@ -314,11 +324,11 @@ var SuppressionsResource = class {
|
|
|
314
324
|
page++;
|
|
315
325
|
}
|
|
316
326
|
}
|
|
317
|
-
async add(params) {
|
|
318
|
-
return this.http.post("/v1/tenants/suppressions", params);
|
|
327
|
+
async add(params, overrides) {
|
|
328
|
+
return this.http.post("/v1/tenants/suppressions", params, overrides?.apiKey);
|
|
319
329
|
}
|
|
320
|
-
async remove(email) {
|
|
321
|
-
return this.http.delete(`/v1/tenants/suppressions/${encodeURIComponent(email)}
|
|
330
|
+
async remove(email, overrides) {
|
|
331
|
+
return this.http.delete(`/v1/tenants/suppressions/${encodeURIComponent(email)}`, overrides?.apiKey);
|
|
322
332
|
}
|
|
323
333
|
};
|
|
324
334
|
|
|
@@ -327,17 +337,17 @@ var WebhooksResource = class {
|
|
|
327
337
|
constructor(http) {
|
|
328
338
|
this.http = http;
|
|
329
339
|
}
|
|
330
|
-
async create(params) {
|
|
331
|
-
return this.http.post("/v1/tenants/webhooks", params);
|
|
340
|
+
async create(params, overrides) {
|
|
341
|
+
return this.http.post("/v1/tenants/webhooks", params, overrides?.apiKey);
|
|
332
342
|
}
|
|
333
|
-
async list() {
|
|
334
|
-
return this.http.get("/v1/tenants/webhooks");
|
|
343
|
+
async list(overrides) {
|
|
344
|
+
return this.http.get("/v1/tenants/webhooks", void 0, overrides?.apiKey);
|
|
335
345
|
}
|
|
336
|
-
async update(id, params) {
|
|
337
|
-
return this.http.patch(`/v1/tenants/webhooks/${encodeURIComponent(id)}`, params);
|
|
346
|
+
async update(id, params, overrides) {
|
|
347
|
+
return this.http.patch(`/v1/tenants/webhooks/${encodeURIComponent(id)}`, params, overrides?.apiKey);
|
|
338
348
|
}
|
|
339
|
-
async delete(id) {
|
|
340
|
-
return this.http.delete(`/v1/tenants/webhooks/${encodeURIComponent(id)}
|
|
349
|
+
async delete(id, overrides) {
|
|
350
|
+
return this.http.delete(`/v1/tenants/webhooks/${encodeURIComponent(id)}`, overrides?.apiKey);
|
|
341
351
|
}
|
|
342
352
|
};
|
|
343
353
|
|
|
@@ -346,11 +356,11 @@ var DashboardResource = class {
|
|
|
346
356
|
constructor(http) {
|
|
347
357
|
this.http = http;
|
|
348
358
|
}
|
|
349
|
-
async get() {
|
|
350
|
-
return this.http.get("/v1/tenants/dashboard");
|
|
359
|
+
async get(overrides) {
|
|
360
|
+
return this.http.get("/v1/tenants/dashboard", void 0, overrides?.apiKey);
|
|
351
361
|
}
|
|
352
|
-
async quota() {
|
|
353
|
-
return this.http.get("/v1/tenants/quota");
|
|
362
|
+
async quota(overrides) {
|
|
363
|
+
return this.http.get("/v1/tenants/quota", void 0, overrides?.apiKey);
|
|
354
364
|
}
|
|
355
365
|
};
|
|
356
366
|
|
|
@@ -364,17 +374,12 @@ var Outbound = class {
|
|
|
364
374
|
dashboard;
|
|
365
375
|
constructor(config) {
|
|
366
376
|
const resolved = {
|
|
367
|
-
apiKey: config?.apiKey
|
|
377
|
+
apiKey: config?.apiKey,
|
|
368
378
|
baseUrl: config?.baseUrl || BASE_URL,
|
|
369
379
|
timeout: config?.timeout ?? 3e4,
|
|
370
380
|
maxRetries: config?.maxRetries ?? 3,
|
|
371
381
|
retryDelay: config?.retryDelay ?? 1e3
|
|
372
382
|
};
|
|
373
|
-
if (!resolved.apiKey) {
|
|
374
|
-
throw new AuthenticationError(
|
|
375
|
-
"API key is required. Pass it to the constructor or set the OUTBOUND_API_KEY environment variable."
|
|
376
|
-
);
|
|
377
|
-
}
|
|
378
383
|
const http = new HttpClient(resolved);
|
|
379
384
|
this.email = new EmailResource(http);
|
|
380
385
|
this.templates = new TemplatesResource(http);
|
|
@@ -395,12 +400,6 @@ var Outbound = class {
|
|
|
395
400
|
return false;
|
|
396
401
|
}
|
|
397
402
|
}
|
|
398
|
-
getEnv(key) {
|
|
399
|
-
if (typeof process !== "undefined" && process.env) {
|
|
400
|
-
return process.env[key];
|
|
401
|
-
}
|
|
402
|
-
return void 0;
|
|
403
|
-
}
|
|
404
403
|
};
|
|
405
404
|
// Annotate the CommonJS export names for ESM import in node:
|
|
406
405
|
0 && (module.exports = {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/http.ts","../src/resources/email.ts","../src/resources/templates.ts","../src/resources/suppressions.ts","../src/resources/webhooks.ts","../src/resources/dashboard.ts","../src/client.ts"],"sourcesContent":["export { Outbound } from './client';\n\n// Error classes\nexport {\n OutboundError,\n BadRequestError,\n AuthenticationError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n RateLimitError,\n ServerError,\n TimeoutError,\n NetworkError,\n} from './errors';\n\n// All types\nexport type {\n OutboundConfig,\n ResolvedConfig,\n SendEmailParams,\n Attachment,\n SendEmailResponse,\n BulkEmailParams,\n BulkEmailRecipient,\n BulkEmailResponse,\n JobStatusResponse,\n EmailRecipientStatus,\n EmailStatus,\n CreateTemplateParams,\n UpdateTemplateParams,\n ListTemplatesParams,\n ListTemplatesResponse,\n Template,\n TemplateResponse,\n TemplateSendParams,\n TemplateBulkSendParams,\n TemplateBulkRecipient,\n TemplateBulkSendResponse,\n TemplatePreviewParams,\n TemplatePreviewResponse,\n TemplateStatsResponse,\n ListSuppressionsParams,\n ListSuppressionsResponse,\n Suppression,\n AddSuppressionParams,\n SuppressionResponse,\n WebhookEvent,\n CreateWebhookParams,\n UpdateWebhookParams,\n Webhook,\n CreateWebhookResponse,\n UpdateWebhookResponse,\n ListWebhooksResponse,\n DashboardResponse,\n QuotaResponse,\n} from './types';\n","export class OutboundError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly details?: unknown,\n public readonly requestId?: string,\n ) {\n super(message);\n this.name = 'OutboundError';\n }\n}\n\nexport class BadRequestError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 400, details, requestId);\n this.name = 'BadRequestError';\n }\n}\n\nexport class AuthenticationError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 401, details, requestId);\n this.name = 'AuthenticationError';\n }\n}\n\nexport class ForbiddenError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 403, details, requestId);\n this.name = 'ForbiddenError';\n }\n}\n\nexport class NotFoundError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 404, details, requestId);\n this.name = 'NotFoundError';\n }\n}\n\nexport class ConflictError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 409, details, requestId);\n this.name = 'ConflictError';\n }\n}\n\nexport class RateLimitError extends OutboundError {\n public readonly retryAfter?: number;\n\n constructor(message: string, retryAfter?: number, details?: unknown, requestId?: string) {\n super(message, 429, details, requestId);\n this.name = 'RateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\nexport class ServerError extends OutboundError {\n constructor(message: string, statusCode: number = 500, details?: unknown, requestId?: string) {\n super(message, statusCode, details, requestId);\n this.name = 'ServerError';\n }\n}\n\nexport class TimeoutError extends OutboundError {\n constructor(message: string = 'Request timed out') {\n super(message, 0);\n this.name = 'TimeoutError';\n }\n}\n\nexport class NetworkError extends OutboundError {\n constructor(message: string = 'Network request failed') {\n super(message, 0);\n this.name = 'NetworkError';\n }\n}\n","import type { ResolvedConfig } from './types';\nimport {\n OutboundError,\n BadRequestError,\n AuthenticationError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n RateLimitError,\n ServerError,\n TimeoutError,\n NetworkError,\n} from './errors';\n\nexport interface RequestOptions {\n body?: unknown;\n params?: Record<string, unknown>;\n}\n\nexport class HttpClient {\n constructor(private config: ResolvedConfig) {}\n\n async get<T>(path: string, params?: Record<string, unknown>): Promise<T> {\n return this.request<T>('GET', path, { params });\n }\n\n async post<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('POST', path, { body });\n }\n\n async patch<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('PATCH', path, { body });\n }\n\n async delete<T>(path: string): Promise<T> {\n return this.request<T>('DELETE', path);\n }\n\n private async request<T>(method: string, path: string, options?: RequestOptions): Promise<T> {\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const url = this.buildUrl(path, options?.params);\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n const response = await fetch(url, {\n method,\n headers: {\n 'X-Api-Key': this.config.apiKey,\n 'Content-Type': 'application/json',\n },\n body: options?.body ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n const error = await this.parseError(response);\n\n // Only retry on 429 and 5xx\n if (response.status === 429 || response.status >= 500) {\n lastError = error;\n\n if (attempt < this.config.maxRetries) {\n const retryAfter = error instanceof RateLimitError && error.retryAfter\n ? error.retryAfter * 1000\n : this.config.retryDelay * Math.pow(2, attempt);\n\n await this.sleep(retryAfter);\n continue;\n }\n }\n\n throw error;\n } catch (err) {\n if (err instanceof OutboundError) {\n // Already a typed error from parseError — check if retryable\n if ((err.statusCode === 429 || err.statusCode >= 500) && attempt < this.config.maxRetries) {\n lastError = err;\n const retryAfter = err instanceof RateLimitError && err.retryAfter\n ? err.retryAfter * 1000\n : this.config.retryDelay * Math.pow(2, attempt);\n await this.sleep(retryAfter);\n continue;\n }\n throw err;\n }\n\n if (err instanceof DOMException && err.name === 'AbortError') {\n lastError = new TimeoutError(`Request timed out after ${this.config.timeout}ms`);\n if (attempt < this.config.maxRetries) {\n await this.sleep(this.config.retryDelay * Math.pow(2, attempt));\n continue;\n }\n throw lastError;\n }\n\n lastError = new NetworkError((err as Error).message);\n if (attempt < this.config.maxRetries) {\n await this.sleep(this.config.retryDelay * Math.pow(2, attempt));\n continue;\n }\n throw lastError;\n }\n }\n\n throw lastError || new NetworkError('Request failed after retries');\n }\n\n private buildUrl(path: string, params?: Record<string, unknown>): string {\n const base = this.config.baseUrl.replace(/\\/+$/, '');\n const url = new URL(`${base}${path}`);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n\n return url.toString();\n }\n\n private async parseError(response: Response): Promise<OutboundError> {\n let body: { error?: string; message?: string; details?: unknown } = {};\n const requestId = response.headers.get('x-request-id') || undefined;\n\n try {\n body = (await response.json()) as typeof body;\n } catch {\n // Response may not be JSON\n }\n\n const message = body.error || body.message || `HTTP ${response.status}`;\n const details = body.details;\n\n switch (response.status) {\n case 400:\n return new BadRequestError(message, details, requestId);\n case 401:\n return new AuthenticationError(message, details, requestId);\n case 403:\n return new ForbiddenError(message, details, requestId);\n case 404:\n return new NotFoundError(message, details, requestId);\n case 409:\n return new ConflictError(message, details, requestId);\n case 429: {\n const retryAfter = response.headers.get('retry-after');\n return new RateLimitError(\n message,\n retryAfter ? parseInt(retryAfter, 10) : undefined,\n details,\n requestId,\n );\n }\n default:\n if (response.status >= 500) {\n return new ServerError(message, response.status, details, requestId);\n }\n return new OutboundError(message, response.status, details, requestId);\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n SendEmailParams,\n SendEmailResponse,\n BulkEmailParams,\n BulkEmailResponse,\n JobStatusResponse,\n} from '../types';\n\nexport class EmailResource {\n constructor(private http: HttpClient) {}\n\n async send(params: SendEmailParams): Promise<SendEmailResponse> {\n return this.http.post<SendEmailResponse>('/v1/email/send', params);\n }\n\n async bulk(params: BulkEmailParams): Promise<BulkEmailResponse> {\n return this.http.post<BulkEmailResponse>('/v1/email/bulk', params);\n }\n\n async status(jobId: string): Promise<JobStatusResponse> {\n return this.http.get<JobStatusResponse>(`/v1/email/status/${encodeURIComponent(jobId)}`);\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n CreateTemplateParams,\n UpdateTemplateParams,\n ListTemplatesParams,\n ListTemplatesResponse,\n Template,\n TemplateResponse,\n TemplateSendParams,\n SendEmailResponse,\n TemplateBulkSendParams,\n TemplateBulkSendResponse,\n TemplatePreviewParams,\n TemplatePreviewResponse,\n TemplateStatsResponse,\n} from '../types';\n\nexport class TemplatesResource {\n constructor(private http: HttpClient) {}\n\n async create(params: CreateTemplateParams): Promise<TemplateResponse> {\n return this.http.post<TemplateResponse>('/v1/email-templates', params);\n }\n\n async list(params?: ListTemplatesParams): Promise<ListTemplatesResponse> {\n return this.http.get<ListTemplatesResponse>('/v1/email-templates', params as Record<string, unknown>);\n }\n\n async *listAll(params?: Omit<ListTemplatesParams, 'page'>): AsyncGenerator<Template> {\n let page = 1;\n const limit = params?.limit || 20;\n\n while (true) {\n const result = await this.list({ ...params, page, limit });\n for (const template of result.templates) {\n yield template;\n }\n if (result.templates.length < limit) break;\n page++;\n }\n }\n\n async get(id: string): Promise<TemplateResponse> {\n return this.http.get<TemplateResponse>(`/v1/email-templates/${encodeURIComponent(id)}`);\n }\n\n async update(id: string, params: UpdateTemplateParams): Promise<TemplateResponse> {\n return this.http.patch<TemplateResponse>(`/v1/email-templates/${encodeURIComponent(id)}`, params);\n }\n\n async delete(id: string): Promise<{ message: string; id: string }> {\n return this.http.delete<{ message: string; id: string }>(`/v1/email-templates/${encodeURIComponent(id)}`);\n }\n\n async duplicate(id: string, params?: { name?: string }): Promise<TemplateResponse> {\n return this.http.post<TemplateResponse>(`/v1/email-templates/${encodeURIComponent(id)}/duplicate`, params);\n }\n\n async preview(id: string, params?: TemplatePreviewParams): Promise<TemplatePreviewResponse> {\n return this.http.post<TemplatePreviewResponse>(`/v1/email-templates/${encodeURIComponent(id)}/preview`, params);\n }\n\n async send(params: TemplateSendParams): Promise<SendEmailResponse> {\n return this.http.post<SendEmailResponse>('/v1/email-templates/send', params);\n }\n\n async bulkSend(params: TemplateBulkSendParams): Promise<TemplateBulkSendResponse> {\n return this.http.post<TemplateBulkSendResponse>('/v1/email-templates/bulk', params);\n }\n\n async stats(): Promise<TemplateStatsResponse> {\n return this.http.get<TemplateStatsResponse>('/v1/email-templates/stats');\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n ListSuppressionsParams,\n ListSuppressionsResponse,\n AddSuppressionParams,\n SuppressionResponse,\n Suppression,\n} from '../types';\n\nexport class SuppressionsResource {\n constructor(private http: HttpClient) {}\n\n async list(params?: ListSuppressionsParams): Promise<ListSuppressionsResponse> {\n return this.http.get<ListSuppressionsResponse>('/v1/tenants/suppressions', params as Record<string, unknown>);\n }\n\n async *listAll(params?: Omit<ListSuppressionsParams, 'page'>): AsyncGenerator<Suppression> {\n let page = 1;\n const limit = params?.limit || 50;\n\n while (true) {\n const result = await this.list({ ...params, page, limit });\n for (const suppression of result.suppressions) {\n yield suppression;\n }\n if (result.suppressions.length < limit) break;\n page++;\n }\n }\n\n async add(params: AddSuppressionParams): Promise<SuppressionResponse> {\n return this.http.post<SuppressionResponse>('/v1/tenants/suppressions', params);\n }\n\n async remove(email: string): Promise<{ message: string }> {\n return this.http.delete<{ message: string }>(`/v1/tenants/suppressions/${encodeURIComponent(email)}`);\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n CreateWebhookParams,\n CreateWebhookResponse,\n UpdateWebhookParams,\n UpdateWebhookResponse,\n ListWebhooksResponse,\n} from '../types';\n\nexport class WebhooksResource {\n constructor(private http: HttpClient) {}\n\n async create(params: CreateWebhookParams): Promise<CreateWebhookResponse> {\n return this.http.post<CreateWebhookResponse>('/v1/tenants/webhooks', params);\n }\n\n async list(): Promise<ListWebhooksResponse> {\n return this.http.get<ListWebhooksResponse>('/v1/tenants/webhooks');\n }\n\n async update(id: string, params: UpdateWebhookParams): Promise<UpdateWebhookResponse> {\n return this.http.patch<UpdateWebhookResponse>(`/v1/tenants/webhooks/${encodeURIComponent(id)}`, params);\n }\n\n async delete(id: string): Promise<{ message: string; id: string }> {\n return this.http.delete<{ message: string; id: string }>(`/v1/tenants/webhooks/${encodeURIComponent(id)}`);\n }\n}\n","import type { HttpClient } from '../http';\nimport type { DashboardResponse, QuotaResponse } from '../types';\n\nexport class DashboardResource {\n constructor(private http: HttpClient) {}\n\n async get(): Promise<DashboardResponse> {\n return this.http.get<DashboardResponse>('/v1/tenants/dashboard');\n }\n\n async quota(): Promise<QuotaResponse> {\n return this.http.get<QuotaResponse>('/v1/tenants/quota');\n }\n}\n","import { HttpClient } from './http';\nimport { AuthenticationError } from './errors';\nimport { EmailResource } from './resources/email';\nimport { TemplatesResource } from './resources/templates';\nimport { SuppressionsResource } from './resources/suppressions';\nimport { WebhooksResource } from './resources/webhooks';\nimport { DashboardResource } from './resources/dashboard';\nimport type { OutboundConfig, ResolvedConfig } from './types';\n\nconst BASE_URL = 'https://outbound-api.mastersunion.org';\n\nexport class Outbound {\n readonly email: EmailResource;\n readonly templates: TemplatesResource;\n readonly suppressions: SuppressionsResource;\n readonly webhooks: WebhooksResource;\n readonly dashboard: DashboardResource;\n\n constructor(config?: OutboundConfig) {\n const resolved: ResolvedConfig = {\n apiKey: config?.apiKey || this.getEnv('OUTBOUND_API_KEY') || '',\n baseUrl: config?.baseUrl || BASE_URL,\n timeout: config?.timeout ?? 30_000,\n maxRetries: config?.maxRetries ?? 3,\n retryDelay: config?.retryDelay ?? 1000,\n };\n\n if (!resolved.apiKey) {\n throw new AuthenticationError(\n 'API key is required. Pass it to the constructor or set the OUTBOUND_API_KEY environment variable.',\n );\n }\n\n const http = new HttpClient(resolved);\n\n this.email = new EmailResource(http);\n this.templates = new TemplatesResource(http);\n this.suppressions = new SuppressionsResource(http);\n this.webhooks = new WebhooksResource(http);\n this.dashboard = new DashboardResource(http);\n }\n\n /**\n * Verify a webhook signature using HMAC-SHA256.\n * Use this in your webhook handler to validate incoming requests.\n */\n static verifyWebhookSignature(\n payload: string | Buffer,\n signature: string,\n secret: string,\n ): boolean {\n // Dynamic import to keep browser-compatible at the type level\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const crypto = require('crypto') as typeof import('crypto');\n const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex');\n try {\n return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));\n } catch {\n return false;\n }\n }\n\n private getEnv(key: string): string | undefined {\n if (typeof process !== 'undefined' && process.env) {\n return process.env[key];\n }\n return undefined;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,gBAAN,cAA4B,MAAM;AAAA,EACvC,YACE,SACgB,YACA,SACA,WAChB;AACA,UAAM,OAAO;AAJG;AACA;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,kBAAN,cAA8B,cAAc;AAAA,EACjD,YAAY,SAAiB,SAAmB,WAAoB;AAClE,UAAM,SAAS,KAAK,SAAS,SAAS;AACtC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,sBAAN,cAAkC,cAAc;AAAA,EACrD,YAAY,SAAiB,SAAmB,WAAoB;AAClE,UAAM,SAAS,KAAK,SAAS,SAAS;AACtC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,iBAAN,cAA6B,cAAc;AAAA,EAChD,YAAY,SAAiB,SAAmB,WAAoB;AAClE,UAAM,SAAS,KAAK,SAAS,SAAS;AACtC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,gBAAN,cAA4B,cAAc;AAAA,EAC/C,YAAY,SAAiB,SAAmB,WAAoB;AAClE,UAAM,SAAS,KAAK,SAAS,SAAS;AACtC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,gBAAN,cAA4B,cAAc;AAAA,EAC/C,YAAY,SAAiB,SAAmB,WAAoB;AAClE,UAAM,SAAS,KAAK,SAAS,SAAS;AACtC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,iBAAN,cAA6B,cAAc;AAAA,EAChC;AAAA,EAEhB,YAAY,SAAiB,YAAqB,SAAmB,WAAoB;AACvF,UAAM,SAAS,KAAK,SAAS,SAAS;AACtC,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,cAAN,cAA0B,cAAc;AAAA,EAC7C,YAAY,SAAiB,aAAqB,KAAK,SAAmB,WAAoB;AAC5F,UAAM,SAAS,YAAY,SAAS,SAAS;AAC7C,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,eAAN,cAA2B,cAAc;AAAA,EAC9C,YAAY,UAAkB,qBAAqB;AACjD,UAAM,SAAS,CAAC;AAChB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,eAAN,cAA2B,cAAc;AAAA,EAC9C,YAAY,UAAkB,0BAA0B;AACtD,UAAM,SAAS,CAAC;AAChB,SAAK,OAAO;AAAA,EACd;AACF;;;ACzDO,IAAM,aAAN,MAAiB;AAAA,EACtB,YAAoB,QAAwB;AAAxB;AAAA,EAAyB;AAAA,EAE7C,MAAM,IAAO,MAAc,QAA8C;AACvE,WAAO,KAAK,QAAW,OAAO,MAAM,EAAE,OAAO,CAAC;AAAA,EAChD;AAAA,EAEA,MAAM,KAAQ,MAAc,MAA4B;AACtD,WAAO,KAAK,QAAW,QAAQ,MAAM,EAAE,KAAK,CAAC;AAAA,EAC/C;AAAA,EAEA,MAAM,MAAS,MAAc,MAA4B;AACvD,WAAO,KAAK,QAAW,SAAS,MAAM,EAAE,KAAK,CAAC;AAAA,EAChD;AAAA,EAEA,MAAM,OAAU,MAA0B;AACxC,WAAO,KAAK,QAAW,UAAU,IAAI;AAAA,EACvC;AAAA,EAEA,MAAc,QAAW,QAAgB,MAAc,SAAsC;AAC3F,QAAI;AAEJ,aAAS,UAAU,GAAG,WAAW,KAAK,OAAO,YAAY,WAAW;AAClE,UAAI;AACF,cAAM,MAAM,KAAK,SAAS,MAAM,SAAS,MAAM;AAC/C,cAAM,aAAa,IAAI,gBAAgB;AACvC,cAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO,OAAO;AAE1E,cAAM,WAAW,MAAM,MAAM,KAAK;AAAA,UAChC;AAAA,UACA,SAAS;AAAA,YACP,aAAa,KAAK,OAAO;AAAA,YACzB,gBAAgB;AAAA,UAClB;AAAA,UACA,MAAM,SAAS,OAAO,KAAK,UAAU,QAAQ,IAAI,IAAI;AAAA,UACrD,QAAQ,WAAW;AAAA,QACrB,CAAC;AAED,qBAAa,SAAS;AAEtB,YAAI,SAAS,IAAI;AACf,iBAAQ,MAAM,SAAS,KAAK;AAAA,QAC9B;AAEA,cAAM,QAAQ,MAAM,KAAK,WAAW,QAAQ;AAG5C,YAAI,SAAS,WAAW,OAAO,SAAS,UAAU,KAAK;AACrD,sBAAY;AAEZ,cAAI,UAAU,KAAK,OAAO,YAAY;AACpC,kBAAM,aAAa,iBAAiB,kBAAkB,MAAM,aACxD,MAAM,aAAa,MACnB,KAAK,OAAO,aAAa,KAAK,IAAI,GAAG,OAAO;AAEhD,kBAAM,KAAK,MAAM,UAAU;AAC3B;AAAA,UACF;AAAA,QACF;AAEA,cAAM;AAAA,MACR,SAAS,KAAK;AACZ,YAAI,eAAe,eAAe;AAEhC,eAAK,IAAI,eAAe,OAAO,IAAI,cAAc,QAAQ,UAAU,KAAK,OAAO,YAAY;AACzF,wBAAY;AACZ,kBAAM,aAAa,eAAe,kBAAkB,IAAI,aACpD,IAAI,aAAa,MACjB,KAAK,OAAO,aAAa,KAAK,IAAI,GAAG,OAAO;AAChD,kBAAM,KAAK,MAAM,UAAU;AAC3B;AAAA,UACF;AACA,gBAAM;AAAA,QACR;AAEA,YAAI,eAAe,gBAAgB,IAAI,SAAS,cAAc;AAC5D,sBAAY,IAAI,aAAa,2BAA2B,KAAK,OAAO,OAAO,IAAI;AAC/E,cAAI,UAAU,KAAK,OAAO,YAAY;AACpC,kBAAM,KAAK,MAAM,KAAK,OAAO,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC;AAC9D;AAAA,UACF;AACA,gBAAM;AAAA,QACR;AAEA,oBAAY,IAAI,aAAc,IAAc,OAAO;AACnD,YAAI,UAAU,KAAK,OAAO,YAAY;AACpC,gBAAM,KAAK,MAAM,KAAK,OAAO,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC;AAC9D;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,aAAa,IAAI,aAAa,8BAA8B;AAAA,EACpE;AAAA,EAEQ,SAAS,MAAc,QAA0C;AACvE,UAAM,OAAO,KAAK,OAAO,QAAQ,QAAQ,QAAQ,EAAE;AACnD,UAAM,MAAM,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE;AAEpC,QAAI,QAAQ;AACV,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,YAAI,UAAU,UAAa,UAAU,MAAM;AACzC,cAAI,aAAa,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAEA,WAAO,IAAI,SAAS;AAAA,EACtB;AAAA,EAEA,MAAc,WAAW,UAA4C;AACnE,QAAI,OAAgE,CAAC;AACrE,UAAM,YAAY,SAAS,QAAQ,IAAI,cAAc,KAAK;AAE1D,QAAI;AACF,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B,QAAQ;AAAA,IAER;AAEA,UAAM,UAAU,KAAK,SAAS,KAAK,WAAW,QAAQ,SAAS,MAAM;AACrE,UAAM,UAAU,KAAK;AAErB,YAAQ,SAAS,QAAQ;AAAA,MACvB,KAAK;AACH,eAAO,IAAI,gBAAgB,SAAS,SAAS,SAAS;AAAA,MACxD,KAAK;AACH,eAAO,IAAI,oBAAoB,SAAS,SAAS,SAAS;AAAA,MAC5D,KAAK;AACH,eAAO,IAAI,eAAe,SAAS,SAAS,SAAS;AAAA,MACvD,KAAK;AACH,eAAO,IAAI,cAAc,SAAS,SAAS,SAAS;AAAA,MACtD,KAAK;AACH,eAAO,IAAI,cAAc,SAAS,SAAS,SAAS;AAAA,MACtD,KAAK,KAAK;AACR,cAAM,aAAa,SAAS,QAAQ,IAAI,aAAa;AACrD,eAAO,IAAI;AAAA,UACT;AAAA,UACA,aAAa,SAAS,YAAY,EAAE,IAAI;AAAA,UACxC;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA;AACE,YAAI,SAAS,UAAU,KAAK;AAC1B,iBAAO,IAAI,YAAY,SAAS,SAAS,QAAQ,SAAS,SAAS;AAAA,QACrE;AACA,eAAO,IAAI,cAAc,SAAS,SAAS,QAAQ,SAAS,SAAS;AAAA,IACzE;AAAA,EACF;AAAA,EAEQ,MAAM,IAA2B;AACvC,WAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAAA,EACzD;AACF;;;ACrKO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAAoB,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAEvC,MAAM,KAAK,QAAqD;AAC9D,WAAO,KAAK,KAAK,KAAwB,kBAAkB,MAAM;AAAA,EACnE;AAAA,EAEA,MAAM,KAAK,QAAqD;AAC9D,WAAO,KAAK,KAAK,KAAwB,kBAAkB,MAAM;AAAA,EACnE;AAAA,EAEA,MAAM,OAAO,OAA2C;AACtD,WAAO,KAAK,KAAK,IAAuB,oBAAoB,mBAAmB,KAAK,CAAC,EAAE;AAAA,EACzF;AACF;;;ACNO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAAoB,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAEvC,MAAM,OAAO,QAAyD;AACpE,WAAO,KAAK,KAAK,KAAuB,uBAAuB,MAAM;AAAA,EACvE;AAAA,EAEA,MAAM,KAAK,QAA8D;AACvE,WAAO,KAAK,KAAK,IAA2B,uBAAuB,MAAiC;AAAA,EACtG;AAAA,EAEA,OAAO,QAAQ,QAAsE;AACnF,QAAI,OAAO;AACX,UAAM,QAAQ,QAAQ,SAAS;AAE/B,WAAO,MAAM;AACX,YAAM,SAAS,MAAM,KAAK,KAAK,EAAE,GAAG,QAAQ,MAAM,MAAM,CAAC;AACzD,iBAAW,YAAY,OAAO,WAAW;AACvC,cAAM;AAAA,MACR;AACA,UAAI,OAAO,UAAU,SAAS,MAAO;AACrC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,IAAuC;AAC/C,WAAO,KAAK,KAAK,IAAsB,uBAAuB,mBAAmB,EAAE,CAAC,EAAE;AAAA,EACxF;AAAA,EAEA,MAAM,OAAO,IAAY,QAAyD;AAChF,WAAO,KAAK,KAAK,MAAwB,uBAAuB,mBAAmB,EAAE,CAAC,IAAI,MAAM;AAAA,EAClG;AAAA,EAEA,MAAM,OAAO,IAAsD;AACjE,WAAO,KAAK,KAAK,OAAwC,uBAAuB,mBAAmB,EAAE,CAAC,EAAE;AAAA,EAC1G;AAAA,EAEA,MAAM,UAAU,IAAY,QAAuD;AACjF,WAAO,KAAK,KAAK,KAAuB,uBAAuB,mBAAmB,EAAE,CAAC,cAAc,MAAM;AAAA,EAC3G;AAAA,EAEA,MAAM,QAAQ,IAAY,QAAkE;AAC1F,WAAO,KAAK,KAAK,KAA8B,uBAAuB,mBAAmB,EAAE,CAAC,YAAY,MAAM;AAAA,EAChH;AAAA,EAEA,MAAM,KAAK,QAAwD;AACjE,WAAO,KAAK,KAAK,KAAwB,4BAA4B,MAAM;AAAA,EAC7E;AAAA,EAEA,MAAM,SAAS,QAAmE;AAChF,WAAO,KAAK,KAAK,KAA+B,4BAA4B,MAAM;AAAA,EACpF;AAAA,EAEA,MAAM,QAAwC;AAC5C,WAAO,KAAK,KAAK,IAA2B,2BAA2B;AAAA,EACzE;AACF;;;AChEO,IAAM,uBAAN,MAA2B;AAAA,EAChC,YAAoB,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAEvC,MAAM,KAAK,QAAoE;AAC7E,WAAO,KAAK,KAAK,IAA8B,4BAA4B,MAAiC;AAAA,EAC9G;AAAA,EAEA,OAAO,QAAQ,QAA4E;AACzF,QAAI,OAAO;AACX,UAAM,QAAQ,QAAQ,SAAS;AAE/B,WAAO,MAAM;AACX,YAAM,SAAS,MAAM,KAAK,KAAK,EAAE,GAAG,QAAQ,MAAM,MAAM,CAAC;AACzD,iBAAW,eAAe,OAAO,cAAc;AAC7C,cAAM;AAAA,MACR;AACA,UAAI,OAAO,aAAa,SAAS,MAAO;AACxC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,QAA4D;AACpE,WAAO,KAAK,KAAK,KAA0B,4BAA4B,MAAM;AAAA,EAC/E;AAAA,EAEA,MAAM,OAAO,OAA6C;AACxD,WAAO,KAAK,KAAK,OAA4B,4BAA4B,mBAAmB,KAAK,CAAC,EAAE;AAAA,EACtG;AACF;;;AC5BO,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAAoB,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAEvC,MAAM,OAAO,QAA6D;AACxE,WAAO,KAAK,KAAK,KAA4B,wBAAwB,MAAM;AAAA,EAC7E;AAAA,EAEA,MAAM,OAAsC;AAC1C,WAAO,KAAK,KAAK,IAA0B,sBAAsB;AAAA,EACnE;AAAA,EAEA,MAAM,OAAO,IAAY,QAA6D;AACpF,WAAO,KAAK,KAAK,MAA6B,wBAAwB,mBAAmB,EAAE,CAAC,IAAI,MAAM;AAAA,EACxG;AAAA,EAEA,MAAM,OAAO,IAAsD;AACjE,WAAO,KAAK,KAAK,OAAwC,wBAAwB,mBAAmB,EAAE,CAAC,EAAE;AAAA,EAC3G;AACF;;;ACxBO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAAoB,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAEvC,MAAM,MAAkC;AACtC,WAAO,KAAK,KAAK,IAAuB,uBAAuB;AAAA,EACjE;AAAA,EAEA,MAAM,QAAgC;AACpC,WAAO,KAAK,KAAK,IAAmB,mBAAmB;AAAA,EACzD;AACF;;;ACJA,IAAM,WAAW;AAEV,IAAM,WAAN,MAAe;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAAyB;AACnC,UAAM,WAA2B;AAAA,MAC/B,QAAQ,QAAQ,UAAU,KAAK,OAAO,kBAAkB,KAAK;AAAA,MAC7D,SAAS,QAAQ,WAAW;AAAA,MAC5B,SAAS,QAAQ,WAAW;AAAA,MAC5B,YAAY,QAAQ,cAAc;AAAA,MAClC,YAAY,QAAQ,cAAc;AAAA,IACpC;AAEA,QAAI,CAAC,SAAS,QAAQ;AACpB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,IAAI,WAAW,QAAQ;AAEpC,SAAK,QAAQ,IAAI,cAAc,IAAI;AACnC,SAAK,YAAY,IAAI,kBAAkB,IAAI;AAC3C,SAAK,eAAe,IAAI,qBAAqB,IAAI;AACjD,SAAK,WAAW,IAAI,iBAAiB,IAAI;AACzC,SAAK,YAAY,IAAI,kBAAkB,IAAI;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,uBACL,SACA,WACA,QACS;AAGT,UAAM,SAAS,QAAQ,QAAQ;AAC/B,UAAM,WAAW,OAAO,WAAW,UAAU,MAAM,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;AACjF,QAAI;AACF,aAAO,OAAO,gBAAgB,OAAO,KAAK,SAAS,GAAG,OAAO,KAAK,QAAQ,CAAC;AAAA,IAC7E,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,OAAO,KAAiC;AAC9C,QAAI,OAAO,YAAY,eAAe,QAAQ,KAAK;AACjD,aAAO,QAAQ,IAAI,GAAG;AAAA,IACxB;AACA,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/http.ts","../src/resources/email.ts","../src/resources/templates.ts","../src/resources/suppressions.ts","../src/resources/webhooks.ts","../src/resources/dashboard.ts","../src/client.ts"],"sourcesContent":["export { Outbound } from './client';\n\n// Error classes\nexport {\n OutboundError,\n BadRequestError,\n AuthenticationError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n RateLimitError,\n ServerError,\n TimeoutError,\n NetworkError,\n} from './errors';\n\n// All types\nexport type {\n OutboundConfig,\n ResolvedConfig,\n RequestOverrides,\n SendEmailParams,\n Attachment,\n SendEmailResponse,\n BulkEmailParams,\n BulkEmailRecipient,\n BulkEmailResponse,\n JobStatusResponse,\n EmailRecipientStatus,\n EmailStatus,\n CreateTemplateParams,\n UpdateTemplateParams,\n ListTemplatesParams,\n ListTemplatesResponse,\n Template,\n TemplateResponse,\n TemplateSendParams,\n TemplateBulkSendParams,\n TemplateBulkRecipient,\n TemplateBulkSendResponse,\n TemplatePreviewParams,\n TemplatePreviewResponse,\n TemplateStatsResponse,\n ListSuppressionsParams,\n ListSuppressionsResponse,\n Suppression,\n AddSuppressionParams,\n SuppressionResponse,\n WebhookEvent,\n CreateWebhookParams,\n UpdateWebhookParams,\n Webhook,\n CreateWebhookResponse,\n UpdateWebhookResponse,\n ListWebhooksResponse,\n DashboardResponse,\n QuotaResponse,\n} from './types';\n","export class OutboundError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly details?: unknown,\n public readonly requestId?: string,\n ) {\n super(message);\n this.name = 'OutboundError';\n }\n}\n\nexport class BadRequestError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 400, details, requestId);\n this.name = 'BadRequestError';\n }\n}\n\nexport class AuthenticationError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 401, details, requestId);\n this.name = 'AuthenticationError';\n }\n}\n\nexport class ForbiddenError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 403, details, requestId);\n this.name = 'ForbiddenError';\n }\n}\n\nexport class NotFoundError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 404, details, requestId);\n this.name = 'NotFoundError';\n }\n}\n\nexport class ConflictError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 409, details, requestId);\n this.name = 'ConflictError';\n }\n}\n\nexport class RateLimitError extends OutboundError {\n public readonly retryAfter?: number;\n\n constructor(message: string, retryAfter?: number, details?: unknown, requestId?: string) {\n super(message, 429, details, requestId);\n this.name = 'RateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\nexport class ServerError extends OutboundError {\n constructor(message: string, statusCode: number = 500, details?: unknown, requestId?: string) {\n super(message, statusCode, details, requestId);\n this.name = 'ServerError';\n }\n}\n\nexport class TimeoutError extends OutboundError {\n constructor(message: string = 'Request timed out') {\n super(message, 0);\n this.name = 'TimeoutError';\n }\n}\n\nexport class NetworkError extends OutboundError {\n constructor(message: string = 'Network request failed') {\n super(message, 0);\n this.name = 'NetworkError';\n }\n}\n","import type { ResolvedConfig } from './types';\nimport {\n OutboundError,\n BadRequestError,\n AuthenticationError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n RateLimitError,\n ServerError,\n TimeoutError,\n NetworkError,\n} from './errors';\n\nexport interface RequestOptions {\n body?: unknown;\n params?: Record<string, unknown>;\n}\n\nexport class HttpClient {\n constructor(private config: ResolvedConfig) {}\n\n async get<T>(path: string, params?: Record<string, unknown>, apiKey?: string): Promise<T> {\n return this.request<T>('GET', path, { params }, apiKey);\n }\n\n async post<T>(path: string, body?: unknown, apiKey?: string): Promise<T> {\n return this.request<T>('POST', path, { body }, apiKey);\n }\n\n async patch<T>(path: string, body?: unknown, apiKey?: string): Promise<T> {\n return this.request<T>('PATCH', path, { body }, apiKey);\n }\n\n async delete<T>(path: string, apiKey?: string): Promise<T> {\n return this.request<T>('DELETE', path, undefined, apiKey);\n }\n\n private resolveApiKey(apiKey?: string): string {\n const key = apiKey || this.config.apiKey;\n if (!key) {\n throw new AuthenticationError(\n 'API key is required. Pass it to the constructor or provide it per method call.',\n );\n }\n return key;\n }\n\n private async request<T>(method: string, path: string, options?: RequestOptions, apiKey?: string): Promise<T> {\n const resolvedKey = this.resolveApiKey(apiKey);\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const url = this.buildUrl(path, options?.params);\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n const response = await fetch(url, {\n method,\n headers: {\n 'X-Api-Key': resolvedKey,\n 'Content-Type': 'application/json',\n },\n body: options?.body ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n const error = await this.parseError(response);\n\n // Only retry on 429 and 5xx\n if (response.status === 429 || response.status >= 500) {\n lastError = error;\n\n if (attempt < this.config.maxRetries) {\n const retryAfter = error instanceof RateLimitError && error.retryAfter\n ? error.retryAfter * 1000\n : this.config.retryDelay * Math.pow(2, attempt);\n\n await this.sleep(retryAfter);\n continue;\n }\n }\n\n throw error;\n } catch (err) {\n if (err instanceof OutboundError) {\n // Already a typed error from parseError — check if retryable\n if ((err.statusCode === 429 || err.statusCode >= 500) && attempt < this.config.maxRetries) {\n lastError = err;\n const retryAfter = err instanceof RateLimitError && err.retryAfter\n ? err.retryAfter * 1000\n : this.config.retryDelay * Math.pow(2, attempt);\n await this.sleep(retryAfter);\n continue;\n }\n throw err;\n }\n\n if (err instanceof DOMException && err.name === 'AbortError') {\n lastError = new TimeoutError(`Request timed out after ${this.config.timeout}ms`);\n if (attempt < this.config.maxRetries) {\n await this.sleep(this.config.retryDelay * Math.pow(2, attempt));\n continue;\n }\n throw lastError;\n }\n\n lastError = new NetworkError((err as Error).message);\n if (attempt < this.config.maxRetries) {\n await this.sleep(this.config.retryDelay * Math.pow(2, attempt));\n continue;\n }\n throw lastError;\n }\n }\n\n throw lastError || new NetworkError('Request failed after retries');\n }\n\n private buildUrl(path: string, params?: Record<string, unknown>): string {\n const base = this.config.baseUrl.replace(/\\/+$/, '');\n const url = new URL(`${base}${path}`);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n\n return url.toString();\n }\n\n private async parseError(response: Response): Promise<OutboundError> {\n let body: { error?: string; message?: string; details?: unknown } = {};\n const requestId = response.headers.get('x-request-id') || undefined;\n\n try {\n body = (await response.json()) as typeof body;\n } catch {\n // Response may not be JSON\n }\n\n const message = body.error || body.message || `HTTP ${response.status}`;\n const details = body.details;\n\n switch (response.status) {\n case 400:\n return new BadRequestError(message, details, requestId);\n case 401:\n return new AuthenticationError(message, details, requestId);\n case 403:\n return new ForbiddenError(message, details, requestId);\n case 404:\n return new NotFoundError(message, details, requestId);\n case 409:\n return new ConflictError(message, details, requestId);\n case 429: {\n const retryAfter = response.headers.get('retry-after');\n return new RateLimitError(\n message,\n retryAfter ? parseInt(retryAfter, 10) : undefined,\n details,\n requestId,\n );\n }\n default:\n if (response.status >= 500) {\n return new ServerError(message, response.status, details, requestId);\n }\n return new OutboundError(message, response.status, details, requestId);\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n SendEmailParams,\n SendEmailResponse,\n BulkEmailParams,\n BulkEmailResponse,\n JobStatusResponse,\n RequestOverrides,\n} from '../types';\n\nexport class EmailResource {\n constructor(private http: HttpClient) {}\n\n async send(params: SendEmailParams, overrides?: RequestOverrides): Promise<SendEmailResponse> {\n return this.http.post<SendEmailResponse>('/v1/email/send', params, overrides?.apiKey);\n }\n\n async bulk(params: BulkEmailParams, overrides?: RequestOverrides): Promise<BulkEmailResponse> {\n return this.http.post<BulkEmailResponse>('/v1/email/bulk', params, overrides?.apiKey);\n }\n\n async status(jobId: string, overrides?: RequestOverrides): Promise<JobStatusResponse> {\n return this.http.get<JobStatusResponse>(`/v1/email/status/${encodeURIComponent(jobId)}`, undefined, overrides?.apiKey);\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n CreateTemplateParams,\n UpdateTemplateParams,\n ListTemplatesParams,\n ListTemplatesResponse,\n Template,\n TemplateResponse,\n TemplateSendParams,\n SendEmailResponse,\n TemplateBulkSendParams,\n TemplateBulkSendResponse,\n TemplatePreviewParams,\n TemplatePreviewResponse,\n TemplateStatsResponse,\n RequestOverrides,\n} from '../types';\n\nexport class TemplatesResource {\n constructor(private http: HttpClient) {}\n\n async create(params: CreateTemplateParams, overrides?: RequestOverrides): Promise<TemplateResponse> {\n return this.http.post<TemplateResponse>('/v1/email-templates', params, overrides?.apiKey);\n }\n\n async list(params?: ListTemplatesParams, overrides?: RequestOverrides): Promise<ListTemplatesResponse> {\n return this.http.get<ListTemplatesResponse>('/v1/email-templates', params as Record<string, unknown>, overrides?.apiKey);\n }\n\n async *listAll(params?: Omit<ListTemplatesParams, 'page'>, overrides?: RequestOverrides): AsyncGenerator<Template> {\n let page = 1;\n const limit = params?.limit || 20;\n\n while (true) {\n const result = await this.list({ ...params, page, limit }, overrides);\n for (const template of result.templates) {\n yield template;\n }\n if (result.templates.length < limit) break;\n page++;\n }\n }\n\n async get(id: string, overrides?: RequestOverrides): Promise<TemplateResponse> {\n return this.http.get<TemplateResponse>(`/v1/email-templates/${encodeURIComponent(id)}`, undefined, overrides?.apiKey);\n }\n\n async update(id: string, params: UpdateTemplateParams, overrides?: RequestOverrides): Promise<TemplateResponse> {\n return this.http.patch<TemplateResponse>(`/v1/email-templates/${encodeURIComponent(id)}`, params, overrides?.apiKey);\n }\n\n async delete(id: string, overrides?: RequestOverrides): Promise<{ message: string; id: string }> {\n return this.http.delete<{ message: string; id: string }>(`/v1/email-templates/${encodeURIComponent(id)}`, overrides?.apiKey);\n }\n\n async duplicate(id: string, params?: { name?: string }, overrides?: RequestOverrides): Promise<TemplateResponse> {\n return this.http.post<TemplateResponse>(`/v1/email-templates/${encodeURIComponent(id)}/duplicate`, params, overrides?.apiKey);\n }\n\n async preview(id: string, params?: TemplatePreviewParams, overrides?: RequestOverrides): Promise<TemplatePreviewResponse> {\n return this.http.post<TemplatePreviewResponse>(`/v1/email-templates/${encodeURIComponent(id)}/preview`, params, overrides?.apiKey);\n }\n\n async send(params: TemplateSendParams, overrides?: RequestOverrides): Promise<SendEmailResponse> {\n return this.http.post<SendEmailResponse>('/v1/email-templates/send', params, overrides?.apiKey);\n }\n\n async bulkSend(params: TemplateBulkSendParams, overrides?: RequestOverrides): Promise<TemplateBulkSendResponse> {\n return this.http.post<TemplateBulkSendResponse>('/v1/email-templates/bulk', params, overrides?.apiKey);\n }\n\n async stats(overrides?: RequestOverrides): Promise<TemplateStatsResponse> {\n return this.http.get<TemplateStatsResponse>('/v1/email-templates/stats', undefined, overrides?.apiKey);\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n ListSuppressionsParams,\n ListSuppressionsResponse,\n AddSuppressionParams,\n SuppressionResponse,\n Suppression,\n RequestOverrides,\n} from '../types';\n\nexport class SuppressionsResource {\n constructor(private http: HttpClient) {}\n\n async list(params?: ListSuppressionsParams, overrides?: RequestOverrides): Promise<ListSuppressionsResponse> {\n return this.http.get<ListSuppressionsResponse>('/v1/tenants/suppressions', params as Record<string, unknown>, overrides?.apiKey);\n }\n\n async *listAll(params?: Omit<ListSuppressionsParams, 'page'>, overrides?: RequestOverrides): AsyncGenerator<Suppression> {\n let page = 1;\n const limit = params?.limit || 50;\n\n while (true) {\n const result = await this.list({ ...params, page, limit }, overrides);\n for (const suppression of result.suppressions) {\n yield suppression;\n }\n if (result.suppressions.length < limit) break;\n page++;\n }\n }\n\n async add(params: AddSuppressionParams, overrides?: RequestOverrides): Promise<SuppressionResponse> {\n return this.http.post<SuppressionResponse>('/v1/tenants/suppressions', params, overrides?.apiKey);\n }\n\n async remove(email: string, overrides?: RequestOverrides): Promise<{ message: string }> {\n return this.http.delete<{ message: string }>(`/v1/tenants/suppressions/${encodeURIComponent(email)}`, overrides?.apiKey);\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n CreateWebhookParams,\n CreateWebhookResponse,\n UpdateWebhookParams,\n UpdateWebhookResponse,\n ListWebhooksResponse,\n RequestOverrides,\n} from '../types';\n\nexport class WebhooksResource {\n constructor(private http: HttpClient) {}\n\n async create(params: CreateWebhookParams, overrides?: RequestOverrides): Promise<CreateWebhookResponse> {\n return this.http.post<CreateWebhookResponse>('/v1/tenants/webhooks', params, overrides?.apiKey);\n }\n\n async list(overrides?: RequestOverrides): Promise<ListWebhooksResponse> {\n return this.http.get<ListWebhooksResponse>('/v1/tenants/webhooks', undefined, overrides?.apiKey);\n }\n\n async update(id: string, params: UpdateWebhookParams, overrides?: RequestOverrides): Promise<UpdateWebhookResponse> {\n return this.http.patch<UpdateWebhookResponse>(`/v1/tenants/webhooks/${encodeURIComponent(id)}`, params, overrides?.apiKey);\n }\n\n async delete(id: string, overrides?: RequestOverrides): Promise<{ message: string; id: string }> {\n return this.http.delete<{ message: string; id: string }>(`/v1/tenants/webhooks/${encodeURIComponent(id)}`, overrides?.apiKey);\n }\n}\n","import type { HttpClient } from '../http';\nimport type { DashboardResponse, QuotaResponse, RequestOverrides } from '../types';\n\nexport class DashboardResource {\n constructor(private http: HttpClient) {}\n\n async get(overrides?: RequestOverrides): Promise<DashboardResponse> {\n return this.http.get<DashboardResponse>('/v1/tenants/dashboard', undefined, overrides?.apiKey);\n }\n\n async quota(overrides?: RequestOverrides): Promise<QuotaResponse> {\n return this.http.get<QuotaResponse>('/v1/tenants/quota', undefined, overrides?.apiKey);\n }\n}\n","import { HttpClient } from './http';\nimport { EmailResource } from './resources/email';\nimport { TemplatesResource } from './resources/templates';\nimport { SuppressionsResource } from './resources/suppressions';\nimport { WebhooksResource } from './resources/webhooks';\nimport { DashboardResource } from './resources/dashboard';\nimport type { OutboundConfig, ResolvedConfig } from './types';\n\nconst BASE_URL = 'https://outbound-api.mastersunion.org';\n\nexport class Outbound {\n readonly email: EmailResource;\n readonly templates: TemplatesResource;\n readonly suppressions: SuppressionsResource;\n readonly webhooks: WebhooksResource;\n readonly dashboard: DashboardResource;\n\n constructor(config?: OutboundConfig) {\n const resolved: ResolvedConfig = {\n apiKey: config?.apiKey,\n baseUrl: config?.baseUrl || BASE_URL,\n timeout: config?.timeout ?? 30_000,\n maxRetries: config?.maxRetries ?? 3,\n retryDelay: config?.retryDelay ?? 1000,\n };\n\n const http = new HttpClient(resolved);\n\n this.email = new EmailResource(http);\n this.templates = new TemplatesResource(http);\n this.suppressions = new SuppressionsResource(http);\n this.webhooks = new WebhooksResource(http);\n this.dashboard = new DashboardResource(http);\n }\n\n /**\n * Verify a webhook signature using HMAC-SHA256.\n * Use this in your webhook handler to validate incoming requests.\n */\n static verifyWebhookSignature(\n payload: string | Buffer,\n signature: string,\n secret: string,\n ): boolean {\n // Dynamic import to keep browser-compatible at the type level\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const crypto = require('crypto') as typeof import('crypto');\n const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex');\n try {\n return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));\n } catch {\n return false;\n }\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -77,19 +77,29 @@ var HttpClient = class {
|
|
|
77
77
|
constructor(config) {
|
|
78
78
|
this.config = config;
|
|
79
79
|
}
|
|
80
|
-
async get(path, params) {
|
|
81
|
-
return this.request("GET", path, { params });
|
|
80
|
+
async get(path, params, apiKey) {
|
|
81
|
+
return this.request("GET", path, { params }, apiKey);
|
|
82
82
|
}
|
|
83
|
-
async post(path, body) {
|
|
84
|
-
return this.request("POST", path, { body });
|
|
83
|
+
async post(path, body, apiKey) {
|
|
84
|
+
return this.request("POST", path, { body }, apiKey);
|
|
85
85
|
}
|
|
86
|
-
async patch(path, body) {
|
|
87
|
-
return this.request("PATCH", path, { body });
|
|
86
|
+
async patch(path, body, apiKey) {
|
|
87
|
+
return this.request("PATCH", path, { body }, apiKey);
|
|
88
88
|
}
|
|
89
|
-
async delete(path) {
|
|
90
|
-
return this.request("DELETE", path);
|
|
89
|
+
async delete(path, apiKey) {
|
|
90
|
+
return this.request("DELETE", path, void 0, apiKey);
|
|
91
91
|
}
|
|
92
|
-
|
|
92
|
+
resolveApiKey(apiKey) {
|
|
93
|
+
const key = apiKey || this.config.apiKey;
|
|
94
|
+
if (!key) {
|
|
95
|
+
throw new AuthenticationError(
|
|
96
|
+
"API key is required. Pass it to the constructor or provide it per method call."
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
return key;
|
|
100
|
+
}
|
|
101
|
+
async request(method, path, options, apiKey) {
|
|
102
|
+
const resolvedKey = this.resolveApiKey(apiKey);
|
|
93
103
|
let lastError;
|
|
94
104
|
for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
|
|
95
105
|
try {
|
|
@@ -99,7 +109,7 @@ var HttpClient = class {
|
|
|
99
109
|
const response = await fetch(url, {
|
|
100
110
|
method,
|
|
101
111
|
headers: {
|
|
102
|
-
"X-Api-Key":
|
|
112
|
+
"X-Api-Key": resolvedKey,
|
|
103
113
|
"Content-Type": "application/json"
|
|
104
114
|
},
|
|
105
115
|
body: options?.body ? JSON.stringify(options.body) : void 0,
|
|
@@ -205,14 +215,14 @@ var EmailResource = class {
|
|
|
205
215
|
constructor(http) {
|
|
206
216
|
this.http = http;
|
|
207
217
|
}
|
|
208
|
-
async send(params) {
|
|
209
|
-
return this.http.post("/v1/email/send", params);
|
|
218
|
+
async send(params, overrides) {
|
|
219
|
+
return this.http.post("/v1/email/send", params, overrides?.apiKey);
|
|
210
220
|
}
|
|
211
|
-
async bulk(params) {
|
|
212
|
-
return this.http.post("/v1/email/bulk", params);
|
|
221
|
+
async bulk(params, overrides) {
|
|
222
|
+
return this.http.post("/v1/email/bulk", params, overrides?.apiKey);
|
|
213
223
|
}
|
|
214
|
-
async status(jobId) {
|
|
215
|
-
return this.http.get(`/v1/email/status/${encodeURIComponent(jobId)}
|
|
224
|
+
async status(jobId, overrides) {
|
|
225
|
+
return this.http.get(`/v1/email/status/${encodeURIComponent(jobId)}`, void 0, overrides?.apiKey);
|
|
216
226
|
}
|
|
217
227
|
};
|
|
218
228
|
|
|
@@ -221,17 +231,17 @@ var TemplatesResource = class {
|
|
|
221
231
|
constructor(http) {
|
|
222
232
|
this.http = http;
|
|
223
233
|
}
|
|
224
|
-
async create(params) {
|
|
225
|
-
return this.http.post("/v1/email-templates", params);
|
|
234
|
+
async create(params, overrides) {
|
|
235
|
+
return this.http.post("/v1/email-templates", params, overrides?.apiKey);
|
|
226
236
|
}
|
|
227
|
-
async list(params) {
|
|
228
|
-
return this.http.get("/v1/email-templates", params);
|
|
237
|
+
async list(params, overrides) {
|
|
238
|
+
return this.http.get("/v1/email-templates", params, overrides?.apiKey);
|
|
229
239
|
}
|
|
230
|
-
async *listAll(params) {
|
|
240
|
+
async *listAll(params, overrides) {
|
|
231
241
|
let page = 1;
|
|
232
242
|
const limit = params?.limit || 20;
|
|
233
243
|
while (true) {
|
|
234
|
-
const result = await this.list({ ...params, page, limit });
|
|
244
|
+
const result = await this.list({ ...params, page, limit }, overrides);
|
|
235
245
|
for (const template of result.templates) {
|
|
236
246
|
yield template;
|
|
237
247
|
}
|
|
@@ -239,29 +249,29 @@ var TemplatesResource = class {
|
|
|
239
249
|
page++;
|
|
240
250
|
}
|
|
241
251
|
}
|
|
242
|
-
async get(id) {
|
|
243
|
-
return this.http.get(`/v1/email-templates/${encodeURIComponent(id)}
|
|
252
|
+
async get(id, overrides) {
|
|
253
|
+
return this.http.get(`/v1/email-templates/${encodeURIComponent(id)}`, void 0, overrides?.apiKey);
|
|
244
254
|
}
|
|
245
|
-
async update(id, params) {
|
|
246
|
-
return this.http.patch(`/v1/email-templates/${encodeURIComponent(id)}`, params);
|
|
255
|
+
async update(id, params, overrides) {
|
|
256
|
+
return this.http.patch(`/v1/email-templates/${encodeURIComponent(id)}`, params, overrides?.apiKey);
|
|
247
257
|
}
|
|
248
|
-
async delete(id) {
|
|
249
|
-
return this.http.delete(`/v1/email-templates/${encodeURIComponent(id)}
|
|
258
|
+
async delete(id, overrides) {
|
|
259
|
+
return this.http.delete(`/v1/email-templates/${encodeURIComponent(id)}`, overrides?.apiKey);
|
|
250
260
|
}
|
|
251
|
-
async duplicate(id, params) {
|
|
252
|
-
return this.http.post(`/v1/email-templates/${encodeURIComponent(id)}/duplicate`, params);
|
|
261
|
+
async duplicate(id, params, overrides) {
|
|
262
|
+
return this.http.post(`/v1/email-templates/${encodeURIComponent(id)}/duplicate`, params, overrides?.apiKey);
|
|
253
263
|
}
|
|
254
|
-
async preview(id, params) {
|
|
255
|
-
return this.http.post(`/v1/email-templates/${encodeURIComponent(id)}/preview`, params);
|
|
264
|
+
async preview(id, params, overrides) {
|
|
265
|
+
return this.http.post(`/v1/email-templates/${encodeURIComponent(id)}/preview`, params, overrides?.apiKey);
|
|
256
266
|
}
|
|
257
|
-
async send(params) {
|
|
258
|
-
return this.http.post("/v1/email-templates/send", params);
|
|
267
|
+
async send(params, overrides) {
|
|
268
|
+
return this.http.post("/v1/email-templates/send", params, overrides?.apiKey);
|
|
259
269
|
}
|
|
260
|
-
async bulkSend(params) {
|
|
261
|
-
return this.http.post("/v1/email-templates/bulk", params);
|
|
270
|
+
async bulkSend(params, overrides) {
|
|
271
|
+
return this.http.post("/v1/email-templates/bulk", params, overrides?.apiKey);
|
|
262
272
|
}
|
|
263
|
-
async stats() {
|
|
264
|
-
return this.http.get("/v1/email-templates/stats");
|
|
273
|
+
async stats(overrides) {
|
|
274
|
+
return this.http.get("/v1/email-templates/stats", void 0, overrides?.apiKey);
|
|
265
275
|
}
|
|
266
276
|
};
|
|
267
277
|
|
|
@@ -270,14 +280,14 @@ var SuppressionsResource = class {
|
|
|
270
280
|
constructor(http) {
|
|
271
281
|
this.http = http;
|
|
272
282
|
}
|
|
273
|
-
async list(params) {
|
|
274
|
-
return this.http.get("/v1/tenants/suppressions", params);
|
|
283
|
+
async list(params, overrides) {
|
|
284
|
+
return this.http.get("/v1/tenants/suppressions", params, overrides?.apiKey);
|
|
275
285
|
}
|
|
276
|
-
async *listAll(params) {
|
|
286
|
+
async *listAll(params, overrides) {
|
|
277
287
|
let page = 1;
|
|
278
288
|
const limit = params?.limit || 50;
|
|
279
289
|
while (true) {
|
|
280
|
-
const result = await this.list({ ...params, page, limit });
|
|
290
|
+
const result = await this.list({ ...params, page, limit }, overrides);
|
|
281
291
|
for (const suppression of result.suppressions) {
|
|
282
292
|
yield suppression;
|
|
283
293
|
}
|
|
@@ -285,11 +295,11 @@ var SuppressionsResource = class {
|
|
|
285
295
|
page++;
|
|
286
296
|
}
|
|
287
297
|
}
|
|
288
|
-
async add(params) {
|
|
289
|
-
return this.http.post("/v1/tenants/suppressions", params);
|
|
298
|
+
async add(params, overrides) {
|
|
299
|
+
return this.http.post("/v1/tenants/suppressions", params, overrides?.apiKey);
|
|
290
300
|
}
|
|
291
|
-
async remove(email) {
|
|
292
|
-
return this.http.delete(`/v1/tenants/suppressions/${encodeURIComponent(email)}
|
|
301
|
+
async remove(email, overrides) {
|
|
302
|
+
return this.http.delete(`/v1/tenants/suppressions/${encodeURIComponent(email)}`, overrides?.apiKey);
|
|
293
303
|
}
|
|
294
304
|
};
|
|
295
305
|
|
|
@@ -298,17 +308,17 @@ var WebhooksResource = class {
|
|
|
298
308
|
constructor(http) {
|
|
299
309
|
this.http = http;
|
|
300
310
|
}
|
|
301
|
-
async create(params) {
|
|
302
|
-
return this.http.post("/v1/tenants/webhooks", params);
|
|
311
|
+
async create(params, overrides) {
|
|
312
|
+
return this.http.post("/v1/tenants/webhooks", params, overrides?.apiKey);
|
|
303
313
|
}
|
|
304
|
-
async list() {
|
|
305
|
-
return this.http.get("/v1/tenants/webhooks");
|
|
314
|
+
async list(overrides) {
|
|
315
|
+
return this.http.get("/v1/tenants/webhooks", void 0, overrides?.apiKey);
|
|
306
316
|
}
|
|
307
|
-
async update(id, params) {
|
|
308
|
-
return this.http.patch(`/v1/tenants/webhooks/${encodeURIComponent(id)}`, params);
|
|
317
|
+
async update(id, params, overrides) {
|
|
318
|
+
return this.http.patch(`/v1/tenants/webhooks/${encodeURIComponent(id)}`, params, overrides?.apiKey);
|
|
309
319
|
}
|
|
310
|
-
async delete(id) {
|
|
311
|
-
return this.http.delete(`/v1/tenants/webhooks/${encodeURIComponent(id)}
|
|
320
|
+
async delete(id, overrides) {
|
|
321
|
+
return this.http.delete(`/v1/tenants/webhooks/${encodeURIComponent(id)}`, overrides?.apiKey);
|
|
312
322
|
}
|
|
313
323
|
};
|
|
314
324
|
|
|
@@ -317,11 +327,11 @@ var DashboardResource = class {
|
|
|
317
327
|
constructor(http) {
|
|
318
328
|
this.http = http;
|
|
319
329
|
}
|
|
320
|
-
async get() {
|
|
321
|
-
return this.http.get("/v1/tenants/dashboard");
|
|
330
|
+
async get(overrides) {
|
|
331
|
+
return this.http.get("/v1/tenants/dashboard", void 0, overrides?.apiKey);
|
|
322
332
|
}
|
|
323
|
-
async quota() {
|
|
324
|
-
return this.http.get("/v1/tenants/quota");
|
|
333
|
+
async quota(overrides) {
|
|
334
|
+
return this.http.get("/v1/tenants/quota", void 0, overrides?.apiKey);
|
|
325
335
|
}
|
|
326
336
|
};
|
|
327
337
|
|
|
@@ -335,17 +345,12 @@ var Outbound = class {
|
|
|
335
345
|
dashboard;
|
|
336
346
|
constructor(config) {
|
|
337
347
|
const resolved = {
|
|
338
|
-
apiKey: config?.apiKey
|
|
348
|
+
apiKey: config?.apiKey,
|
|
339
349
|
baseUrl: config?.baseUrl || BASE_URL,
|
|
340
350
|
timeout: config?.timeout ?? 3e4,
|
|
341
351
|
maxRetries: config?.maxRetries ?? 3,
|
|
342
352
|
retryDelay: config?.retryDelay ?? 1e3
|
|
343
353
|
};
|
|
344
|
-
if (!resolved.apiKey) {
|
|
345
|
-
throw new AuthenticationError(
|
|
346
|
-
"API key is required. Pass it to the constructor or set the OUTBOUND_API_KEY environment variable."
|
|
347
|
-
);
|
|
348
|
-
}
|
|
349
354
|
const http = new HttpClient(resolved);
|
|
350
355
|
this.email = new EmailResource(http);
|
|
351
356
|
this.templates = new TemplatesResource(http);
|
|
@@ -366,12 +371,6 @@ var Outbound = class {
|
|
|
366
371
|
return false;
|
|
367
372
|
}
|
|
368
373
|
}
|
|
369
|
-
getEnv(key) {
|
|
370
|
-
if (typeof process !== "undefined" && process.env) {
|
|
371
|
-
return process.env[key];
|
|
372
|
-
}
|
|
373
|
-
return void 0;
|
|
374
|
-
}
|
|
375
374
|
};
|
|
376
375
|
export {
|
|
377
376
|
AuthenticationError,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/resources/email.ts","../src/resources/templates.ts","../src/resources/suppressions.ts","../src/resources/webhooks.ts","../src/resources/dashboard.ts","../src/client.ts"],"sourcesContent":["export class OutboundError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly details?: unknown,\n public readonly requestId?: string,\n ) {\n super(message);\n this.name = 'OutboundError';\n }\n}\n\nexport class BadRequestError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 400, details, requestId);\n this.name = 'BadRequestError';\n }\n}\n\nexport class AuthenticationError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 401, details, requestId);\n this.name = 'AuthenticationError';\n }\n}\n\nexport class ForbiddenError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 403, details, requestId);\n this.name = 'ForbiddenError';\n }\n}\n\nexport class NotFoundError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 404, details, requestId);\n this.name = 'NotFoundError';\n }\n}\n\nexport class ConflictError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 409, details, requestId);\n this.name = 'ConflictError';\n }\n}\n\nexport class RateLimitError extends OutboundError {\n public readonly retryAfter?: number;\n\n constructor(message: string, retryAfter?: number, details?: unknown, requestId?: string) {\n super(message, 429, details, requestId);\n this.name = 'RateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\nexport class ServerError extends OutboundError {\n constructor(message: string, statusCode: number = 500, details?: unknown, requestId?: string) {\n super(message, statusCode, details, requestId);\n this.name = 'ServerError';\n }\n}\n\nexport class TimeoutError extends OutboundError {\n constructor(message: string = 'Request timed out') {\n super(message, 0);\n this.name = 'TimeoutError';\n }\n}\n\nexport class NetworkError extends OutboundError {\n constructor(message: string = 'Network request failed') {\n super(message, 0);\n this.name = 'NetworkError';\n }\n}\n","import type { ResolvedConfig } from './types';\nimport {\n OutboundError,\n BadRequestError,\n AuthenticationError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n RateLimitError,\n ServerError,\n TimeoutError,\n NetworkError,\n} from './errors';\n\nexport interface RequestOptions {\n body?: unknown;\n params?: Record<string, unknown>;\n}\n\nexport class HttpClient {\n constructor(private config: ResolvedConfig) {}\n\n async get<T>(path: string, params?: Record<string, unknown>): Promise<T> {\n return this.request<T>('GET', path, { params });\n }\n\n async post<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('POST', path, { body });\n }\n\n async patch<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('PATCH', path, { body });\n }\n\n async delete<T>(path: string): Promise<T> {\n return this.request<T>('DELETE', path);\n }\n\n private async request<T>(method: string, path: string, options?: RequestOptions): Promise<T> {\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const url = this.buildUrl(path, options?.params);\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n const response = await fetch(url, {\n method,\n headers: {\n 'X-Api-Key': this.config.apiKey,\n 'Content-Type': 'application/json',\n },\n body: options?.body ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n const error = await this.parseError(response);\n\n // Only retry on 429 and 5xx\n if (response.status === 429 || response.status >= 500) {\n lastError = error;\n\n if (attempt < this.config.maxRetries) {\n const retryAfter = error instanceof RateLimitError && error.retryAfter\n ? error.retryAfter * 1000\n : this.config.retryDelay * Math.pow(2, attempt);\n\n await this.sleep(retryAfter);\n continue;\n }\n }\n\n throw error;\n } catch (err) {\n if (err instanceof OutboundError) {\n // Already a typed error from parseError — check if retryable\n if ((err.statusCode === 429 || err.statusCode >= 500) && attempt < this.config.maxRetries) {\n lastError = err;\n const retryAfter = err instanceof RateLimitError && err.retryAfter\n ? err.retryAfter * 1000\n : this.config.retryDelay * Math.pow(2, attempt);\n await this.sleep(retryAfter);\n continue;\n }\n throw err;\n }\n\n if (err instanceof DOMException && err.name === 'AbortError') {\n lastError = new TimeoutError(`Request timed out after ${this.config.timeout}ms`);\n if (attempt < this.config.maxRetries) {\n await this.sleep(this.config.retryDelay * Math.pow(2, attempt));\n continue;\n }\n throw lastError;\n }\n\n lastError = new NetworkError((err as Error).message);\n if (attempt < this.config.maxRetries) {\n await this.sleep(this.config.retryDelay * Math.pow(2, attempt));\n continue;\n }\n throw lastError;\n }\n }\n\n throw lastError || new NetworkError('Request failed after retries');\n }\n\n private buildUrl(path: string, params?: Record<string, unknown>): string {\n const base = this.config.baseUrl.replace(/\\/+$/, '');\n const url = new URL(`${base}${path}`);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n\n return url.toString();\n }\n\n private async parseError(response: Response): Promise<OutboundError> {\n let body: { error?: string; message?: string; details?: unknown } = {};\n const requestId = response.headers.get('x-request-id') || undefined;\n\n try {\n body = (await response.json()) as typeof body;\n } catch {\n // Response may not be JSON\n }\n\n const message = body.error || body.message || `HTTP ${response.status}`;\n const details = body.details;\n\n switch (response.status) {\n case 400:\n return new BadRequestError(message, details, requestId);\n case 401:\n return new AuthenticationError(message, details, requestId);\n case 403:\n return new ForbiddenError(message, details, requestId);\n case 404:\n return new NotFoundError(message, details, requestId);\n case 409:\n return new ConflictError(message, details, requestId);\n case 429: {\n const retryAfter = response.headers.get('retry-after');\n return new RateLimitError(\n message,\n retryAfter ? parseInt(retryAfter, 10) : undefined,\n details,\n requestId,\n );\n }\n default:\n if (response.status >= 500) {\n return new ServerError(message, response.status, details, requestId);\n }\n return new OutboundError(message, response.status, details, requestId);\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n SendEmailParams,\n SendEmailResponse,\n BulkEmailParams,\n BulkEmailResponse,\n JobStatusResponse,\n} from '../types';\n\nexport class EmailResource {\n constructor(private http: HttpClient) {}\n\n async send(params: SendEmailParams): Promise<SendEmailResponse> {\n return this.http.post<SendEmailResponse>('/v1/email/send', params);\n }\n\n async bulk(params: BulkEmailParams): Promise<BulkEmailResponse> {\n return this.http.post<BulkEmailResponse>('/v1/email/bulk', params);\n }\n\n async status(jobId: string): Promise<JobStatusResponse> {\n return this.http.get<JobStatusResponse>(`/v1/email/status/${encodeURIComponent(jobId)}`);\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n CreateTemplateParams,\n UpdateTemplateParams,\n ListTemplatesParams,\n ListTemplatesResponse,\n Template,\n TemplateResponse,\n TemplateSendParams,\n SendEmailResponse,\n TemplateBulkSendParams,\n TemplateBulkSendResponse,\n TemplatePreviewParams,\n TemplatePreviewResponse,\n TemplateStatsResponse,\n} from '../types';\n\nexport class TemplatesResource {\n constructor(private http: HttpClient) {}\n\n async create(params: CreateTemplateParams): Promise<TemplateResponse> {\n return this.http.post<TemplateResponse>('/v1/email-templates', params);\n }\n\n async list(params?: ListTemplatesParams): Promise<ListTemplatesResponse> {\n return this.http.get<ListTemplatesResponse>('/v1/email-templates', params as Record<string, unknown>);\n }\n\n async *listAll(params?: Omit<ListTemplatesParams, 'page'>): AsyncGenerator<Template> {\n let page = 1;\n const limit = params?.limit || 20;\n\n while (true) {\n const result = await this.list({ ...params, page, limit });\n for (const template of result.templates) {\n yield template;\n }\n if (result.templates.length < limit) break;\n page++;\n }\n }\n\n async get(id: string): Promise<TemplateResponse> {\n return this.http.get<TemplateResponse>(`/v1/email-templates/${encodeURIComponent(id)}`);\n }\n\n async update(id: string, params: UpdateTemplateParams): Promise<TemplateResponse> {\n return this.http.patch<TemplateResponse>(`/v1/email-templates/${encodeURIComponent(id)}`, params);\n }\n\n async delete(id: string): Promise<{ message: string; id: string }> {\n return this.http.delete<{ message: string; id: string }>(`/v1/email-templates/${encodeURIComponent(id)}`);\n }\n\n async duplicate(id: string, params?: { name?: string }): Promise<TemplateResponse> {\n return this.http.post<TemplateResponse>(`/v1/email-templates/${encodeURIComponent(id)}/duplicate`, params);\n }\n\n async preview(id: string, params?: TemplatePreviewParams): Promise<TemplatePreviewResponse> {\n return this.http.post<TemplatePreviewResponse>(`/v1/email-templates/${encodeURIComponent(id)}/preview`, params);\n }\n\n async send(params: TemplateSendParams): Promise<SendEmailResponse> {\n return this.http.post<SendEmailResponse>('/v1/email-templates/send', params);\n }\n\n async bulkSend(params: TemplateBulkSendParams): Promise<TemplateBulkSendResponse> {\n return this.http.post<TemplateBulkSendResponse>('/v1/email-templates/bulk', params);\n }\n\n async stats(): Promise<TemplateStatsResponse> {\n return this.http.get<TemplateStatsResponse>('/v1/email-templates/stats');\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n ListSuppressionsParams,\n ListSuppressionsResponse,\n AddSuppressionParams,\n SuppressionResponse,\n Suppression,\n} from '../types';\n\nexport class SuppressionsResource {\n constructor(private http: HttpClient) {}\n\n async list(params?: ListSuppressionsParams): Promise<ListSuppressionsResponse> {\n return this.http.get<ListSuppressionsResponse>('/v1/tenants/suppressions', params as Record<string, unknown>);\n }\n\n async *listAll(params?: Omit<ListSuppressionsParams, 'page'>): AsyncGenerator<Suppression> {\n let page = 1;\n const limit = params?.limit || 50;\n\n while (true) {\n const result = await this.list({ ...params, page, limit });\n for (const suppression of result.suppressions) {\n yield suppression;\n }\n if (result.suppressions.length < limit) break;\n page++;\n }\n }\n\n async add(params: AddSuppressionParams): Promise<SuppressionResponse> {\n return this.http.post<SuppressionResponse>('/v1/tenants/suppressions', params);\n }\n\n async remove(email: string): Promise<{ message: string }> {\n return this.http.delete<{ message: string }>(`/v1/tenants/suppressions/${encodeURIComponent(email)}`);\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n CreateWebhookParams,\n CreateWebhookResponse,\n UpdateWebhookParams,\n UpdateWebhookResponse,\n ListWebhooksResponse,\n} from '../types';\n\nexport class WebhooksResource {\n constructor(private http: HttpClient) {}\n\n async create(params: CreateWebhookParams): Promise<CreateWebhookResponse> {\n return this.http.post<CreateWebhookResponse>('/v1/tenants/webhooks', params);\n }\n\n async list(): Promise<ListWebhooksResponse> {\n return this.http.get<ListWebhooksResponse>('/v1/tenants/webhooks');\n }\n\n async update(id: string, params: UpdateWebhookParams): Promise<UpdateWebhookResponse> {\n return this.http.patch<UpdateWebhookResponse>(`/v1/tenants/webhooks/${encodeURIComponent(id)}`, params);\n }\n\n async delete(id: string): Promise<{ message: string; id: string }> {\n return this.http.delete<{ message: string; id: string }>(`/v1/tenants/webhooks/${encodeURIComponent(id)}`);\n }\n}\n","import type { HttpClient } from '../http';\nimport type { DashboardResponse, QuotaResponse } from '../types';\n\nexport class DashboardResource {\n constructor(private http: HttpClient) {}\n\n async get(): Promise<DashboardResponse> {\n return this.http.get<DashboardResponse>('/v1/tenants/dashboard');\n }\n\n async quota(): Promise<QuotaResponse> {\n return this.http.get<QuotaResponse>('/v1/tenants/quota');\n }\n}\n","import { HttpClient } from './http';\nimport { AuthenticationError } from './errors';\nimport { EmailResource } from './resources/email';\nimport { TemplatesResource } from './resources/templates';\nimport { SuppressionsResource } from './resources/suppressions';\nimport { WebhooksResource } from './resources/webhooks';\nimport { DashboardResource } from './resources/dashboard';\nimport type { OutboundConfig, ResolvedConfig } from './types';\n\nconst BASE_URL = 'https://outbound-api.mastersunion.org';\n\nexport class Outbound {\n readonly email: EmailResource;\n readonly templates: TemplatesResource;\n readonly suppressions: SuppressionsResource;\n readonly webhooks: WebhooksResource;\n readonly dashboard: DashboardResource;\n\n constructor(config?: OutboundConfig) {\n const resolved: ResolvedConfig = {\n apiKey: config?.apiKey || this.getEnv('OUTBOUND_API_KEY') || '',\n baseUrl: config?.baseUrl || BASE_URL,\n timeout: config?.timeout ?? 30_000,\n maxRetries: config?.maxRetries ?? 3,\n retryDelay: config?.retryDelay ?? 1000,\n };\n\n if (!resolved.apiKey) {\n throw new AuthenticationError(\n 'API key is required. Pass it to the constructor or set the OUTBOUND_API_KEY environment variable.',\n );\n }\n\n const http = new HttpClient(resolved);\n\n this.email = new EmailResource(http);\n this.templates = new TemplatesResource(http);\n this.suppressions = new SuppressionsResource(http);\n this.webhooks = new WebhooksResource(http);\n this.dashboard = new DashboardResource(http);\n }\n\n /**\n * Verify a webhook signature using HMAC-SHA256.\n * Use this in your webhook handler to validate incoming requests.\n */\n static verifyWebhookSignature(\n payload: string | Buffer,\n signature: string,\n secret: string,\n ): boolean {\n // Dynamic import to keep browser-compatible at the type level\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const crypto = require('crypto') as typeof import('crypto');\n const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex');\n try {\n return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));\n } catch {\n return false;\n }\n }\n\n private getEnv(key: string): string | undefined {\n if (typeof process !== 'undefined' && process.env) {\n return process.env[key];\n }\n return undefined;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/resources/email.ts","../src/resources/templates.ts","../src/resources/suppressions.ts","../src/resources/webhooks.ts","../src/resources/dashboard.ts","../src/client.ts"],"sourcesContent":["export class OutboundError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly details?: unknown,\n public readonly requestId?: string,\n ) {\n super(message);\n this.name = 'OutboundError';\n }\n}\n\nexport class BadRequestError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 400, details, requestId);\n this.name = 'BadRequestError';\n }\n}\n\nexport class AuthenticationError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 401, details, requestId);\n this.name = 'AuthenticationError';\n }\n}\n\nexport class ForbiddenError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 403, details, requestId);\n this.name = 'ForbiddenError';\n }\n}\n\nexport class NotFoundError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 404, details, requestId);\n this.name = 'NotFoundError';\n }\n}\n\nexport class ConflictError extends OutboundError {\n constructor(message: string, details?: unknown, requestId?: string) {\n super(message, 409, details, requestId);\n this.name = 'ConflictError';\n }\n}\n\nexport class RateLimitError extends OutboundError {\n public readonly retryAfter?: number;\n\n constructor(message: string, retryAfter?: number, details?: unknown, requestId?: string) {\n super(message, 429, details, requestId);\n this.name = 'RateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\nexport class ServerError extends OutboundError {\n constructor(message: string, statusCode: number = 500, details?: unknown, requestId?: string) {\n super(message, statusCode, details, requestId);\n this.name = 'ServerError';\n }\n}\n\nexport class TimeoutError extends OutboundError {\n constructor(message: string = 'Request timed out') {\n super(message, 0);\n this.name = 'TimeoutError';\n }\n}\n\nexport class NetworkError extends OutboundError {\n constructor(message: string = 'Network request failed') {\n super(message, 0);\n this.name = 'NetworkError';\n }\n}\n","import type { ResolvedConfig } from './types';\nimport {\n OutboundError,\n BadRequestError,\n AuthenticationError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n RateLimitError,\n ServerError,\n TimeoutError,\n NetworkError,\n} from './errors';\n\nexport interface RequestOptions {\n body?: unknown;\n params?: Record<string, unknown>;\n}\n\nexport class HttpClient {\n constructor(private config: ResolvedConfig) {}\n\n async get<T>(path: string, params?: Record<string, unknown>, apiKey?: string): Promise<T> {\n return this.request<T>('GET', path, { params }, apiKey);\n }\n\n async post<T>(path: string, body?: unknown, apiKey?: string): Promise<T> {\n return this.request<T>('POST', path, { body }, apiKey);\n }\n\n async patch<T>(path: string, body?: unknown, apiKey?: string): Promise<T> {\n return this.request<T>('PATCH', path, { body }, apiKey);\n }\n\n async delete<T>(path: string, apiKey?: string): Promise<T> {\n return this.request<T>('DELETE', path, undefined, apiKey);\n }\n\n private resolveApiKey(apiKey?: string): string {\n const key = apiKey || this.config.apiKey;\n if (!key) {\n throw new AuthenticationError(\n 'API key is required. Pass it to the constructor or provide it per method call.',\n );\n }\n return key;\n }\n\n private async request<T>(method: string, path: string, options?: RequestOptions, apiKey?: string): Promise<T> {\n const resolvedKey = this.resolveApiKey(apiKey);\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const url = this.buildUrl(path, options?.params);\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n const response = await fetch(url, {\n method,\n headers: {\n 'X-Api-Key': resolvedKey,\n 'Content-Type': 'application/json',\n },\n body: options?.body ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n const error = await this.parseError(response);\n\n // Only retry on 429 and 5xx\n if (response.status === 429 || response.status >= 500) {\n lastError = error;\n\n if (attempt < this.config.maxRetries) {\n const retryAfter = error instanceof RateLimitError && error.retryAfter\n ? error.retryAfter * 1000\n : this.config.retryDelay * Math.pow(2, attempt);\n\n await this.sleep(retryAfter);\n continue;\n }\n }\n\n throw error;\n } catch (err) {\n if (err instanceof OutboundError) {\n // Already a typed error from parseError — check if retryable\n if ((err.statusCode === 429 || err.statusCode >= 500) && attempt < this.config.maxRetries) {\n lastError = err;\n const retryAfter = err instanceof RateLimitError && err.retryAfter\n ? err.retryAfter * 1000\n : this.config.retryDelay * Math.pow(2, attempt);\n await this.sleep(retryAfter);\n continue;\n }\n throw err;\n }\n\n if (err instanceof DOMException && err.name === 'AbortError') {\n lastError = new TimeoutError(`Request timed out after ${this.config.timeout}ms`);\n if (attempt < this.config.maxRetries) {\n await this.sleep(this.config.retryDelay * Math.pow(2, attempt));\n continue;\n }\n throw lastError;\n }\n\n lastError = new NetworkError((err as Error).message);\n if (attempt < this.config.maxRetries) {\n await this.sleep(this.config.retryDelay * Math.pow(2, attempt));\n continue;\n }\n throw lastError;\n }\n }\n\n throw lastError || new NetworkError('Request failed after retries');\n }\n\n private buildUrl(path: string, params?: Record<string, unknown>): string {\n const base = this.config.baseUrl.replace(/\\/+$/, '');\n const url = new URL(`${base}${path}`);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n\n return url.toString();\n }\n\n private async parseError(response: Response): Promise<OutboundError> {\n let body: { error?: string; message?: string; details?: unknown } = {};\n const requestId = response.headers.get('x-request-id') || undefined;\n\n try {\n body = (await response.json()) as typeof body;\n } catch {\n // Response may not be JSON\n }\n\n const message = body.error || body.message || `HTTP ${response.status}`;\n const details = body.details;\n\n switch (response.status) {\n case 400:\n return new BadRequestError(message, details, requestId);\n case 401:\n return new AuthenticationError(message, details, requestId);\n case 403:\n return new ForbiddenError(message, details, requestId);\n case 404:\n return new NotFoundError(message, details, requestId);\n case 409:\n return new ConflictError(message, details, requestId);\n case 429: {\n const retryAfter = response.headers.get('retry-after');\n return new RateLimitError(\n message,\n retryAfter ? parseInt(retryAfter, 10) : undefined,\n details,\n requestId,\n );\n }\n default:\n if (response.status >= 500) {\n return new ServerError(message, response.status, details, requestId);\n }\n return new OutboundError(message, response.status, details, requestId);\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n SendEmailParams,\n SendEmailResponse,\n BulkEmailParams,\n BulkEmailResponse,\n JobStatusResponse,\n RequestOverrides,\n} from '../types';\n\nexport class EmailResource {\n constructor(private http: HttpClient) {}\n\n async send(params: SendEmailParams, overrides?: RequestOverrides): Promise<SendEmailResponse> {\n return this.http.post<SendEmailResponse>('/v1/email/send', params, overrides?.apiKey);\n }\n\n async bulk(params: BulkEmailParams, overrides?: RequestOverrides): Promise<BulkEmailResponse> {\n return this.http.post<BulkEmailResponse>('/v1/email/bulk', params, overrides?.apiKey);\n }\n\n async status(jobId: string, overrides?: RequestOverrides): Promise<JobStatusResponse> {\n return this.http.get<JobStatusResponse>(`/v1/email/status/${encodeURIComponent(jobId)}`, undefined, overrides?.apiKey);\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n CreateTemplateParams,\n UpdateTemplateParams,\n ListTemplatesParams,\n ListTemplatesResponse,\n Template,\n TemplateResponse,\n TemplateSendParams,\n SendEmailResponse,\n TemplateBulkSendParams,\n TemplateBulkSendResponse,\n TemplatePreviewParams,\n TemplatePreviewResponse,\n TemplateStatsResponse,\n RequestOverrides,\n} from '../types';\n\nexport class TemplatesResource {\n constructor(private http: HttpClient) {}\n\n async create(params: CreateTemplateParams, overrides?: RequestOverrides): Promise<TemplateResponse> {\n return this.http.post<TemplateResponse>('/v1/email-templates', params, overrides?.apiKey);\n }\n\n async list(params?: ListTemplatesParams, overrides?: RequestOverrides): Promise<ListTemplatesResponse> {\n return this.http.get<ListTemplatesResponse>('/v1/email-templates', params as Record<string, unknown>, overrides?.apiKey);\n }\n\n async *listAll(params?: Omit<ListTemplatesParams, 'page'>, overrides?: RequestOverrides): AsyncGenerator<Template> {\n let page = 1;\n const limit = params?.limit || 20;\n\n while (true) {\n const result = await this.list({ ...params, page, limit }, overrides);\n for (const template of result.templates) {\n yield template;\n }\n if (result.templates.length < limit) break;\n page++;\n }\n }\n\n async get(id: string, overrides?: RequestOverrides): Promise<TemplateResponse> {\n return this.http.get<TemplateResponse>(`/v1/email-templates/${encodeURIComponent(id)}`, undefined, overrides?.apiKey);\n }\n\n async update(id: string, params: UpdateTemplateParams, overrides?: RequestOverrides): Promise<TemplateResponse> {\n return this.http.patch<TemplateResponse>(`/v1/email-templates/${encodeURIComponent(id)}`, params, overrides?.apiKey);\n }\n\n async delete(id: string, overrides?: RequestOverrides): Promise<{ message: string; id: string }> {\n return this.http.delete<{ message: string; id: string }>(`/v1/email-templates/${encodeURIComponent(id)}`, overrides?.apiKey);\n }\n\n async duplicate(id: string, params?: { name?: string }, overrides?: RequestOverrides): Promise<TemplateResponse> {\n return this.http.post<TemplateResponse>(`/v1/email-templates/${encodeURIComponent(id)}/duplicate`, params, overrides?.apiKey);\n }\n\n async preview(id: string, params?: TemplatePreviewParams, overrides?: RequestOverrides): Promise<TemplatePreviewResponse> {\n return this.http.post<TemplatePreviewResponse>(`/v1/email-templates/${encodeURIComponent(id)}/preview`, params, overrides?.apiKey);\n }\n\n async send(params: TemplateSendParams, overrides?: RequestOverrides): Promise<SendEmailResponse> {\n return this.http.post<SendEmailResponse>('/v1/email-templates/send', params, overrides?.apiKey);\n }\n\n async bulkSend(params: TemplateBulkSendParams, overrides?: RequestOverrides): Promise<TemplateBulkSendResponse> {\n return this.http.post<TemplateBulkSendResponse>('/v1/email-templates/bulk', params, overrides?.apiKey);\n }\n\n async stats(overrides?: RequestOverrides): Promise<TemplateStatsResponse> {\n return this.http.get<TemplateStatsResponse>('/v1/email-templates/stats', undefined, overrides?.apiKey);\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n ListSuppressionsParams,\n ListSuppressionsResponse,\n AddSuppressionParams,\n SuppressionResponse,\n Suppression,\n RequestOverrides,\n} from '../types';\n\nexport class SuppressionsResource {\n constructor(private http: HttpClient) {}\n\n async list(params?: ListSuppressionsParams, overrides?: RequestOverrides): Promise<ListSuppressionsResponse> {\n return this.http.get<ListSuppressionsResponse>('/v1/tenants/suppressions', params as Record<string, unknown>, overrides?.apiKey);\n }\n\n async *listAll(params?: Omit<ListSuppressionsParams, 'page'>, overrides?: RequestOverrides): AsyncGenerator<Suppression> {\n let page = 1;\n const limit = params?.limit || 50;\n\n while (true) {\n const result = await this.list({ ...params, page, limit }, overrides);\n for (const suppression of result.suppressions) {\n yield suppression;\n }\n if (result.suppressions.length < limit) break;\n page++;\n }\n }\n\n async add(params: AddSuppressionParams, overrides?: RequestOverrides): Promise<SuppressionResponse> {\n return this.http.post<SuppressionResponse>('/v1/tenants/suppressions', params, overrides?.apiKey);\n }\n\n async remove(email: string, overrides?: RequestOverrides): Promise<{ message: string }> {\n return this.http.delete<{ message: string }>(`/v1/tenants/suppressions/${encodeURIComponent(email)}`, overrides?.apiKey);\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n CreateWebhookParams,\n CreateWebhookResponse,\n UpdateWebhookParams,\n UpdateWebhookResponse,\n ListWebhooksResponse,\n RequestOverrides,\n} from '../types';\n\nexport class WebhooksResource {\n constructor(private http: HttpClient) {}\n\n async create(params: CreateWebhookParams, overrides?: RequestOverrides): Promise<CreateWebhookResponse> {\n return this.http.post<CreateWebhookResponse>('/v1/tenants/webhooks', params, overrides?.apiKey);\n }\n\n async list(overrides?: RequestOverrides): Promise<ListWebhooksResponse> {\n return this.http.get<ListWebhooksResponse>('/v1/tenants/webhooks', undefined, overrides?.apiKey);\n }\n\n async update(id: string, params: UpdateWebhookParams, overrides?: RequestOverrides): Promise<UpdateWebhookResponse> {\n return this.http.patch<UpdateWebhookResponse>(`/v1/tenants/webhooks/${encodeURIComponent(id)}`, params, overrides?.apiKey);\n }\n\n async delete(id: string, overrides?: RequestOverrides): Promise<{ message: string; id: string }> {\n return this.http.delete<{ message: string; id: string }>(`/v1/tenants/webhooks/${encodeURIComponent(id)}`, overrides?.apiKey);\n }\n}\n","import type { HttpClient } from '../http';\nimport type { DashboardResponse, QuotaResponse, RequestOverrides } from '../types';\n\nexport class DashboardResource {\n constructor(private http: HttpClient) {}\n\n async get(overrides?: RequestOverrides): Promise<DashboardResponse> {\n return this.http.get<DashboardResponse>('/v1/tenants/dashboard', undefined, overrides?.apiKey);\n }\n\n async quota(overrides?: RequestOverrides): Promise<QuotaResponse> {\n return this.http.get<QuotaResponse>('/v1/tenants/quota', undefined, overrides?.apiKey);\n }\n}\n","import { HttpClient } from './http';\nimport { EmailResource } from './resources/email';\nimport { TemplatesResource } from './resources/templates';\nimport { SuppressionsResource } from './resources/suppressions';\nimport { WebhooksResource } from './resources/webhooks';\nimport { DashboardResource } from './resources/dashboard';\nimport type { OutboundConfig, ResolvedConfig } from './types';\n\nconst BASE_URL = 'https://outbound-api.mastersunion.org';\n\nexport class Outbound {\n readonly email: EmailResource;\n readonly templates: TemplatesResource;\n readonly suppressions: SuppressionsResource;\n readonly webhooks: WebhooksResource;\n readonly dashboard: DashboardResource;\n\n constructor(config?: OutboundConfig) {\n const resolved: ResolvedConfig = {\n apiKey: config?.apiKey,\n baseUrl: config?.baseUrl || BASE_URL,\n timeout: config?.timeout ?? 30_000,\n maxRetries: config?.maxRetries ?? 3,\n retryDelay: config?.retryDelay ?? 1000,\n };\n\n const http = new HttpClient(resolved);\n\n this.email = new EmailResource(http);\n this.templates = new TemplatesResource(http);\n this.suppressions = new SuppressionsResource(http);\n this.webhooks = new WebhooksResource(http);\n this.dashboard = new DashboardResource(http);\n }\n\n /**\n * Verify a webhook signature using HMAC-SHA256.\n * Use this in your webhook handler to validate incoming requests.\n */\n static verifyWebhookSignature(\n payload: string | Buffer,\n signature: string,\n secret: string,\n ): boolean {\n // Dynamic import to keep browser-compatible at the type level\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const crypto = require('crypto') as typeof import('crypto');\n const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex');\n try {\n return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));\n } catch {\n return false;\n }\n }\n}\n"],"mappings":"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","names":[]}
|