@masters-union/outbound-sdk 0.1.3 → 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 CHANGED
@@ -13,19 +13,10 @@ npm install outbound-sdk
13
13
  ```ts
14
14
  import { Outbound } from 'outbound-sdk';
15
15
 
16
- const outbound = new Outbound({
17
- baseUrl: 'https://api.your-domain.com', // optional, defaults to production
18
- });
19
-
20
- const apiKey = 'mu_outbound_...'; // your tenant API key
21
- ```
22
-
23
- Every method requires an `apiKey` as the first argument, allowing you to use multiple tenants with a single client instance.
16
+ // Single tenant set API key once
17
+ const outbound = new Outbound({ apiKey: 'mu_outbound_...' });
24
18
 
25
- ### Send an Email
26
-
27
- ```ts
28
- const { jobId, messageId } = await outbound.email.send(apiKey, {
19
+ const { jobId } = await outbound.email.send({
29
20
  toEmail: 'user@example.com',
30
21
  fromEmail: 'noreply@company.com',
31
22
  emailSubject: 'Welcome!',
@@ -33,10 +24,26 @@ const { jobId, messageId } = await outbound.email.send(apiKey, {
33
24
  });
34
25
  ```
35
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
+
36
43
  ### Send Bulk Emails
37
44
 
38
45
  ```ts
39
- const result = await outbound.email.bulk(apiKey, {
46
+ const result = await outbound.email.bulk({
40
47
  fromEmail: 'noreply@company.com',
41
48
  emailSubject: 'Newsletter',
42
49
  emails: [
@@ -50,7 +57,7 @@ const result = await outbound.email.bulk(apiKey, {
50
57
  ### Check Job Status
51
58
 
52
59
  ```ts
53
- const status = await outbound.email.status(apiKey, 'job-uuid');
60
+ const status = await outbound.email.status('job-uuid');
54
61
  // status.job, status.recipients
55
62
  ```
56
63
 
@@ -58,7 +65,7 @@ const status = await outbound.email.status(apiKey, 'job-uuid');
58
65
 
59
66
  ```ts
60
67
  // Create
61
- const { template } = await outbound.templates.create(apiKey, {
68
+ const { template } = await outbound.templates.create({
62
69
  name: 'welcome',
63
70
  subject: 'Welcome {{firstName}}!',
64
71
  htmlBody: '<h1>Hello {{firstName}}</h1>',
@@ -66,10 +73,10 @@ const { template } = await outbound.templates.create(apiKey, {
66
73
  });
67
74
 
68
75
  // List
69
- const { templates, total } = await outbound.templates.list(apiKey, { status: 'active' });
76
+ const { templates, total } = await outbound.templates.list({ status: 'active' });
70
77
 
71
78
  // Send using template
72
- const { jobId } = await outbound.templates.send(apiKey, {
79
+ const { jobId } = await outbound.templates.send({
73
80
  templateId: template.id,
74
81
  toEmail: 'user@example.com',
75
82
  fromEmail: 'noreply@company.com',
@@ -77,7 +84,7 @@ const { jobId } = await outbound.templates.send(apiKey, {
77
84
  });
78
85
 
79
86
  // Bulk send using template
80
- const bulk = await outbound.templates.bulkSend(apiKey, {
87
+ const bulk = await outbound.templates.bulkSend({
81
88
  templateId: template.id,
82
89
  fromEmail: 'noreply@company.com',
83
90
  recipients: [
@@ -87,7 +94,7 @@ const bulk = await outbound.templates.bulkSend(apiKey, {
87
94
  });
88
95
 
89
96
  // Preview
90
- const preview = await outbound.templates.preview(apiKey, template.id, {
97
+ const preview = await outbound.templates.preview(template.id, {
91
98
  variables: { firstName: 'John' },
92
99
  });
93
100
  ```
@@ -96,20 +103,20 @@ const preview = await outbound.templates.preview(apiKey, template.id, {
96
103
 
97
104
  ```ts
98
105
  // Add
99
- await outbound.suppressions.add(apiKey, { email: 'bad@example.com', reason: 'manual' });
106
+ await outbound.suppressions.add({ email: 'bad@example.com', reason: 'manual' });
100
107
 
101
108
  // List
102
- const { suppressions } = await outbound.suppressions.list(apiKey, { reason: 'bounce' });
109
+ const { suppressions } = await outbound.suppressions.list({ reason: 'bounce' });
103
110
 
104
111
  // Remove
105
- await outbound.suppressions.remove(apiKey, 'bad@example.com');
112
+ await outbound.suppressions.remove('bad@example.com');
106
113
  ```
107
114
 
108
115
  ### Webhooks
109
116
 
110
117
  ```ts
111
118
  // Create
112
- const { webhook, secret } = await outbound.webhooks.create(apiKey, {
119
+ const { webhook, secret } = await outbound.webhooks.create({
113
120
  url: 'https://myapp.com/webhooks/outbound',
114
121
  events: ['delivery', 'bounce', 'complaint'],
115
122
  });
@@ -122,30 +129,18 @@ const isValid = Outbound.verifyWebhookSignature(rawBody, signatureHeader, secret
122
129
  ### Dashboard
123
130
 
124
131
  ```ts
125
- const dashboard = await outbound.dashboard.get(apiKey);
132
+ const dashboard = await outbound.dashboard.get();
126
133
  // dashboard.last30Days.sent, dashboard.quota, etc.
127
134
 
128
- const quota = await outbound.dashboard.quota(apiKey);
135
+ const quota = await outbound.dashboard.quota();
129
136
  // quota.dailyUsed, quota.monthlyUsed, quota.remaining
130
137
  ```
131
138
 
132
- ### Multi-Tenant Usage
133
-
134
- ```ts
135
- const outbound = new Outbound();
136
-
137
- const tenantAKey = 'mu_outbound_tenant_a_...';
138
- const tenantBKey = 'mu_outbound_tenant_b_...';
139
-
140
- // Use different API keys for different tenants
141
- await outbound.email.send(tenantAKey, { ... });
142
- await outbound.email.send(tenantBKey, { ... });
143
- ```
144
-
145
139
  ## Configuration
146
140
 
147
141
  | Option | Default | Description |
148
142
  |--------|---------|-------------|
143
+ | `apiKey` | — | Default API key (optional if provided per call) |
149
144
  | `baseUrl` | `https://outbound-api.mastersunion.org` | API base URL |
150
145
  | `timeout` | `30000` | Request timeout in ms |
151
146
  | `maxRetries` | `3` | Max retries on 429/5xx |
@@ -159,7 +154,7 @@ All errors extend `OutboundError` with `statusCode`, `message`, and `details`:
159
154
  import { Outbound, RateLimitError, NotFoundError } from 'outbound-sdk';
160
155
 
161
156
  try {
162
- await outbound.email.send(apiKey, { ... });
157
+ await outbound.email.send({ ... });
163
158
  } catch (err) {
164
159
  if (err instanceof RateLimitError) {
165
160
  console.log(`Rate limited. Retry after ${err.retryAfter}s`);
package/dist/index.d.mts CHANGED
@@ -1,15 +1,20 @@
1
1
  interface OutboundConfig {
2
+ apiKey?: string;
2
3
  baseUrl?: string;
3
4
  timeout?: number;
4
5
  maxRetries?: number;
5
6
  retryDelay?: number;
6
7
  }
7
8
  interface ResolvedConfig {
9
+ apiKey?: string;
8
10
  baseUrl: string;
9
11
  timeout: number;
10
12
  maxRetries: number;
11
13
  retryDelay: number;
12
14
  }
15
+ interface RequestOverrides {
16
+ apiKey?: string;
17
+ }
13
18
  interface SendEmailParams {
14
19
  toEmail: string;
15
20
  fromEmail: string;
@@ -296,10 +301,11 @@ interface QuotaResponse {
296
301
  declare class HttpClient {
297
302
  private config;
298
303
  constructor(config: ResolvedConfig);
299
- get<T>(apiKey: string, path: string, params?: Record<string, unknown>): Promise<T>;
300
- post<T>(apiKey: string, path: string, body?: unknown): Promise<T>;
301
- patch<T>(apiKey: string, path: string, body?: unknown): Promise<T>;
302
- delete<T>(apiKey: string, 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;
303
309
  private request;
304
310
  private buildUrl;
305
311
  private parseError;
@@ -309,39 +315,39 @@ declare class HttpClient {
309
315
  declare class EmailResource {
310
316
  private http;
311
317
  constructor(http: HttpClient);
312
- send(apiKey: string, params: SendEmailParams): Promise<SendEmailResponse>;
313
- bulk(apiKey: string, params: BulkEmailParams): Promise<BulkEmailResponse>;
314
- status(apiKey: string, 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>;
315
321
  }
316
322
 
317
323
  declare class TemplatesResource {
318
324
  private http;
319
325
  constructor(http: HttpClient);
320
- create(apiKey: string, params: CreateTemplateParams): Promise<TemplateResponse>;
321
- list(apiKey: string, params?: ListTemplatesParams): Promise<ListTemplatesResponse>;
322
- listAll(apiKey: string, params?: Omit<ListTemplatesParams, 'page'>): AsyncGenerator<Template>;
323
- get(apiKey: string, id: string): Promise<TemplateResponse>;
324
- update(apiKey: string, id: string, params: UpdateTemplateParams): Promise<TemplateResponse>;
325
- delete(apiKey: string, 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<{
326
332
  message: string;
327
333
  id: string;
328
334
  }>;
329
- duplicate(apiKey: string, id: string, params?: {
335
+ duplicate(id: string, params?: {
330
336
  name?: string;
331
- }): Promise<TemplateResponse>;
332
- preview(apiKey: string, id: string, params?: TemplatePreviewParams): Promise<TemplatePreviewResponse>;
333
- send(apiKey: string, params: TemplateSendParams): Promise<SendEmailResponse>;
334
- bulkSend(apiKey: string, params: TemplateBulkSendParams): Promise<TemplateBulkSendResponse>;
335
- stats(apiKey: string): 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>;
336
342
  }
337
343
 
338
344
  declare class SuppressionsResource {
339
345
  private http;
340
346
  constructor(http: HttpClient);
341
- list(apiKey: string, params?: ListSuppressionsParams): Promise<ListSuppressionsResponse>;
342
- listAll(apiKey: string, params?: Omit<ListSuppressionsParams, 'page'>): AsyncGenerator<Suppression>;
343
- add(apiKey: string, params: AddSuppressionParams): Promise<SuppressionResponse>;
344
- remove(apiKey: string, 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<{
345
351
  message: string;
346
352
  }>;
347
353
  }
@@ -349,10 +355,10 @@ declare class SuppressionsResource {
349
355
  declare class WebhooksResource {
350
356
  private http;
351
357
  constructor(http: HttpClient);
352
- create(apiKey: string, params: CreateWebhookParams): Promise<CreateWebhookResponse>;
353
- list(apiKey: string): Promise<ListWebhooksResponse>;
354
- update(apiKey: string, id: string, params: UpdateWebhookParams): Promise<UpdateWebhookResponse>;
355
- delete(apiKey: string, 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<{
356
362
  message: string;
357
363
  id: string;
358
364
  }>;
@@ -361,8 +367,8 @@ declare class WebhooksResource {
361
367
  declare class DashboardResource {
362
368
  private http;
363
369
  constructor(http: HttpClient);
364
- get(apiKey: string): Promise<DashboardResponse>;
365
- quota(apiKey: string): Promise<QuotaResponse>;
370
+ get(overrides?: RequestOverrides): Promise<DashboardResponse>;
371
+ quota(overrides?: RequestOverrides): Promise<QuotaResponse>;
366
372
  }
367
373
 
368
374
  declare class Outbound {
@@ -414,4 +420,4 @@ declare class NetworkError extends OutboundError {
414
420
  constructor(message?: string);
415
421
  }
416
422
 
417
- 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
@@ -1,15 +1,20 @@
1
1
  interface OutboundConfig {
2
+ apiKey?: string;
2
3
  baseUrl?: string;
3
4
  timeout?: number;
4
5
  maxRetries?: number;
5
6
  retryDelay?: number;
6
7
  }
7
8
  interface ResolvedConfig {
9
+ apiKey?: string;
8
10
  baseUrl: string;
9
11
  timeout: number;
10
12
  maxRetries: number;
11
13
  retryDelay: number;
12
14
  }
15
+ interface RequestOverrides {
16
+ apiKey?: string;
17
+ }
13
18
  interface SendEmailParams {
14
19
  toEmail: string;
15
20
  fromEmail: string;
@@ -296,10 +301,11 @@ interface QuotaResponse {
296
301
  declare class HttpClient {
297
302
  private config;
298
303
  constructor(config: ResolvedConfig);
299
- get<T>(apiKey: string, path: string, params?: Record<string, unknown>): Promise<T>;
300
- post<T>(apiKey: string, path: string, body?: unknown): Promise<T>;
301
- patch<T>(apiKey: string, path: string, body?: unknown): Promise<T>;
302
- delete<T>(apiKey: string, 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;
303
309
  private request;
304
310
  private buildUrl;
305
311
  private parseError;
@@ -309,39 +315,39 @@ declare class HttpClient {
309
315
  declare class EmailResource {
310
316
  private http;
311
317
  constructor(http: HttpClient);
312
- send(apiKey: string, params: SendEmailParams): Promise<SendEmailResponse>;
313
- bulk(apiKey: string, params: BulkEmailParams): Promise<BulkEmailResponse>;
314
- status(apiKey: string, 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>;
315
321
  }
316
322
 
317
323
  declare class TemplatesResource {
318
324
  private http;
319
325
  constructor(http: HttpClient);
320
- create(apiKey: string, params: CreateTemplateParams): Promise<TemplateResponse>;
321
- list(apiKey: string, params?: ListTemplatesParams): Promise<ListTemplatesResponse>;
322
- listAll(apiKey: string, params?: Omit<ListTemplatesParams, 'page'>): AsyncGenerator<Template>;
323
- get(apiKey: string, id: string): Promise<TemplateResponse>;
324
- update(apiKey: string, id: string, params: UpdateTemplateParams): Promise<TemplateResponse>;
325
- delete(apiKey: string, 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<{
326
332
  message: string;
327
333
  id: string;
328
334
  }>;
329
- duplicate(apiKey: string, id: string, params?: {
335
+ duplicate(id: string, params?: {
330
336
  name?: string;
331
- }): Promise<TemplateResponse>;
332
- preview(apiKey: string, id: string, params?: TemplatePreviewParams): Promise<TemplatePreviewResponse>;
333
- send(apiKey: string, params: TemplateSendParams): Promise<SendEmailResponse>;
334
- bulkSend(apiKey: string, params: TemplateBulkSendParams): Promise<TemplateBulkSendResponse>;
335
- stats(apiKey: string): 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>;
336
342
  }
337
343
 
338
344
  declare class SuppressionsResource {
339
345
  private http;
340
346
  constructor(http: HttpClient);
341
- list(apiKey: string, params?: ListSuppressionsParams): Promise<ListSuppressionsResponse>;
342
- listAll(apiKey: string, params?: Omit<ListSuppressionsParams, 'page'>): AsyncGenerator<Suppression>;
343
- add(apiKey: string, params: AddSuppressionParams): Promise<SuppressionResponse>;
344
- remove(apiKey: string, 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<{
345
351
  message: string;
346
352
  }>;
347
353
  }
@@ -349,10 +355,10 @@ declare class SuppressionsResource {
349
355
  declare class WebhooksResource {
350
356
  private http;
351
357
  constructor(http: HttpClient);
352
- create(apiKey: string, params: CreateWebhookParams): Promise<CreateWebhookResponse>;
353
- list(apiKey: string): Promise<ListWebhooksResponse>;
354
- update(apiKey: string, id: string, params: UpdateWebhookParams): Promise<UpdateWebhookResponse>;
355
- delete(apiKey: string, 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<{
356
362
  message: string;
357
363
  id: string;
358
364
  }>;
@@ -361,8 +367,8 @@ declare class WebhooksResource {
361
367
  declare class DashboardResource {
362
368
  private http;
363
369
  constructor(http: HttpClient);
364
- get(apiKey: string): Promise<DashboardResponse>;
365
- quota(apiKey: string): Promise<QuotaResponse>;
370
+ get(overrides?: RequestOverrides): Promise<DashboardResponse>;
371
+ quota(overrides?: RequestOverrides): Promise<QuotaResponse>;
366
372
  }
367
373
 
368
374
  declare class Outbound {
@@ -414,4 +420,4 @@ declare class NetworkError extends OutboundError {
414
420
  constructor(message?: string);
415
421
  }
416
422
 
417
- 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(apiKey, path, params) {
110
- return this.request(apiKey, "GET", path, { params });
109
+ async get(path, params, apiKey) {
110
+ return this.request("GET", path, { params }, apiKey);
111
111
  }
112
- async post(apiKey, path, body) {
113
- return this.request(apiKey, "POST", path, { body });
112
+ async post(path, body, apiKey) {
113
+ return this.request("POST", path, { body }, apiKey);
114
114
  }
115
- async patch(apiKey, path, body) {
116
- return this.request(apiKey, "PATCH", path, { body });
115
+ async patch(path, body, apiKey) {
116
+ return this.request("PATCH", path, { body }, apiKey);
117
117
  }
118
- async delete(apiKey, path) {
119
- return this.request(apiKey, "DELETE", path);
118
+ async delete(path, apiKey) {
119
+ return this.request("DELETE", path, void 0, apiKey);
120
120
  }
121
- async request(apiKey, method, path, options) {
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": apiKey,
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(apiKey, params) {
238
- return this.http.post(apiKey, "/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(apiKey, params) {
241
- return this.http.post(apiKey, "/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(apiKey, jobId) {
244
- return this.http.get(apiKey, `/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(apiKey, params) {
254
- return this.http.post(apiKey, "/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(apiKey, params) {
257
- return this.http.get(apiKey, "/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(apiKey, 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(apiKey, { ...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(apiKey, id) {
272
- return this.http.get(apiKey, `/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(apiKey, id, params) {
275
- return this.http.patch(apiKey, `/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(apiKey, id) {
278
- return this.http.delete(apiKey, `/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(apiKey, id, params) {
281
- return this.http.post(apiKey, `/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(apiKey, id, params) {
284
- return this.http.post(apiKey, `/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(apiKey, params) {
287
- return this.http.post(apiKey, "/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(apiKey, params) {
290
- return this.http.post(apiKey, "/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(apiKey) {
293
- return this.http.get(apiKey, "/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(apiKey, params) {
303
- return this.http.get(apiKey, "/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(apiKey, 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(apiKey, { ...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(apiKey, params) {
318
- return this.http.post(apiKey, "/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(apiKey, email) {
321
- return this.http.delete(apiKey, `/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(apiKey, params) {
331
- return this.http.post(apiKey, "/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(apiKey) {
334
- return this.http.get(apiKey, "/v1/tenants/webhooks");
343
+ async list(overrides) {
344
+ return this.http.get("/v1/tenants/webhooks", void 0, overrides?.apiKey);
335
345
  }
336
- async update(apiKey, id, params) {
337
- return this.http.patch(apiKey, `/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(apiKey, id) {
340
- return this.http.delete(apiKey, `/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(apiKey) {
350
- return this.http.get(apiKey, "/v1/tenants/dashboard");
359
+ async get(overrides) {
360
+ return this.http.get("/v1/tenants/dashboard", void 0, overrides?.apiKey);
351
361
  }
352
- async quota(apiKey) {
353
- return this.http.get(apiKey, "/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,6 +374,7 @@ var Outbound = class {
364
374
  dashboard;
365
375
  constructor(config) {
366
376
  const resolved = {
377
+ apiKey: config?.apiKey,
367
378
  baseUrl: config?.baseUrl || BASE_URL,
368
379
  timeout: config?.timeout ?? 3e4,
369
380
  maxRetries: config?.maxRetries ?? 3,
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>(apiKey: string, path: string, params?: Record<string, unknown>): Promise<T> {\n return this.request<T>(apiKey, 'GET', path, { params });\n }\n\n async post<T>(apiKey: string, path: string, body?: unknown): Promise<T> {\n return this.request<T>(apiKey, 'POST', path, { body });\n }\n\n async patch<T>(apiKey: string, path: string, body?: unknown): Promise<T> {\n return this.request<T>(apiKey, 'PATCH', path, { body });\n }\n\n async delete<T>(apiKey: string, path: string): Promise<T> {\n return this.request<T>(apiKey, 'DELETE', path);\n }\n\n private async request<T>(apiKey: string, 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': 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(apiKey: string, params: SendEmailParams): Promise<SendEmailResponse> {\n return this.http.post<SendEmailResponse>(apiKey, '/v1/email/send', params);\n }\n\n async bulk(apiKey: string, params: BulkEmailParams): Promise<BulkEmailResponse> {\n return this.http.post<BulkEmailResponse>(apiKey, '/v1/email/bulk', params);\n }\n\n async status(apiKey: string, jobId: string): Promise<JobStatusResponse> {\n return this.http.get<JobStatusResponse>(apiKey, `/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(apiKey: string, params: CreateTemplateParams): Promise<TemplateResponse> {\n return this.http.post<TemplateResponse>(apiKey, '/v1/email-templates', params);\n }\n\n async list(apiKey: string, params?: ListTemplatesParams): Promise<ListTemplatesResponse> {\n return this.http.get<ListTemplatesResponse>(apiKey, '/v1/email-templates', params as Record<string, unknown>);\n }\n\n async *listAll(apiKey: string, 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(apiKey, { ...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(apiKey: string, id: string): Promise<TemplateResponse> {\n return this.http.get<TemplateResponse>(apiKey, `/v1/email-templates/${encodeURIComponent(id)}`);\n }\n\n async update(apiKey: string, id: string, params: UpdateTemplateParams): Promise<TemplateResponse> {\n return this.http.patch<TemplateResponse>(apiKey, `/v1/email-templates/${encodeURIComponent(id)}`, params);\n }\n\n async delete(apiKey: string, id: string): Promise<{ message: string; id: string }> {\n return this.http.delete<{ message: string; id: string }>(apiKey, `/v1/email-templates/${encodeURIComponent(id)}`);\n }\n\n async duplicate(apiKey: string, id: string, params?: { name?: string }): Promise<TemplateResponse> {\n return this.http.post<TemplateResponse>(apiKey, `/v1/email-templates/${encodeURIComponent(id)}/duplicate`, params);\n }\n\n async preview(apiKey: string, id: string, params?: TemplatePreviewParams): Promise<TemplatePreviewResponse> {\n return this.http.post<TemplatePreviewResponse>(apiKey, `/v1/email-templates/${encodeURIComponent(id)}/preview`, params);\n }\n\n async send(apiKey: string, params: TemplateSendParams): Promise<SendEmailResponse> {\n return this.http.post<SendEmailResponse>(apiKey, '/v1/email-templates/send', params);\n }\n\n async bulkSend(apiKey: string, params: TemplateBulkSendParams): Promise<TemplateBulkSendResponse> {\n return this.http.post<TemplateBulkSendResponse>(apiKey, '/v1/email-templates/bulk', params);\n }\n\n async stats(apiKey: string): Promise<TemplateStatsResponse> {\n return this.http.get<TemplateStatsResponse>(apiKey, '/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(apiKey: string, params?: ListSuppressionsParams): Promise<ListSuppressionsResponse> {\n return this.http.get<ListSuppressionsResponse>(apiKey, '/v1/tenants/suppressions', params as Record<string, unknown>);\n }\n\n async *listAll(apiKey: string, 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(apiKey, { ...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(apiKey: string, params: AddSuppressionParams): Promise<SuppressionResponse> {\n return this.http.post<SuppressionResponse>(apiKey, '/v1/tenants/suppressions', params);\n }\n\n async remove(apiKey: string, email: string): Promise<{ message: string }> {\n return this.http.delete<{ message: string }>(apiKey, `/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(apiKey: string, params: CreateWebhookParams): Promise<CreateWebhookResponse> {\n return this.http.post<CreateWebhookResponse>(apiKey, '/v1/tenants/webhooks', params);\n }\n\n async list(apiKey: string): Promise<ListWebhooksResponse> {\n return this.http.get<ListWebhooksResponse>(apiKey, '/v1/tenants/webhooks');\n }\n\n async update(apiKey: string, id: string, params: UpdateWebhookParams): Promise<UpdateWebhookResponse> {\n return this.http.patch<UpdateWebhookResponse>(apiKey, `/v1/tenants/webhooks/${encodeURIComponent(id)}`, params);\n }\n\n async delete(apiKey: string, id: string): Promise<{ message: string; id: string }> {\n return this.http.delete<{ message: string; id: string }>(apiKey, `/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(apiKey: string): Promise<DashboardResponse> {\n return this.http.get<DashboardResponse>(apiKey, '/v1/tenants/dashboard');\n }\n\n async quota(apiKey: string): Promise<QuotaResponse> {\n return this.http.get<QuotaResponse>(apiKey, '/v1/tenants/quota');\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 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":[]}
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(apiKey, path, params) {
81
- return this.request(apiKey, "GET", path, { params });
80
+ async get(path, params, apiKey) {
81
+ return this.request("GET", path, { params }, apiKey);
82
82
  }
83
- async post(apiKey, path, body) {
84
- return this.request(apiKey, "POST", path, { body });
83
+ async post(path, body, apiKey) {
84
+ return this.request("POST", path, { body }, apiKey);
85
85
  }
86
- async patch(apiKey, path, body) {
87
- return this.request(apiKey, "PATCH", path, { body });
86
+ async patch(path, body, apiKey) {
87
+ return this.request("PATCH", path, { body }, apiKey);
88
88
  }
89
- async delete(apiKey, path) {
90
- return this.request(apiKey, "DELETE", path);
89
+ async delete(path, apiKey) {
90
+ return this.request("DELETE", path, void 0, apiKey);
91
91
  }
92
- async request(apiKey, method, path, options) {
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": apiKey,
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(apiKey, params) {
209
- return this.http.post(apiKey, "/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(apiKey, params) {
212
- return this.http.post(apiKey, "/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(apiKey, jobId) {
215
- return this.http.get(apiKey, `/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(apiKey, params) {
225
- return this.http.post(apiKey, "/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(apiKey, params) {
228
- return this.http.get(apiKey, "/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(apiKey, 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(apiKey, { ...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(apiKey, id) {
243
- return this.http.get(apiKey, `/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(apiKey, id, params) {
246
- return this.http.patch(apiKey, `/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(apiKey, id) {
249
- return this.http.delete(apiKey, `/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(apiKey, id, params) {
252
- return this.http.post(apiKey, `/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(apiKey, id, params) {
255
- return this.http.post(apiKey, `/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(apiKey, params) {
258
- return this.http.post(apiKey, "/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(apiKey, params) {
261
- return this.http.post(apiKey, "/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(apiKey) {
264
- return this.http.get(apiKey, "/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(apiKey, params) {
274
- return this.http.get(apiKey, "/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(apiKey, 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(apiKey, { ...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(apiKey, params) {
289
- return this.http.post(apiKey, "/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(apiKey, email) {
292
- return this.http.delete(apiKey, `/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(apiKey, params) {
302
- return this.http.post(apiKey, "/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(apiKey) {
305
- return this.http.get(apiKey, "/v1/tenants/webhooks");
314
+ async list(overrides) {
315
+ return this.http.get("/v1/tenants/webhooks", void 0, overrides?.apiKey);
306
316
  }
307
- async update(apiKey, id, params) {
308
- return this.http.patch(apiKey, `/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(apiKey, id) {
311
- return this.http.delete(apiKey, `/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(apiKey) {
321
- return this.http.get(apiKey, "/v1/tenants/dashboard");
330
+ async get(overrides) {
331
+ return this.http.get("/v1/tenants/dashboard", void 0, overrides?.apiKey);
322
332
  }
323
- async quota(apiKey) {
324
- return this.http.get(apiKey, "/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,6 +345,7 @@ var Outbound = class {
335
345
  dashboard;
336
346
  constructor(config) {
337
347
  const resolved = {
348
+ apiKey: config?.apiKey,
338
349
  baseUrl: config?.baseUrl || BASE_URL,
339
350
  timeout: config?.timeout ?? 3e4,
340
351
  maxRetries: config?.maxRetries ?? 3,
@@ -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>(apiKey: string, path: string, params?: Record<string, unknown>): Promise<T> {\n return this.request<T>(apiKey, 'GET', path, { params });\n }\n\n async post<T>(apiKey: string, path: string, body?: unknown): Promise<T> {\n return this.request<T>(apiKey, 'POST', path, { body });\n }\n\n async patch<T>(apiKey: string, path: string, body?: unknown): Promise<T> {\n return this.request<T>(apiKey, 'PATCH', path, { body });\n }\n\n async delete<T>(apiKey: string, path: string): Promise<T> {\n return this.request<T>(apiKey, 'DELETE', path);\n }\n\n private async request<T>(apiKey: string, 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': 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(apiKey: string, params: SendEmailParams): Promise<SendEmailResponse> {\n return this.http.post<SendEmailResponse>(apiKey, '/v1/email/send', params);\n }\n\n async bulk(apiKey: string, params: BulkEmailParams): Promise<BulkEmailResponse> {\n return this.http.post<BulkEmailResponse>(apiKey, '/v1/email/bulk', params);\n }\n\n async status(apiKey: string, jobId: string): Promise<JobStatusResponse> {\n return this.http.get<JobStatusResponse>(apiKey, `/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(apiKey: string, params: CreateTemplateParams): Promise<TemplateResponse> {\n return this.http.post<TemplateResponse>(apiKey, '/v1/email-templates', params);\n }\n\n async list(apiKey: string, params?: ListTemplatesParams): Promise<ListTemplatesResponse> {\n return this.http.get<ListTemplatesResponse>(apiKey, '/v1/email-templates', params as Record<string, unknown>);\n }\n\n async *listAll(apiKey: string, 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(apiKey, { ...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(apiKey: string, id: string): Promise<TemplateResponse> {\n return this.http.get<TemplateResponse>(apiKey, `/v1/email-templates/${encodeURIComponent(id)}`);\n }\n\n async update(apiKey: string, id: string, params: UpdateTemplateParams): Promise<TemplateResponse> {\n return this.http.patch<TemplateResponse>(apiKey, `/v1/email-templates/${encodeURIComponent(id)}`, params);\n }\n\n async delete(apiKey: string, id: string): Promise<{ message: string; id: string }> {\n return this.http.delete<{ message: string; id: string }>(apiKey, `/v1/email-templates/${encodeURIComponent(id)}`);\n }\n\n async duplicate(apiKey: string, id: string, params?: { name?: string }): Promise<TemplateResponse> {\n return this.http.post<TemplateResponse>(apiKey, `/v1/email-templates/${encodeURIComponent(id)}/duplicate`, params);\n }\n\n async preview(apiKey: string, id: string, params?: TemplatePreviewParams): Promise<TemplatePreviewResponse> {\n return this.http.post<TemplatePreviewResponse>(apiKey, `/v1/email-templates/${encodeURIComponent(id)}/preview`, params);\n }\n\n async send(apiKey: string, params: TemplateSendParams): Promise<SendEmailResponse> {\n return this.http.post<SendEmailResponse>(apiKey, '/v1/email-templates/send', params);\n }\n\n async bulkSend(apiKey: string, params: TemplateBulkSendParams): Promise<TemplateBulkSendResponse> {\n return this.http.post<TemplateBulkSendResponse>(apiKey, '/v1/email-templates/bulk', params);\n }\n\n async stats(apiKey: string): Promise<TemplateStatsResponse> {\n return this.http.get<TemplateStatsResponse>(apiKey, '/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(apiKey: string, params?: ListSuppressionsParams): Promise<ListSuppressionsResponse> {\n return this.http.get<ListSuppressionsResponse>(apiKey, '/v1/tenants/suppressions', params as Record<string, unknown>);\n }\n\n async *listAll(apiKey: string, 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(apiKey, { ...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(apiKey: string, params: AddSuppressionParams): Promise<SuppressionResponse> {\n return this.http.post<SuppressionResponse>(apiKey, '/v1/tenants/suppressions', params);\n }\n\n async remove(apiKey: string, email: string): Promise<{ message: string }> {\n return this.http.delete<{ message: string }>(apiKey, `/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(apiKey: string, params: CreateWebhookParams): Promise<CreateWebhookResponse> {\n return this.http.post<CreateWebhookResponse>(apiKey, '/v1/tenants/webhooks', params);\n }\n\n async list(apiKey: string): Promise<ListWebhooksResponse> {\n return this.http.get<ListWebhooksResponse>(apiKey, '/v1/tenants/webhooks');\n }\n\n async update(apiKey: string, id: string, params: UpdateWebhookParams): Promise<UpdateWebhookResponse> {\n return this.http.patch<UpdateWebhookResponse>(apiKey, `/v1/tenants/webhooks/${encodeURIComponent(id)}`, params);\n }\n\n async delete(apiKey: string, id: string): Promise<{ message: string; id: string }> {\n return this.http.delete<{ message: string; id: string }>(apiKey, `/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(apiKey: string): Promise<DashboardResponse> {\n return this.http.get<DashboardResponse>(apiKey, '/v1/tenants/dashboard');\n }\n\n async quota(apiKey: string): Promise<QuotaResponse> {\n return this.http.get<QuotaResponse>(apiKey, '/v1/tenants/quota');\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 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":[]}
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":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@masters-union/outbound-sdk",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Official Node.js SDK for the Outbound Email SaaS platform",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",