@masters-union/outbound-sdk 0.4.10 → 0.4.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -546,8 +546,16 @@ interface WebhookEventDetails {
546
546
  bounceType?: string | null;
547
547
  bounceSubType?: string | null;
548
548
  smtpStatus?: string | null;
549
+ /**
550
+ * The receiving mail server's own diagnostic, with infrastructure-provider branding
551
+ * and provider documentation links removed. Display text, not a stable key.
552
+ */
549
553
  diagnosticCode?: string | null;
550
- /** bounce / reject / rendering_failure / dropped (dropped carries the drop reason) */
554
+ /**
555
+ * bounce / reject / rendering_failure / dropped (dropped carries the drop reason).
556
+ * A stable Outbound sentence for known bounce subtypes, otherwise the remote
557
+ * diagnostic. Branch on `bounceType`/`bounceSubType`/`smtpStatus`, not on this.
558
+ */
551
559
  failedReason?: string | null;
552
560
  /** bounce / complaint — true when we auto-added the address to the suppression list */
553
561
  suppressed?: boolean;
@@ -1033,9 +1041,13 @@ interface BulkDeleteContactsResponse {
1033
1041
  listId?: string;
1034
1042
  }
1035
1043
  interface ContactListFieldsResponse {
1044
+ /** How many contacts the `filled` counts below were measured over. */
1045
+ sampleSize: number;
1046
+ /** `filled` is out of `sampleSize`, not out of the whole list. */
1036
1047
  fields: Array<{
1037
1048
  name: string;
1038
1049
  sample: string | null;
1050
+ filled: number;
1039
1051
  }>;
1040
1052
  /**
1041
1053
  * Mappable alongside `fields`, but stored on the contact rather than in its
@@ -1046,8 +1058,16 @@ interface ContactListFieldsResponse {
1046
1058
  reservedFields: Array<{
1047
1059
  name: string;
1048
1060
  sample: string | null;
1061
+ filled: number;
1049
1062
  }>;
1050
1063
  }
1064
+ interface ContactFieldRewriteResponse {
1065
+ message: string;
1066
+ listId: string;
1067
+ from: string;
1068
+ /** The new name, or null when the column was dropped. */
1069
+ to: string | null;
1070
+ }
1051
1071
  interface RecountContactListResponse {
1052
1072
  contactCount: number;
1053
1073
  previous: number;
@@ -1356,6 +1376,19 @@ declare class ContactListsResource {
1356
1376
  revalidate(listId: string, overrides?: RequestOverrides): Promise<AcceptedResponse>;
1357
1377
  /** Reconcile the denormalized contact count with an exact COUNT. */
1358
1378
  recount(listId: string, overrides?: RequestOverrides): Promise<RecountContactListResponse>;
1379
+ /**
1380
+ * Rename a column across every contact in the list. Returns 202: the rewrite runs
1381
+ * as a chunked background job, so `fields` settles a moment later.
1382
+ *
1383
+ * Rejects a name that already exists on the list — merging two columns is a data
1384
+ * decision (which value wins per contact?), not a rename.
1385
+ */
1386
+ renameField(listId: string, name: string, newName: string, overrides?: RequestOverrides): Promise<ContactFieldRewriteResponse>;
1387
+ /**
1388
+ * Drop a column from every contact in the list. Returns 202.
1389
+ * The values go with the column; this is not recoverable.
1390
+ */
1391
+ deleteField(listId: string, name: string, overrides?: RequestOverrides): Promise<ContactFieldRewriteResponse>;
1359
1392
  }
1360
1393
 
1361
1394
  declare class Outbound {
@@ -1410,4 +1443,4 @@ declare class NetworkError extends OutboundError {
1410
1443
  constructor(message?: string);
1411
1444
  }
1412
1445
 
1413
- export { type AcceptedResponse, type AddContactParams, type AddSuppressionParams, type AnyIncomingWebhookPayload, type Attachment, AuthenticationError, BadRequestError, type BulkAddSuppressionsParams, type BulkAddSuppressionsResponse, type BulkDeleteContactsParams, type BulkDeleteContactsResponse, type BulkEmailMergeRecipient, type BulkEmailParams, type BulkEmailRecipient, type BulkEmailResponse, type BulkRemoveSuppressionsParams, type BulkRemoveSuppressionsResponse, type BulkResponseRecipient, type CampaignAnalytics, type CampaignAnalyticsParams, type CampaignBounceReason, type CampaignDomainStat, type CampaignRates, type CampaignStatus, type CampaignSummary, type CampaignTimeseriesPoint, type CampaignTotals, type CancelEmailParams, type CancelEmailResponse, type CheckQuotaResponse, ConflictError, type Contact, type ContactList, type ContactListDetail, type ContactListFieldsResponse, type ContactStatus, type ContactStatusReason, type CreateContactListParams, type CreateTemplateParams, type CreateWebhookParams, type CreateWebhookResponse, type DashboardResponse, type DedicatedIpWarmup, type EmailJob, type EmailList, type EmailRecipientStatus, type EmailStatus, ForbiddenError, type GlobalQuotaResponse, type ImportContactRow, type ImportContactsParams, type ImportContactsResponse, type IncomingWebhookEvent, type IncomingWebhookEventV2, type IncomingWebhookPayload, type IncomingWebhookPayloadV2, type IpPoolStatus, type JobStatusResponse, type ListCampaignsParams, type ListCampaignsResponse, type ListContactListsParams, type ListContactListsResponse, type ListContactsParams, type ListContactsResponse, type ListSendResponse, type ListSuppressionsParams, type ListSuppressionsResponse, type ListTemplatesParams, type ListTemplatesResponse, type ListWebhooksResponse, type MessageContentResponse, type MessageStatusRecipient, type MessageStatusResponse, NetworkError, NotFoundError, Outbound, type OutboundConfig, OutboundError, type QuotaResponse, RateLimitError, type RecountContactListResponse, type RejectedEmail, type RequestOverrides, type ResolvedConfig, type SearchSuppressionsParams, type SearchSuppressionsResponse, type SendEmailParams, type SendEmailResponse, ServerError, type Suppression, type SuppressionReason, type SuppressionResponse, type Template, type TemplateBulkRecipient, type TemplateBulkSendParams, type TemplateBulkSendResponse, type TemplatePreviewParams, type TemplatePreviewResponse, type TemplateResponse, type TemplateSendParams, type TemplateStatsResponse, TimeoutError, type UpdateContactListParams, type UpdateContactParams, type UpdateTemplateParams, type UpdateWebhookParams, type UpdateWebhookResponse, type VariableMapping, type Webhook, type WebhookEvent, type WebhookEventDetails, type WebhookEventStatus, type WebhookRetryStrategy };
1446
+ export { type AcceptedResponse, type AddContactParams, type AddSuppressionParams, type AnyIncomingWebhookPayload, type Attachment, AuthenticationError, BadRequestError, type BulkAddSuppressionsParams, type BulkAddSuppressionsResponse, type BulkDeleteContactsParams, type BulkDeleteContactsResponse, type BulkEmailMergeRecipient, type BulkEmailParams, type BulkEmailRecipient, type BulkEmailResponse, type BulkRemoveSuppressionsParams, type BulkRemoveSuppressionsResponse, type BulkResponseRecipient, type CampaignAnalytics, type CampaignAnalyticsParams, type CampaignBounceReason, type CampaignDomainStat, type CampaignRates, type CampaignStatus, type CampaignSummary, type CampaignTimeseriesPoint, type CampaignTotals, type CancelEmailParams, type CancelEmailResponse, type CheckQuotaResponse, ConflictError, type Contact, type ContactFieldRewriteResponse, type ContactList, type ContactListDetail, type ContactListFieldsResponse, type ContactStatus, type ContactStatusReason, type CreateContactListParams, type CreateTemplateParams, type CreateWebhookParams, type CreateWebhookResponse, type DashboardResponse, type DedicatedIpWarmup, type EmailJob, type EmailList, type EmailRecipientStatus, type EmailStatus, ForbiddenError, type GlobalQuotaResponse, type ImportContactRow, type ImportContactsParams, type ImportContactsResponse, type IncomingWebhookEvent, type IncomingWebhookEventV2, type IncomingWebhookPayload, type IncomingWebhookPayloadV2, type IpPoolStatus, type JobStatusResponse, type ListCampaignsParams, type ListCampaignsResponse, type ListContactListsParams, type ListContactListsResponse, type ListContactsParams, type ListContactsResponse, type ListSendResponse, type ListSuppressionsParams, type ListSuppressionsResponse, type ListTemplatesParams, type ListTemplatesResponse, type ListWebhooksResponse, type MessageContentResponse, type MessageStatusRecipient, type MessageStatusResponse, NetworkError, NotFoundError, Outbound, type OutboundConfig, OutboundError, type QuotaResponse, RateLimitError, type RecountContactListResponse, type RejectedEmail, type RequestOverrides, type ResolvedConfig, type SearchSuppressionsParams, type SearchSuppressionsResponse, type SendEmailParams, type SendEmailResponse, ServerError, type Suppression, type SuppressionReason, type SuppressionResponse, type Template, type TemplateBulkRecipient, type TemplateBulkSendParams, type TemplateBulkSendResponse, type TemplatePreviewParams, type TemplatePreviewResponse, type TemplateResponse, type TemplateSendParams, type TemplateStatsResponse, TimeoutError, type UpdateContactListParams, type UpdateContactParams, type UpdateTemplateParams, type UpdateWebhookParams, type UpdateWebhookResponse, type VariableMapping, type Webhook, type WebhookEvent, type WebhookEventDetails, type WebhookEventStatus, type WebhookRetryStrategy };
package/dist/index.d.ts CHANGED
@@ -546,8 +546,16 @@ interface WebhookEventDetails {
546
546
  bounceType?: string | null;
547
547
  bounceSubType?: string | null;
548
548
  smtpStatus?: string | null;
549
+ /**
550
+ * The receiving mail server's own diagnostic, with infrastructure-provider branding
551
+ * and provider documentation links removed. Display text, not a stable key.
552
+ */
549
553
  diagnosticCode?: string | null;
550
- /** bounce / reject / rendering_failure / dropped (dropped carries the drop reason) */
554
+ /**
555
+ * bounce / reject / rendering_failure / dropped (dropped carries the drop reason).
556
+ * A stable Outbound sentence for known bounce subtypes, otherwise the remote
557
+ * diagnostic. Branch on `bounceType`/`bounceSubType`/`smtpStatus`, not on this.
558
+ */
551
559
  failedReason?: string | null;
552
560
  /** bounce / complaint — true when we auto-added the address to the suppression list */
553
561
  suppressed?: boolean;
@@ -1033,9 +1041,13 @@ interface BulkDeleteContactsResponse {
1033
1041
  listId?: string;
1034
1042
  }
1035
1043
  interface ContactListFieldsResponse {
1044
+ /** How many contacts the `filled` counts below were measured over. */
1045
+ sampleSize: number;
1046
+ /** `filled` is out of `sampleSize`, not out of the whole list. */
1036
1047
  fields: Array<{
1037
1048
  name: string;
1038
1049
  sample: string | null;
1050
+ filled: number;
1039
1051
  }>;
1040
1052
  /**
1041
1053
  * Mappable alongside `fields`, but stored on the contact rather than in its
@@ -1046,8 +1058,16 @@ interface ContactListFieldsResponse {
1046
1058
  reservedFields: Array<{
1047
1059
  name: string;
1048
1060
  sample: string | null;
1061
+ filled: number;
1049
1062
  }>;
1050
1063
  }
1064
+ interface ContactFieldRewriteResponse {
1065
+ message: string;
1066
+ listId: string;
1067
+ from: string;
1068
+ /** The new name, or null when the column was dropped. */
1069
+ to: string | null;
1070
+ }
1051
1071
  interface RecountContactListResponse {
1052
1072
  contactCount: number;
1053
1073
  previous: number;
@@ -1356,6 +1376,19 @@ declare class ContactListsResource {
1356
1376
  revalidate(listId: string, overrides?: RequestOverrides): Promise<AcceptedResponse>;
1357
1377
  /** Reconcile the denormalized contact count with an exact COUNT. */
1358
1378
  recount(listId: string, overrides?: RequestOverrides): Promise<RecountContactListResponse>;
1379
+ /**
1380
+ * Rename a column across every contact in the list. Returns 202: the rewrite runs
1381
+ * as a chunked background job, so `fields` settles a moment later.
1382
+ *
1383
+ * Rejects a name that already exists on the list — merging two columns is a data
1384
+ * decision (which value wins per contact?), not a rename.
1385
+ */
1386
+ renameField(listId: string, name: string, newName: string, overrides?: RequestOverrides): Promise<ContactFieldRewriteResponse>;
1387
+ /**
1388
+ * Drop a column from every contact in the list. Returns 202.
1389
+ * The values go with the column; this is not recoverable.
1390
+ */
1391
+ deleteField(listId: string, name: string, overrides?: RequestOverrides): Promise<ContactFieldRewriteResponse>;
1359
1392
  }
1360
1393
 
1361
1394
  declare class Outbound {
@@ -1410,4 +1443,4 @@ declare class NetworkError extends OutboundError {
1410
1443
  constructor(message?: string);
1411
1444
  }
1412
1445
 
1413
- export { type AcceptedResponse, type AddContactParams, type AddSuppressionParams, type AnyIncomingWebhookPayload, type Attachment, AuthenticationError, BadRequestError, type BulkAddSuppressionsParams, type BulkAddSuppressionsResponse, type BulkDeleteContactsParams, type BulkDeleteContactsResponse, type BulkEmailMergeRecipient, type BulkEmailParams, type BulkEmailRecipient, type BulkEmailResponse, type BulkRemoveSuppressionsParams, type BulkRemoveSuppressionsResponse, type BulkResponseRecipient, type CampaignAnalytics, type CampaignAnalyticsParams, type CampaignBounceReason, type CampaignDomainStat, type CampaignRates, type CampaignStatus, type CampaignSummary, type CampaignTimeseriesPoint, type CampaignTotals, type CancelEmailParams, type CancelEmailResponse, type CheckQuotaResponse, ConflictError, type Contact, type ContactList, type ContactListDetail, type ContactListFieldsResponse, type ContactStatus, type ContactStatusReason, type CreateContactListParams, type CreateTemplateParams, type CreateWebhookParams, type CreateWebhookResponse, type DashboardResponse, type DedicatedIpWarmup, type EmailJob, type EmailList, type EmailRecipientStatus, type EmailStatus, ForbiddenError, type GlobalQuotaResponse, type ImportContactRow, type ImportContactsParams, type ImportContactsResponse, type IncomingWebhookEvent, type IncomingWebhookEventV2, type IncomingWebhookPayload, type IncomingWebhookPayloadV2, type IpPoolStatus, type JobStatusResponse, type ListCampaignsParams, type ListCampaignsResponse, type ListContactListsParams, type ListContactListsResponse, type ListContactsParams, type ListContactsResponse, type ListSendResponse, type ListSuppressionsParams, type ListSuppressionsResponse, type ListTemplatesParams, type ListTemplatesResponse, type ListWebhooksResponse, type MessageContentResponse, type MessageStatusRecipient, type MessageStatusResponse, NetworkError, NotFoundError, Outbound, type OutboundConfig, OutboundError, type QuotaResponse, RateLimitError, type RecountContactListResponse, type RejectedEmail, type RequestOverrides, type ResolvedConfig, type SearchSuppressionsParams, type SearchSuppressionsResponse, type SendEmailParams, type SendEmailResponse, ServerError, type Suppression, type SuppressionReason, type SuppressionResponse, type Template, type TemplateBulkRecipient, type TemplateBulkSendParams, type TemplateBulkSendResponse, type TemplatePreviewParams, type TemplatePreviewResponse, type TemplateResponse, type TemplateSendParams, type TemplateStatsResponse, TimeoutError, type UpdateContactListParams, type UpdateContactParams, type UpdateTemplateParams, type UpdateWebhookParams, type UpdateWebhookResponse, type VariableMapping, type Webhook, type WebhookEvent, type WebhookEventDetails, type WebhookEventStatus, type WebhookRetryStrategy };
1446
+ export { type AcceptedResponse, type AddContactParams, type AddSuppressionParams, type AnyIncomingWebhookPayload, type Attachment, AuthenticationError, BadRequestError, type BulkAddSuppressionsParams, type BulkAddSuppressionsResponse, type BulkDeleteContactsParams, type BulkDeleteContactsResponse, type BulkEmailMergeRecipient, type BulkEmailParams, type BulkEmailRecipient, type BulkEmailResponse, type BulkRemoveSuppressionsParams, type BulkRemoveSuppressionsResponse, type BulkResponseRecipient, type CampaignAnalytics, type CampaignAnalyticsParams, type CampaignBounceReason, type CampaignDomainStat, type CampaignRates, type CampaignStatus, type CampaignSummary, type CampaignTimeseriesPoint, type CampaignTotals, type CancelEmailParams, type CancelEmailResponse, type CheckQuotaResponse, ConflictError, type Contact, type ContactFieldRewriteResponse, type ContactList, type ContactListDetail, type ContactListFieldsResponse, type ContactStatus, type ContactStatusReason, type CreateContactListParams, type CreateTemplateParams, type CreateWebhookParams, type CreateWebhookResponse, type DashboardResponse, type DedicatedIpWarmup, type EmailJob, type EmailList, type EmailRecipientStatus, type EmailStatus, ForbiddenError, type GlobalQuotaResponse, type ImportContactRow, type ImportContactsParams, type ImportContactsResponse, type IncomingWebhookEvent, type IncomingWebhookEventV2, type IncomingWebhookPayload, type IncomingWebhookPayloadV2, type IpPoolStatus, type JobStatusResponse, type ListCampaignsParams, type ListCampaignsResponse, type ListContactListsParams, type ListContactListsResponse, type ListContactsParams, type ListContactsResponse, type ListSendResponse, type ListSuppressionsParams, type ListSuppressionsResponse, type ListTemplatesParams, type ListTemplatesResponse, type ListWebhooksResponse, type MessageContentResponse, type MessageStatusRecipient, type MessageStatusResponse, NetworkError, NotFoundError, Outbound, type OutboundConfig, OutboundError, type QuotaResponse, RateLimitError, type RecountContactListResponse, type RejectedEmail, type RequestOverrides, type ResolvedConfig, type SearchSuppressionsParams, type SearchSuppressionsResponse, type SendEmailParams, type SendEmailResponse, ServerError, type Suppression, type SuppressionReason, type SuppressionResponse, type Template, type TemplateBulkRecipient, type TemplateBulkSendParams, type TemplateBulkSendResponse, type TemplatePreviewParams, type TemplatePreviewResponse, type TemplateResponse, type TemplateSendParams, type TemplateStatsResponse, TimeoutError, type UpdateContactListParams, type UpdateContactParams, type UpdateTemplateParams, type UpdateWebhookParams, type UpdateWebhookResponse, type VariableMapping, type Webhook, type WebhookEvent, type WebhookEventDetails, type WebhookEventStatus, type WebhookRetryStrategy };
package/dist/index.js CHANGED
@@ -617,6 +617,30 @@ var ContactListsResource = class {
617
617
  async recount(listId, overrides) {
618
618
  return this.http.post(`/v1/contact-lists/${encodeURIComponent(listId)}/recount`, {}, overrides?.apiKey);
619
619
  }
620
+ /**
621
+ * Rename a column across every contact in the list. Returns 202: the rewrite runs
622
+ * as a chunked background job, so `fields` settles a moment later.
623
+ *
624
+ * Rejects a name that already exists on the list — merging two columns is a data
625
+ * decision (which value wins per contact?), not a rename.
626
+ */
627
+ async renameField(listId, name, newName, overrides) {
628
+ return this.http.patch(
629
+ `/v1/contact-lists/${encodeURIComponent(listId)}/fields/${encodeURIComponent(name)}`,
630
+ { name: newName },
631
+ overrides?.apiKey
632
+ );
633
+ }
634
+ /**
635
+ * Drop a column from every contact in the list. Returns 202.
636
+ * The values go with the column; this is not recoverable.
637
+ */
638
+ async deleteField(listId, name, overrides) {
639
+ return this.http.delete(
640
+ `/v1/contact-lists/${encodeURIComponent(listId)}/fields/${encodeURIComponent(name)}`,
641
+ overrides?.apiKey
642
+ );
643
+ }
620
644
  };
621
645
 
622
646
  // src/client.ts
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/resources/quota.ts","../src/resources/campaigns.ts","../src/resources/contactLists.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 BulkResponseRecipient,\n EmailJob,\n JobStatusResponse,\n MessageStatusResponse,\n MessageStatusRecipient,\n MessageContentResponse,\n EmailRecipientStatus,\n EmailStatus,\n CancelEmailParams,\n CancelEmailResponse,\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 SuppressionReason,\n AddSuppressionParams,\n SuppressionResponse,\n EmailList,\n RejectedEmail,\n SearchSuppressionsParams,\n SearchSuppressionsResponse,\n BulkAddSuppressionsParams,\n BulkAddSuppressionsResponse,\n BulkRemoveSuppressionsParams,\n BulkRemoveSuppressionsResponse,\n WebhookEvent,\n IncomingWebhookEvent,\n IncomingWebhookPayload,\n WebhookEventStatus,\n WebhookEventDetails,\n IncomingWebhookEventV2,\n IncomingWebhookPayloadV2,\n AnyIncomingWebhookPayload,\n WebhookRetryStrategy,\n CreateWebhookParams,\n UpdateWebhookParams,\n Webhook,\n CreateWebhookResponse,\n UpdateWebhookResponse,\n ListWebhooksResponse,\n DashboardResponse,\n DedicatedIpWarmup,\n IpPoolStatus,\n QuotaResponse,\n GlobalQuotaResponse,\n CampaignStatus,\n ListCampaignsParams,\n CampaignSummary,\n ListCampaignsResponse,\n CampaignAnalyticsParams,\n CampaignTotals,\n CampaignRates,\n CampaignTimeseriesPoint,\n CampaignDomainStat,\n CampaignBounceReason,\n CampaignAnalytics,\n // Contact lists\n ContactStatus,\n ContactStatusReason,\n ContactList,\n ContactListDetail,\n Contact,\n CreateContactListParams,\n UpdateContactListParams,\n ListContactListsParams,\n ListContactListsResponse,\n BulkEmailMergeRecipient,\n ImportContactRow,\n ImportContactsParams,\n ImportContactsResponse,\n ListContactsParams,\n ListContactsResponse,\n AddContactParams,\n UpdateContactParams,\n BulkDeleteContactsParams,\n BulkDeleteContactsResponse,\n ContactListFieldsResponse,\n RecountContactListResponse,\n AcceptedResponse,\n VariableMapping,\n ListSendResponse,\n // Previously missing from the public surface even though quota.check() returns it.\n CheckQuotaResponse,\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 ListSendResponse,\n JobStatusResponse,\n MessageStatusResponse,\n MessageContentResponse,\n CancelEmailParams,\n CancelEmailResponse,\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 /**\n * Send to many recipients at once.\n *\n * Three shapes, discriminated by what you pass:\n * - `emails[]` with a full `htmlBody` each — the original behaviour, unchanged.\n * - `emails[]` + a shared `htmlBody` + per-recipient `variables` — MAIL MERGE.\n * The template crosses the wire once instead of once per recipient.\n * - `listId` (+ `mapping`) — a saved contact list, with NO recipient cap. The\n * server materializes the recipients in the background and returns a job id.\n *\n * OVERLOADED rather than returning a union, so existing calls keep resolving to\n * `BulkEmailResponse` exactly as before. A bare union would have made\n * `res.recipientCount` a compile error for every caller that upgraded.\n */\n async bulk(params: BulkEmailParams & { listId: string }, overrides?: RequestOverrides): Promise<ListSendResponse>;\n async bulk(params: BulkEmailParams, overrides?: RequestOverrides): Promise<BulkEmailResponse>;\n async bulk(params: BulkEmailParams, overrides?: RequestOverrides): Promise<BulkEmailResponse | ListSendResponse> {\n return this.http.post<BulkEmailResponse | ListSendResponse>('/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 /**\n * Look up the current status of a single message by its `messageId` — the ID\n * returned from `send()`/`bulk()` and included in webhook payloads. Useful for\n * reconciling a message whose webhook was missed.\n *\n * Accepts **only** a message ID — not a job ID or SES message ID. The message\n * must belong to the tenant the API key is scoped to; otherwise a `NotFoundError`\n * is thrown. The status reflects the latest event recorded by the SES event\n * pipeline.\n */\n async getMessageStatus(messageId: string, overrides?: RequestOverrides): Promise<MessageStatusResponse> {\n return this.http.get<MessageStatusResponse>(`/v1/email/messages/${encodeURIComponent(messageId)}/status`, undefined, overrides?.apiKey);\n }\n\n /**\n * Fetch the content that was sent for a single message by its `messageId` — the\n * subject, envelope and `htmlBody`/`textBody`, exactly as sent (the HTML includes\n * the appended unsubscribe footer). This is the same content the dashboard renders\n * in its \"Preview\", so you can reconstruct or re-display a sent email on your side.\n *\n * Accepts **only** a message ID — not a job ID or SES message ID. The message must\n * belong to the tenant the API key is scoped to; otherwise a `NotFoundError` is\n * thrown. Attachments are not inlined.\n */\n async getMessageContent(messageId: string, overrides?: RequestOverrides): Promise<MessageContentResponse> {\n return this.http.get<MessageContentResponse>(`/v1/email/messages/${encodeURIComponent(messageId)}/content`, undefined, overrides?.apiKey);\n }\n\n /**\n * Cancel all queued/processing emails for a campaign or job.\n * Provide either `campaignId` (cancels all jobs in that campaign) or `jobId` (cancels one job).\n * Already-sent emails cannot be recalled — only recipients still in `queued` or `processing` state are cancelled.\n */\n async cancel(params: CancelEmailParams, overrides?: RequestOverrides): Promise<CancelEmailResponse> {\n if (!params.campaignId && !params.jobId) {\n throw new Error('cancel() requires either campaignId or jobId');\n }\n return this.http.post<CancelEmailResponse>('/v1/email/cancel', params, 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 ListSendResponse,\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 /**\n * Send a template to many recipients.\n *\n * Pass `recipients[]` (up to 1000) for an inline send, or `listId` (+ `mapping`)\n * to send to a whole saved contact list with no recipient cap — the server\n * expands the list in the background.\n *\n * Overloaded rather than returning a union, so existing calls keep resolving to\n * `TemplateBulkSendResponse` and upgrading the SDK cannot break a build.\n */\n async bulkSend(params: TemplateBulkSendParams & { listId: string }, overrides?: RequestOverrides): Promise<ListSendResponse>;\n async bulkSend(params: TemplateBulkSendParams, overrides?: RequestOverrides): Promise<TemplateBulkSendResponse>;\n async bulkSend(params: TemplateBulkSendParams, overrides?: RequestOverrides): Promise<TemplateBulkSendResponse | ListSendResponse> {\n return this.http.post<TemplateBulkSendResponse | ListSendResponse>('/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 EmailList,\n SearchSuppressionsParams,\n SearchSuppressionsResponse,\n BulkAddSuppressionsParams,\n BulkAddSuppressionsResponse,\n BulkRemoveSuppressionsParams,\n BulkRemoveSuppressionsResponse,\n RequestOverrides,\n} from '../types';\n\n/**\n * The API takes a comma-separated list on the wire. Arrays are the ergonomic\n * form for callers, so normalize here rather than making every caller join.\n */\nfunction toEmailList(emails: EmailList): string {\n return Array.isArray(emails) ? emails.join(',') : emails;\n}\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 /**\n * Look up specific addresses on the suppression list — exact, case-insensitive,\n * up to 100 per request. Every address is validated server-side before it is\n * queried, so a malformed entry comes back in `rejected` instead of failing the\n * whole call.\n *\n * For substring matching (e.g. every address on a domain), use\n * `list({ search: 'acme.com' })` instead.\n */\n async search(params: SearchSuppressionsParams, overrides?: RequestOverrides): Promise<SearchSuppressionsResponse> {\n return this.http.get<SearchSuppressionsResponse>(\n '/v1/tenants/suppressions/search',\n { emails: toEmailList(params.emails) },\n overrides?.apiKey,\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 /**\n * Suppress up to 1000 addresses in one request. Valid addresses are added and\n * reported in `added`; ones already on the list come back in `alreadySuppressed`\n * with their existing record untouched; ones that fail validation come back in\n * `rejected` and are never written.\n */\n async bulkAdd(params: BulkAddSuppressionsParams, overrides?: RequestOverrides): Promise<BulkAddSuppressionsResponse> {\n return this.http.post<BulkAddSuppressionsResponse>(\n '/v1/tenants/suppressions/bulk/add',\n { emails: toEmailList(params.emails), reason: params.reason },\n overrides?.apiKey,\n );\n }\n\n /**\n * Unsuppress up to 1000 addresses in one request. Unlike `remove()`, an address\n * that is not on the list is not an error: it is reported in `notFound`, so one\n * bad entry cannot fail the batch.\n */\n async bulkRemove(params: BulkRemoveSuppressionsParams, overrides?: RequestOverrides): Promise<BulkRemoveSuppressionsResponse> {\n return this.http.post<BulkRemoveSuppressionsResponse>(\n '/v1/tenants/suppressions/bulk/remove',\n { emails: toEmailList(params.emails) },\n overrides?.apiKey,\n );\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 type { HttpClient } from '../http';\nimport type {\n GlobalQuotaResponse,\n CheckQuotaResponse,\n RequestOverrides,\n} from '../types';\n\n/**\n * Account-global quota: the shared SES 24h cap across ALL tenants/sources.\n *\n * Sends are NOT gated — `email.send`/`email.bulk` always submit. This is an\n * OPT-IN routing aid: call `check(count)` before a batch to ask whether the\n * shared pool has room and atomically hold it against concurrent callers. An\n * `ok:false` is a normal answer (route that batch to a fallback vendor).\n *\n * `global()` is a cheap point-in-time read; `check()` is the atomic, concurrency-\n * safe primitive that most callers want.\n */\nexport class QuotaResource {\n constructor(private http: HttpClient) {}\n\n /** Read the global quota snapshot (point-in-time). For concurrency safety use `check()`. */\n async global(overrides?: RequestOverrides): Promise<GlobalQuotaResponse> {\n return this.http.get<GlobalQuotaResponse>('/v1/quota/global', undefined, overrides?.apiKey);\n }\n\n /**\n * Opt-in quota check. Atomically holds `count` against the shared pool and\n * returns whether it fit — so two concurrent `check(300)` calls against 500 of\n * headroom can't both succeed. `ok:false` is a normal response (route to a\n * fallback vendor), not an error. The hold auto-expires after `ttlSeconds`;\n * there is no reservationId and nothing to release.\n */\n async check(count: number, overrides?: RequestOverrides): Promise<CheckQuotaResponse> {\n return this.http.post<CheckQuotaResponse>('/v1/quota/check', { count }, overrides?.apiKey);\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n ListCampaignsParams,\n ListCampaignsResponse,\n CampaignAnalyticsParams,\n CampaignAnalytics,\n RequestOverrides,\n} from '../types';\n\nexport class CampaignsResource {\n constructor(private http: HttpClient) {}\n\n /** List the tenant's campaigns with headline send stats. */\n async list(params?: ListCampaignsParams, overrides?: RequestOverrides): Promise<ListCampaignsResponse> {\n return this.http.get<ListCampaignsResponse>(\n '/v1/tenants/campaigns',\n params as Record<string, unknown> | undefined,\n overrides?.apiKey,\n );\n }\n\n /** Full analytics report for one campaign (totals, rates, timeseries, breakdowns). */\n async analytics(\n campaignId: string,\n params?: CampaignAnalyticsParams,\n overrides?: RequestOverrides,\n ): Promise<CampaignAnalytics> {\n return this.http.get<CampaignAnalytics>(\n `/v1/tenants/campaigns/${encodeURIComponent(campaignId)}/analytics`,\n params as Record<string, unknown> | undefined,\n overrides?.apiKey,\n );\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n ContactList,\n ContactListDetail,\n CreateContactListParams,\n UpdateContactListParams,\n ListContactListsParams,\n ListContactListsResponse,\n ImportContactsParams,\n ImportContactsResponse,\n ListContactsParams,\n ListContactsResponse,\n AddContactParams,\n UpdateContactParams,\n Contact,\n BulkDeleteContactsParams,\n BulkDeleteContactsResponse,\n ContactListFieldsResponse,\n RecountContactListResponse,\n AcceptedResponse,\n RequestOverrides,\n} from '../types';\n\n/**\n * Contact lists: reusable audiences you can send to without a recipient limit.\n *\n * The per-request cap on `email.bulk` / `templates.bulkSend` exists because those\n * carry their recipients in the request body. A list send carries only a `listId`,\n * and the server expands the list in the background — so there is no cap, and the\n * caller gets one job id to track however large the audience is.\n *\n * ── Address hygiene ──\n * Every imported address is sanitized (display-name unwrapping, `mailto:`,\n * zero-width characters, quotes, case) and then validated with the SAME rules the\n * send path applies. Addresses that fail are STORED with `status: 'invalid'` rather\n * than discarded, so you can list them, export them and fix them. Addresses on your\n * suppression list are stored with the matching status. Only `subscribed` contacts\n * are ever sent to, and bounces, complaints and unsubscribes flow back onto the\n * contact automatically.\n */\nexport class ContactListsResource {\n constructor(private http: HttpClient) {}\n\n async create(params: CreateContactListParams, overrides?: RequestOverrides): Promise<{ message: string; list: ContactList }> {\n return this.http.post('/v1/contact-lists', params, overrides?.apiKey);\n }\n\n async list(params?: ListContactListsParams, overrides?: RequestOverrides): Promise<ListContactListsResponse> {\n return this.http.get<ListContactListsResponse>('/v1/contact-lists', params as Record<string, unknown>, overrides?.apiKey);\n }\n\n /** Auto-paginating iterator over every contact list, mirroring templates.listAll(). */\n async *listAll(params?: Omit<ListContactListsParams, 'page'>, overrides?: RequestOverrides): AsyncGenerator<ContactList> {\n const limit = params?.limit ?? 100;\n let page = 1;\n for (;;) {\n const result = await this.list({ ...params, page, limit }, overrides);\n for (const item of result.lists) yield item;\n if (result.lists.length < limit) return;\n page += 1;\n }\n }\n\n /** A list plus its per-status breakdown (how many are sendable, invalid, bounced...). */\n async get(listId: string, overrides?: RequestOverrides): Promise<ContactListDetail> {\n return this.http.get<ContactListDetail>(`/v1/contact-lists/${encodeURIComponent(listId)}`, undefined, overrides?.apiKey);\n }\n\n async update(listId: string, params: UpdateContactListParams, overrides?: RequestOverrides): Promise<{ message: string; list: ContactList }> {\n return this.http.patch(`/v1/contact-lists/${encodeURIComponent(listId)}`, params, overrides?.apiKey);\n }\n\n /**\n * Delete a list. Returns 202: the contacts are removed by a background job in\n * chunks, so a multi-million-row list does not block on one enormous transaction.\n * Fails with a conflict while a send is still expanding this list.\n */\n async delete(listId: string, overrides?: RequestOverrides): Promise<AcceptedResponse> {\n return this.http.delete<AcceptedResponse>(`/v1/contact-lists/${encodeURIComponent(listId)}`, overrides?.apiKey);\n }\n\n /**\n * Import a chunk of contacts (max 1000 rows per call).\n *\n * Pass the same `importId` with an incrementing `chunkIndex` for every chunk of\n * one file: that pair makes a retried chunk a no-op instead of a double-insert,\n * so a network failure mid-upload is safe to retry blindly.\n *\n * `onExisting: 'update'` merges attributes into contacts already in the list. It\n * never re-subscribes someone who bounced, complained or opted out.\n */\n async importContacts(listId: string, params: ImportContactsParams, overrides?: RequestOverrides): Promise<ImportContactsResponse> {\n return this.http.post<ImportContactsResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts/import`, params, overrides?.apiKey,\n );\n }\n\n /**\n * List contacts. KEYSET paginated: pass the previous response's\n * `pagination.nextCursor` as `cursor` to advance. There is no page number,\n * because offset paging degrades badly past a few hundred pages.\n */\n async contacts(listId: string, params?: ListContactsParams, overrides?: RequestOverrides): Promise<ListContactsResponse> {\n return this.http.get<ListContactsResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts`, params as Record<string, unknown>, overrides?.apiKey,\n );\n }\n\n /** Auto-paginating iterator over every contact in a list. */\n async *contactsAll(listId: string, params?: Omit<ListContactsParams, 'cursor'>, overrides?: RequestOverrides): AsyncGenerator<Contact> {\n let cursor: string | undefined;\n for (;;) {\n const result = await this.contacts(listId, { ...params, cursor }, overrides);\n for (const contact of result.contacts) yield contact;\n if (!result.pagination.hasMore || !result.pagination.nextCursor) return;\n cursor = result.pagination.nextCursor;\n }\n }\n\n async addContact(listId: string, params: AddContactParams, overrides?: RequestOverrides): Promise<{ message: string; contact: Contact }> {\n return this.http.post(`/v1/contact-lists/${encodeURIComponent(listId)}/contacts`, params, overrides?.apiKey);\n }\n\n /** `attributes` REPLACES the stored object wholesale here; import merges instead. */\n async updateContact(listId: string, contactId: string, params: UpdateContactParams, overrides?: RequestOverrides): Promise<{ message: string; contact: Contact }> {\n return this.http.patch(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts/${encodeURIComponent(contactId)}`, params, overrides?.apiKey,\n );\n }\n\n async deleteContact(listId: string, contactId: string, overrides?: RequestOverrides): Promise<void> {\n await this.http.delete(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts/${encodeURIComponent(contactId)}`, overrides?.apiKey,\n );\n }\n\n /**\n * Delete many contacts. Pass `contactIds` or `emails` (up to 1000), or a FILTER\n * — `{ status: 'invalid' }` or `{ all: true }` — which is how you clear tens of\n * thousands of dead addresses in one small request. Filtered deletes return 202\n * and run in the background.\n */\n async bulkDeleteContacts(listId: string, params: BulkDeleteContactsParams, overrides?: RequestOverrides): Promise<BulkDeleteContactsResponse> {\n return this.http.post<BulkDeleteContactsResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts/bulk-delete`, params, overrides?.apiKey,\n );\n }\n\n /**\n * The column names available for send-time variable mapping, with a sample value\n * for each. This is what tells you which `mapping` keys a list will accept.\n */\n async fields(listId: string, options?: { refresh?: boolean }, overrides?: RequestOverrides): Promise<ContactListFieldsResponse> {\n return this.http.get<ContactListFieldsResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/fields`,\n options?.refresh ? { refresh: 'true' } : undefined,\n overrides?.apiKey,\n );\n }\n\n /**\n * Re-run validation and re-sync suppression across the whole list. Useful after a\n * bulk suppression import, or to refresh a list that has been sitting. Returns 202.\n */\n async revalidate(listId: string, overrides?: RequestOverrides): Promise<AcceptedResponse> {\n return this.http.post<AcceptedResponse>(`/v1/contact-lists/${encodeURIComponent(listId)}/revalidate`, {}, overrides?.apiKey);\n }\n\n /** Reconcile the denormalized contact count with an exact COUNT. */\n async recount(listId: string, overrides?: RequestOverrides): Promise<RecountContactListResponse> {\n return this.http.post<RecountContactListResponse>(`/v1/contact-lists/${encodeURIComponent(listId)}/recount`, {}, 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 { QuotaResource } from './resources/quota';\nimport { CampaignsResource } from './resources/campaigns';\nimport { ContactListsResource } from './resources/contactLists';\nimport type { OutboundConfig, ResolvedConfig } from './types';\n\nconst BASE_URL = 'https://outbound-api.unionstack.in';\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 readonly quota: QuotaResource;\n readonly campaigns: CampaignsResource;\n readonly contactLists: ContactListsResource;\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 this.quota = new QuotaResource(http);\n this.campaigns = new CampaignsResource(http);\n this.contactLists = new ContactListsResource(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/resources/quota.ts","../src/resources/campaigns.ts","../src/resources/contactLists.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 BulkResponseRecipient,\n EmailJob,\n JobStatusResponse,\n MessageStatusResponse,\n MessageStatusRecipient,\n MessageContentResponse,\n EmailRecipientStatus,\n EmailStatus,\n CancelEmailParams,\n CancelEmailResponse,\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 SuppressionReason,\n AddSuppressionParams,\n SuppressionResponse,\n EmailList,\n RejectedEmail,\n SearchSuppressionsParams,\n SearchSuppressionsResponse,\n BulkAddSuppressionsParams,\n BulkAddSuppressionsResponse,\n BulkRemoveSuppressionsParams,\n BulkRemoveSuppressionsResponse,\n WebhookEvent,\n IncomingWebhookEvent,\n IncomingWebhookPayload,\n WebhookEventStatus,\n WebhookEventDetails,\n IncomingWebhookEventV2,\n IncomingWebhookPayloadV2,\n AnyIncomingWebhookPayload,\n WebhookRetryStrategy,\n CreateWebhookParams,\n UpdateWebhookParams,\n Webhook,\n CreateWebhookResponse,\n UpdateWebhookResponse,\n ListWebhooksResponse,\n DashboardResponse,\n DedicatedIpWarmup,\n IpPoolStatus,\n QuotaResponse,\n GlobalQuotaResponse,\n CampaignStatus,\n ListCampaignsParams,\n CampaignSummary,\n ListCampaignsResponse,\n CampaignAnalyticsParams,\n CampaignTotals,\n CampaignRates,\n CampaignTimeseriesPoint,\n CampaignDomainStat,\n CampaignBounceReason,\n CampaignAnalytics,\n // Contact lists\n ContactStatus,\n ContactStatusReason,\n ContactList,\n ContactListDetail,\n Contact,\n CreateContactListParams,\n UpdateContactListParams,\n ListContactListsParams,\n ListContactListsResponse,\n BulkEmailMergeRecipient,\n ImportContactRow,\n ImportContactsParams,\n ImportContactsResponse,\n ListContactsParams,\n ListContactsResponse,\n AddContactParams,\n UpdateContactParams,\n BulkDeleteContactsParams,\n BulkDeleteContactsResponse,\n ContactListFieldsResponse,\n ContactFieldRewriteResponse,\n RecountContactListResponse,\n AcceptedResponse,\n VariableMapping,\n ListSendResponse,\n // Previously missing from the public surface even though quota.check() returns it.\n CheckQuotaResponse,\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 ListSendResponse,\n JobStatusResponse,\n MessageStatusResponse,\n MessageContentResponse,\n CancelEmailParams,\n CancelEmailResponse,\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 /**\n * Send to many recipients at once.\n *\n * Three shapes, discriminated by what you pass:\n * - `emails[]` with a full `htmlBody` each — the original behaviour, unchanged.\n * - `emails[]` + a shared `htmlBody` + per-recipient `variables` — MAIL MERGE.\n * The template crosses the wire once instead of once per recipient.\n * - `listId` (+ `mapping`) — a saved contact list, with NO recipient cap. The\n * server materializes the recipients in the background and returns a job id.\n *\n * OVERLOADED rather than returning a union, so existing calls keep resolving to\n * `BulkEmailResponse` exactly as before. A bare union would have made\n * `res.recipientCount` a compile error for every caller that upgraded.\n */\n async bulk(params: BulkEmailParams & { listId: string }, overrides?: RequestOverrides): Promise<ListSendResponse>;\n async bulk(params: BulkEmailParams, overrides?: RequestOverrides): Promise<BulkEmailResponse>;\n async bulk(params: BulkEmailParams, overrides?: RequestOverrides): Promise<BulkEmailResponse | ListSendResponse> {\n return this.http.post<BulkEmailResponse | ListSendResponse>('/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 /**\n * Look up the current status of a single message by its `messageId` — the ID\n * returned from `send()`/`bulk()` and included in webhook payloads. Useful for\n * reconciling a message whose webhook was missed.\n *\n * Accepts **only** a message ID — not a job ID or SES message ID. The message\n * must belong to the tenant the API key is scoped to; otherwise a `NotFoundError`\n * is thrown. The status reflects the latest event recorded by the SES event\n * pipeline.\n */\n async getMessageStatus(messageId: string, overrides?: RequestOverrides): Promise<MessageStatusResponse> {\n return this.http.get<MessageStatusResponse>(`/v1/email/messages/${encodeURIComponent(messageId)}/status`, undefined, overrides?.apiKey);\n }\n\n /**\n * Fetch the content that was sent for a single message by its `messageId` — the\n * subject, envelope and `htmlBody`/`textBody`, exactly as sent (the HTML includes\n * the appended unsubscribe footer). This is the same content the dashboard renders\n * in its \"Preview\", so you can reconstruct or re-display a sent email on your side.\n *\n * Accepts **only** a message ID — not a job ID or SES message ID. The message must\n * belong to the tenant the API key is scoped to; otherwise a `NotFoundError` is\n * thrown. Attachments are not inlined.\n */\n async getMessageContent(messageId: string, overrides?: RequestOverrides): Promise<MessageContentResponse> {\n return this.http.get<MessageContentResponse>(`/v1/email/messages/${encodeURIComponent(messageId)}/content`, undefined, overrides?.apiKey);\n }\n\n /**\n * Cancel all queued/processing emails for a campaign or job.\n * Provide either `campaignId` (cancels all jobs in that campaign) or `jobId` (cancels one job).\n * Already-sent emails cannot be recalled — only recipients still in `queued` or `processing` state are cancelled.\n */\n async cancel(params: CancelEmailParams, overrides?: RequestOverrides): Promise<CancelEmailResponse> {\n if (!params.campaignId && !params.jobId) {\n throw new Error('cancel() requires either campaignId or jobId');\n }\n return this.http.post<CancelEmailResponse>('/v1/email/cancel', params, 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 ListSendResponse,\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 /**\n * Send a template to many recipients.\n *\n * Pass `recipients[]` (up to 1000) for an inline send, or `listId` (+ `mapping`)\n * to send to a whole saved contact list with no recipient cap — the server\n * expands the list in the background.\n *\n * Overloaded rather than returning a union, so existing calls keep resolving to\n * `TemplateBulkSendResponse` and upgrading the SDK cannot break a build.\n */\n async bulkSend(params: TemplateBulkSendParams & { listId: string }, overrides?: RequestOverrides): Promise<ListSendResponse>;\n async bulkSend(params: TemplateBulkSendParams, overrides?: RequestOverrides): Promise<TemplateBulkSendResponse>;\n async bulkSend(params: TemplateBulkSendParams, overrides?: RequestOverrides): Promise<TemplateBulkSendResponse | ListSendResponse> {\n return this.http.post<TemplateBulkSendResponse | ListSendResponse>('/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 EmailList,\n SearchSuppressionsParams,\n SearchSuppressionsResponse,\n BulkAddSuppressionsParams,\n BulkAddSuppressionsResponse,\n BulkRemoveSuppressionsParams,\n BulkRemoveSuppressionsResponse,\n RequestOverrides,\n} from '../types';\n\n/**\n * The API takes a comma-separated list on the wire. Arrays are the ergonomic\n * form for callers, so normalize here rather than making every caller join.\n */\nfunction toEmailList(emails: EmailList): string {\n return Array.isArray(emails) ? emails.join(',') : emails;\n}\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 /**\n * Look up specific addresses on the suppression list — exact, case-insensitive,\n * up to 100 per request. Every address is validated server-side before it is\n * queried, so a malformed entry comes back in `rejected` instead of failing the\n * whole call.\n *\n * For substring matching (e.g. every address on a domain), use\n * `list({ search: 'acme.com' })` instead.\n */\n async search(params: SearchSuppressionsParams, overrides?: RequestOverrides): Promise<SearchSuppressionsResponse> {\n return this.http.get<SearchSuppressionsResponse>(\n '/v1/tenants/suppressions/search',\n { emails: toEmailList(params.emails) },\n overrides?.apiKey,\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 /**\n * Suppress up to 1000 addresses in one request. Valid addresses are added and\n * reported in `added`; ones already on the list come back in `alreadySuppressed`\n * with their existing record untouched; ones that fail validation come back in\n * `rejected` and are never written.\n */\n async bulkAdd(params: BulkAddSuppressionsParams, overrides?: RequestOverrides): Promise<BulkAddSuppressionsResponse> {\n return this.http.post<BulkAddSuppressionsResponse>(\n '/v1/tenants/suppressions/bulk/add',\n { emails: toEmailList(params.emails), reason: params.reason },\n overrides?.apiKey,\n );\n }\n\n /**\n * Unsuppress up to 1000 addresses in one request. Unlike `remove()`, an address\n * that is not on the list is not an error: it is reported in `notFound`, so one\n * bad entry cannot fail the batch.\n */\n async bulkRemove(params: BulkRemoveSuppressionsParams, overrides?: RequestOverrides): Promise<BulkRemoveSuppressionsResponse> {\n return this.http.post<BulkRemoveSuppressionsResponse>(\n '/v1/tenants/suppressions/bulk/remove',\n { emails: toEmailList(params.emails) },\n overrides?.apiKey,\n );\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 type { HttpClient } from '../http';\nimport type {\n GlobalQuotaResponse,\n CheckQuotaResponse,\n RequestOverrides,\n} from '../types';\n\n/**\n * Account-global quota: the shared SES 24h cap across ALL tenants/sources.\n *\n * Sends are NOT gated — `email.send`/`email.bulk` always submit. This is an\n * OPT-IN routing aid: call `check(count)` before a batch to ask whether the\n * shared pool has room and atomically hold it against concurrent callers. An\n * `ok:false` is a normal answer (route that batch to a fallback vendor).\n *\n * `global()` is a cheap point-in-time read; `check()` is the atomic, concurrency-\n * safe primitive that most callers want.\n */\nexport class QuotaResource {\n constructor(private http: HttpClient) {}\n\n /** Read the global quota snapshot (point-in-time). For concurrency safety use `check()`. */\n async global(overrides?: RequestOverrides): Promise<GlobalQuotaResponse> {\n return this.http.get<GlobalQuotaResponse>('/v1/quota/global', undefined, overrides?.apiKey);\n }\n\n /**\n * Opt-in quota check. Atomically holds `count` against the shared pool and\n * returns whether it fit — so two concurrent `check(300)` calls against 500 of\n * headroom can't both succeed. `ok:false` is a normal response (route to a\n * fallback vendor), not an error. The hold auto-expires after `ttlSeconds`;\n * there is no reservationId and nothing to release.\n */\n async check(count: number, overrides?: RequestOverrides): Promise<CheckQuotaResponse> {\n return this.http.post<CheckQuotaResponse>('/v1/quota/check', { count }, overrides?.apiKey);\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n ListCampaignsParams,\n ListCampaignsResponse,\n CampaignAnalyticsParams,\n CampaignAnalytics,\n RequestOverrides,\n} from '../types';\n\nexport class CampaignsResource {\n constructor(private http: HttpClient) {}\n\n /** List the tenant's campaigns with headline send stats. */\n async list(params?: ListCampaignsParams, overrides?: RequestOverrides): Promise<ListCampaignsResponse> {\n return this.http.get<ListCampaignsResponse>(\n '/v1/tenants/campaigns',\n params as Record<string, unknown> | undefined,\n overrides?.apiKey,\n );\n }\n\n /** Full analytics report for one campaign (totals, rates, timeseries, breakdowns). */\n async analytics(\n campaignId: string,\n params?: CampaignAnalyticsParams,\n overrides?: RequestOverrides,\n ): Promise<CampaignAnalytics> {\n return this.http.get<CampaignAnalytics>(\n `/v1/tenants/campaigns/${encodeURIComponent(campaignId)}/analytics`,\n params as Record<string, unknown> | undefined,\n overrides?.apiKey,\n );\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n ContactList,\n ContactListDetail,\n CreateContactListParams,\n UpdateContactListParams,\n ListContactListsParams,\n ListContactListsResponse,\n ImportContactsParams,\n ImportContactsResponse,\n ListContactsParams,\n ListContactsResponse,\n AddContactParams,\n UpdateContactParams,\n Contact,\n BulkDeleteContactsParams,\n BulkDeleteContactsResponse,\n ContactListFieldsResponse,\n RecountContactListResponse,\n AcceptedResponse,\n RequestOverrides,\n ContactFieldRewriteResponse,\n} from '../types';\n\n/**\n * Contact lists: reusable audiences you can send to without a recipient limit.\n *\n * The per-request cap on `email.bulk` / `templates.bulkSend` exists because those\n * carry their recipients in the request body. A list send carries only a `listId`,\n * and the server expands the list in the background — so there is no cap, and the\n * caller gets one job id to track however large the audience is.\n *\n * ── Address hygiene ──\n * Every imported address is sanitized (display-name unwrapping, `mailto:`,\n * zero-width characters, quotes, case) and then validated with the SAME rules the\n * send path applies. Addresses that fail are STORED with `status: 'invalid'` rather\n * than discarded, so you can list them, export them and fix them. Addresses on your\n * suppression list are stored with the matching status. Only `subscribed` contacts\n * are ever sent to, and bounces, complaints and unsubscribes flow back onto the\n * contact automatically.\n */\nexport class ContactListsResource {\n constructor(private http: HttpClient) {}\n\n async create(params: CreateContactListParams, overrides?: RequestOverrides): Promise<{ message: string; list: ContactList }> {\n return this.http.post('/v1/contact-lists', params, overrides?.apiKey);\n }\n\n async list(params?: ListContactListsParams, overrides?: RequestOverrides): Promise<ListContactListsResponse> {\n return this.http.get<ListContactListsResponse>('/v1/contact-lists', params as Record<string, unknown>, overrides?.apiKey);\n }\n\n /** Auto-paginating iterator over every contact list, mirroring templates.listAll(). */\n async *listAll(params?: Omit<ListContactListsParams, 'page'>, overrides?: RequestOverrides): AsyncGenerator<ContactList> {\n const limit = params?.limit ?? 100;\n let page = 1;\n for (;;) {\n const result = await this.list({ ...params, page, limit }, overrides);\n for (const item of result.lists) yield item;\n if (result.lists.length < limit) return;\n page += 1;\n }\n }\n\n /** A list plus its per-status breakdown (how many are sendable, invalid, bounced...). */\n async get(listId: string, overrides?: RequestOverrides): Promise<ContactListDetail> {\n return this.http.get<ContactListDetail>(`/v1/contact-lists/${encodeURIComponent(listId)}`, undefined, overrides?.apiKey);\n }\n\n async update(listId: string, params: UpdateContactListParams, overrides?: RequestOverrides): Promise<{ message: string; list: ContactList }> {\n return this.http.patch(`/v1/contact-lists/${encodeURIComponent(listId)}`, params, overrides?.apiKey);\n }\n\n /**\n * Delete a list. Returns 202: the contacts are removed by a background job in\n * chunks, so a multi-million-row list does not block on one enormous transaction.\n * Fails with a conflict while a send is still expanding this list.\n */\n async delete(listId: string, overrides?: RequestOverrides): Promise<AcceptedResponse> {\n return this.http.delete<AcceptedResponse>(`/v1/contact-lists/${encodeURIComponent(listId)}`, overrides?.apiKey);\n }\n\n /**\n * Import a chunk of contacts (max 1000 rows per call).\n *\n * Pass the same `importId` with an incrementing `chunkIndex` for every chunk of\n * one file: that pair makes a retried chunk a no-op instead of a double-insert,\n * so a network failure mid-upload is safe to retry blindly.\n *\n * `onExisting: 'update'` merges attributes into contacts already in the list. It\n * never re-subscribes someone who bounced, complained or opted out.\n */\n async importContacts(listId: string, params: ImportContactsParams, overrides?: RequestOverrides): Promise<ImportContactsResponse> {\n return this.http.post<ImportContactsResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts/import`, params, overrides?.apiKey,\n );\n }\n\n /**\n * List contacts. KEYSET paginated: pass the previous response's\n * `pagination.nextCursor` as `cursor` to advance. There is no page number,\n * because offset paging degrades badly past a few hundred pages.\n */\n async contacts(listId: string, params?: ListContactsParams, overrides?: RequestOverrides): Promise<ListContactsResponse> {\n return this.http.get<ListContactsResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts`, params as Record<string, unknown>, overrides?.apiKey,\n );\n }\n\n /** Auto-paginating iterator over every contact in a list. */\n async *contactsAll(listId: string, params?: Omit<ListContactsParams, 'cursor'>, overrides?: RequestOverrides): AsyncGenerator<Contact> {\n let cursor: string | undefined;\n for (;;) {\n const result = await this.contacts(listId, { ...params, cursor }, overrides);\n for (const contact of result.contacts) yield contact;\n if (!result.pagination.hasMore || !result.pagination.nextCursor) return;\n cursor = result.pagination.nextCursor;\n }\n }\n\n async addContact(listId: string, params: AddContactParams, overrides?: RequestOverrides): Promise<{ message: string; contact: Contact }> {\n return this.http.post(`/v1/contact-lists/${encodeURIComponent(listId)}/contacts`, params, overrides?.apiKey);\n }\n\n /** `attributes` REPLACES the stored object wholesale here; import merges instead. */\n async updateContact(listId: string, contactId: string, params: UpdateContactParams, overrides?: RequestOverrides): Promise<{ message: string; contact: Contact }> {\n return this.http.patch(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts/${encodeURIComponent(contactId)}`, params, overrides?.apiKey,\n );\n }\n\n async deleteContact(listId: string, contactId: string, overrides?: RequestOverrides): Promise<void> {\n await this.http.delete(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts/${encodeURIComponent(contactId)}`, overrides?.apiKey,\n );\n }\n\n /**\n * Delete many contacts. Pass `contactIds` or `emails` (up to 1000), or a FILTER\n * — `{ status: 'invalid' }` or `{ all: true }` — which is how you clear tens of\n * thousands of dead addresses in one small request. Filtered deletes return 202\n * and run in the background.\n */\n async bulkDeleteContacts(listId: string, params: BulkDeleteContactsParams, overrides?: RequestOverrides): Promise<BulkDeleteContactsResponse> {\n return this.http.post<BulkDeleteContactsResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts/bulk-delete`, params, overrides?.apiKey,\n );\n }\n\n /**\n * The column names available for send-time variable mapping, with a sample value\n * for each. This is what tells you which `mapping` keys a list will accept.\n */\n async fields(listId: string, options?: { refresh?: boolean }, overrides?: RequestOverrides): Promise<ContactListFieldsResponse> {\n return this.http.get<ContactListFieldsResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/fields`,\n options?.refresh ? { refresh: 'true' } : undefined,\n overrides?.apiKey,\n );\n }\n\n /**\n * Re-run validation and re-sync suppression across the whole list. Useful after a\n * bulk suppression import, or to refresh a list that has been sitting. Returns 202.\n */\n async revalidate(listId: string, overrides?: RequestOverrides): Promise<AcceptedResponse> {\n return this.http.post<AcceptedResponse>(`/v1/contact-lists/${encodeURIComponent(listId)}/revalidate`, {}, overrides?.apiKey);\n }\n\n /** Reconcile the denormalized contact count with an exact COUNT. */\n async recount(listId: string, overrides?: RequestOverrides): Promise<RecountContactListResponse> {\n return this.http.post<RecountContactListResponse>(`/v1/contact-lists/${encodeURIComponent(listId)}/recount`, {}, overrides?.apiKey);\n }\n\n /**\n * Rename a column across every contact in the list. Returns 202: the rewrite runs\n * as a chunked background job, so `fields` settles a moment later.\n *\n * Rejects a name that already exists on the list — merging two columns is a data\n * decision (which value wins per contact?), not a rename.\n */\n async renameField(\n listId: string,\n name: string,\n newName: string,\n overrides?: RequestOverrides,\n ): Promise<ContactFieldRewriteResponse> {\n return this.http.patch<ContactFieldRewriteResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/fields/${encodeURIComponent(name)}`,\n { name: newName },\n overrides?.apiKey,\n );\n }\n\n /**\n * Drop a column from every contact in the list. Returns 202.\n * The values go with the column; this is not recoverable.\n */\n async deleteField(\n listId: string,\n name: string,\n overrides?: RequestOverrides,\n ): Promise<ContactFieldRewriteResponse> {\n return this.http.delete<ContactFieldRewriteResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/fields/${encodeURIComponent(name)}`,\n overrides?.apiKey,\n );\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 { QuotaResource } from './resources/quota';\nimport { CampaignsResource } from './resources/campaigns';\nimport { ContactListsResource } from './resources/contactLists';\nimport type { OutboundConfig, ResolvedConfig } from './types';\n\nconst BASE_URL = 'https://outbound-api.unionstack.in';\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 readonly quota: QuotaResource;\n readonly campaigns: CampaignsResource;\n readonly contactLists: ContactListsResource;\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 this.quota = new QuotaResource(http);\n this.campaigns = new CampaignsResource(http);\n this.contactLists = new ContactListsResource(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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,gBAAN,cAA4B,MAAM;AAAA,EACvC,YACE,SACgB,YACA,SACA,WAChB;AACA,UAAM,OAAO;AAJG;AACA;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,kBAAN,cAA8B,cAAc;AAAA,EACjD,YAAY,SAAiB,SAAmB,WAAoB;AAClE,UAAM,SAAS,KAAK,SAAS,SAAS;AACtC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,sBAAN,cAAkC,cAAc;AAAA,EACrD,YAAY,SAAiB,SAAmB,WAAoB;AAClE,UAAM,SAAS,KAAK,SAAS,SAAS;AACtC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,iBAAN,cAA6B,cAAc;AAAA,EAChD,YAAY,SAAiB,SAAmB,WAAoB;AAClE,UAAM,SAAS,KAAK,SAAS,SAAS;AACtC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,gBAAN,cAA4B,cAAc;AAAA,EAC/C,YAAY,SAAiB,SAAmB,WAAoB;AAClE,UAAM,SAAS,KAAK,SAAS,SAAS;AACtC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,gBAAN,cAA4B,cAAc;AAAA,EAC/C,YAAY,SAAiB,SAAmB,WAAoB;AAClE,UAAM,SAAS,KAAK,SAAS,SAAS;AACtC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,iBAAN,cAA6B,cAAc;AAAA,EAChC;AAAA,EAEhB,YAAY,SAAiB,YAAqB,SAAmB,WAAoB;AACvF,UAAM,SAAS,KAAK,SAAS,SAAS;AACtC,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,cAAN,cAA0B,cAAc;AAAA,EAC7C,YAAY,SAAiB,aAAqB,KAAK,SAAmB,WAAoB;AAC5F,UAAM,SAAS,YAAY,SAAS,SAAS;AAC7C,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,eAAN,cAA2B,cAAc;AAAA,EAC9C,YAAY,UAAkB,qBAAqB;AACjD,UAAM,SAAS,CAAC;AAChB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,eAAN,cAA2B,cAAc;AAAA,EAC9C,YAAY,UAAkB,0BAA0B;AACtD,UAAM,SAAS,CAAC;AAChB,SAAK,OAAO;AAAA,EACd;AACF;;;ACzDO,IAAM,aAAN,MAAiB;AAAA,EACtB,YAAoB,QAAwB;AAAxB;AAAA,EAAyB;AAAA,EAE7C,MAAM,IAAO,MAAc,QAAkC,QAA6B;AACxF,WAAO,KAAK,QAAW,OAAO,MAAM,EAAE,OAAO,GAAG,MAAM;AAAA,EACxD;AAAA,EAEA,MAAM,KAAQ,MAAc,MAAgB,QAA6B;AACvE,WAAO,KAAK,QAAW,QAAQ,MAAM,EAAE,KAAK,GAAG,MAAM;AAAA,EACvD;AAAA,EAEA,MAAM,MAAS,MAAc,MAAgB,QAA6B;AACxE,WAAO,KAAK,QAAW,SAAS,MAAM,EAAE,KAAK,GAAG,MAAM;AAAA,EACxD;AAAA,EAEA,MAAM,OAAU,MAAc,QAA6B;AACzD,WAAO,KAAK,QAAW,UAAU,MAAM,QAAW,MAAM;AAAA,EAC1D;AAAA,EAEQ,cAAc,QAAyB;AAC7C,UAAM,MAAM,UAAU,KAAK,OAAO;AAClC,QAAI,CAAC,KAAK;AACR,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,QAAW,QAAgB,MAAc,SAA0B,QAA6B;AAC5G,UAAM,cAAc,KAAK,cAAc,MAAM;AAC7C,QAAI;AAEJ,aAAS,UAAU,GAAG,WAAW,KAAK,OAAO,YAAY,WAAW;AAClE,UAAI;AACF,cAAM,MAAM,KAAK,SAAS,MAAM,SAAS,MAAM;AAC/C,cAAM,aAAa,IAAI,gBAAgB;AACvC,cAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO,OAAO;AAE1E,cAAM,WAAW,MAAM,MAAM,KAAK;AAAA,UAChC;AAAA,UACA,SAAS;AAAA,YACP,aAAa;AAAA,YACb,gBAAgB;AAAA,UAClB;AAAA,UACA,MAAM,SAAS,OAAO,KAAK,UAAU,QAAQ,IAAI,IAAI;AAAA,UACrD,QAAQ,WAAW;AAAA,QACrB,CAAC;AAED,qBAAa,SAAS;AAEtB,YAAI,SAAS,IAAI;AACf,iBAAQ,MAAM,SAAS,KAAK;AAAA,QAC9B;AAEA,cAAM,QAAQ,MAAM,KAAK,WAAW,QAAQ;AAG5C,YAAI,SAAS,WAAW,OAAO,SAAS,UAAU,KAAK;AACrD,sBAAY;AAEZ,cAAI,UAAU,KAAK,OAAO,YAAY;AACpC,kBAAM,aAAa,iBAAiB,kBAAkB,MAAM,aACxD,MAAM,aAAa,MACnB,KAAK,OAAO,aAAa,KAAK,IAAI,GAAG,OAAO;AAEhD,kBAAM,KAAK,MAAM,UAAU;AAC3B;AAAA,UACF;AAAA,QACF;AAEA,cAAM;AAAA,MACR,SAAS,KAAK;AACZ,YAAI,eAAe,eAAe;AAEhC,eAAK,IAAI,eAAe,OAAO,IAAI,cAAc,QAAQ,UAAU,KAAK,OAAO,YAAY;AACzF,wBAAY;AACZ,kBAAM,aAAa,eAAe,kBAAkB,IAAI,aACpD,IAAI,aAAa,MACjB,KAAK,OAAO,aAAa,KAAK,IAAI,GAAG,OAAO;AAChD,kBAAM,KAAK,MAAM,UAAU;AAC3B;AAAA,UACF;AACA,gBAAM;AAAA,QACR;AAEA,YAAI,eAAe,gBAAgB,IAAI,SAAS,cAAc;AAC5D,sBAAY,IAAI,aAAa,2BAA2B,KAAK,OAAO,OAAO,IAAI;AAC/E,cAAI,UAAU,KAAK,OAAO,YAAY;AACpC,kBAAM,KAAK,MAAM,KAAK,OAAO,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC;AAC9D;AAAA,UACF;AACA,gBAAM;AAAA,QACR;AAEA,oBAAY,IAAI,aAAc,IAAc,OAAO;AACnD,YAAI,UAAU,KAAK,OAAO,YAAY;AACpC,gBAAM,KAAK,MAAM,KAAK,OAAO,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC;AAC9D;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,aAAa,IAAI,aAAa,8BAA8B;AAAA,EACpE;AAAA,EAEQ,SAAS,MAAc,QAA0C;AACvE,UAAM,OAAO,KAAK,OAAO,QAAQ,QAAQ,QAAQ,EAAE;AACnD,UAAM,MAAM,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE;AAEpC,QAAI,QAAQ;AACV,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,YAAI,UAAU,UAAa,UAAU,MAAM;AACzC,cAAI,aAAa,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAEA,WAAO,IAAI,SAAS;AAAA,EACtB;AAAA,EAEA,MAAc,WAAW,UAA4C;AACnE,QAAI,OAAgE,CAAC;AACrE,UAAM,YAAY,SAAS,QAAQ,IAAI,cAAc,KAAK;AAE1D,QAAI;AACF,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B,QAAQ;AAAA,IAER;AAEA,UAAM,UAAU,KAAK,SAAS,KAAK,WAAW,QAAQ,SAAS,MAAM;AACrE,UAAM,UAAU,KAAK;AAErB,YAAQ,SAAS,QAAQ;AAAA,MACvB,KAAK;AACH,eAAO,IAAI,gBAAgB,SAAS,SAAS,SAAS;AAAA,MACxD,KAAK;AACH,eAAO,IAAI,oBAAoB,SAAS,SAAS,SAAS;AAAA,MAC5D,KAAK;AACH,eAAO,IAAI,eAAe,SAAS,SAAS,SAAS;AAAA,MACvD,KAAK;AACH,eAAO,IAAI,cAAc,SAAS,SAAS,SAAS;AAAA,MACtD,KAAK;AACH,eAAO,IAAI,cAAc,SAAS,SAAS,SAAS;AAAA,MACtD,KAAK,KAAK;AACR,cAAM,aAAa,SAAS,QAAQ,IAAI,aAAa;AACrD,eAAO,IAAI;AAAA,UACT;AAAA,UACA,aAAa,SAAS,YAAY,EAAE,IAAI;AAAA,UACxC;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA;AACE,YAAI,SAAS,UAAU,KAAK;AAC1B,iBAAO,IAAI,YAAY,SAAS,SAAS,QAAQ,SAAS,SAAS;AAAA,QACrE;AACA,eAAO,IAAI,cAAc,SAAS,SAAS,QAAQ,SAAS,SAAS;AAAA,IACzE;AAAA,EACF;AAAA,EAEQ,MAAM,IAA2B;AACvC,WAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAAA,EACzD;AACF;;;AC1KO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAAoB,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAEvC,MAAM,KAAK,QAAyB,WAA0D;AAC5F,WAAO,KAAK,KAAK,KAAwB,kBAAkB,QAAQ,WAAW,MAAM;AAAA,EACtF;AAAA,EAkBA,MAAM,KAAK,QAAyB,WAA6E;AAC/G,WAAO,KAAK,KAAK,KAA2C,kBAAkB,QAAQ,WAAW,MAAM;AAAA,EACzG;AAAA,EAEA,MAAM,OAAO,OAAe,WAA0D;AACpF,WAAO,KAAK,KAAK,IAAuB,oBAAoB,mBAAmB,KAAK,CAAC,IAAI,QAAW,WAAW,MAAM;AAAA,EACvH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,iBAAiB,WAAmB,WAA8D;AACtG,WAAO,KAAK,KAAK,IAA2B,sBAAsB,mBAAmB,SAAS,CAAC,WAAW,QAAW,WAAW,MAAM;AAAA,EACxI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,kBAAkB,WAAmB,WAA+D;AACxG,WAAO,KAAK,KAAK,IAA4B,sBAAsB,mBAAmB,SAAS,CAAC,YAAY,QAAW,WAAW,MAAM;AAAA,EAC1I;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAAO,QAA2B,WAA4D;AAClG,QAAI,CAAC,OAAO,cAAc,CAAC,OAAO,OAAO;AACvC,YAAM,IAAI,MAAM,8CAA8C;AAAA,IAChE;AACA,WAAO,KAAK,KAAK,KAA0B,oBAAoB,QAAQ,WAAW,MAAM;AAAA,EAC1F;AACF;;;AClEO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAAoB,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAEvC,MAAM,OAAO,QAA8B,WAAyD;AAClG,WAAO,KAAK,KAAK,KAAuB,uBAAuB,QAAQ,WAAW,MAAM;AAAA,EAC1F;AAAA,EAEA,MAAM,KAAK,QAA8B,WAA8D;AACrG,WAAO,KAAK,KAAK,IAA2B,uBAAuB,QAAmC,WAAW,MAAM;AAAA,EACzH;AAAA,EAEA,OAAO,QAAQ,QAA4C,WAAwD;AACjH,QAAI,OAAO;AACX,UAAM,QAAQ,QAAQ,SAAS;AAE/B,WAAO,MAAM;AACX,YAAM,SAAS,MAAM,KAAK,KAAK,EAAE,GAAG,QAAQ,MAAM,MAAM,GAAG,SAAS;AACpE,iBAAW,YAAY,OAAO,WAAW;AACvC,cAAM;AAAA,MACR;AACA,UAAI,OAAO,UAAU,SAAS,MAAO;AACrC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,IAAY,WAAyD;AAC7E,WAAO,KAAK,KAAK,IAAsB,uBAAuB,mBAAmB,EAAE,CAAC,IAAI,QAAW,WAAW,MAAM;AAAA,EACtH;AAAA,EAEA,MAAM,OAAO,IAAY,QAA8B,WAAyD;AAC9G,WAAO,KAAK,KAAK,MAAwB,uBAAuB,mBAAmB,EAAE,CAAC,IAAI,QAAQ,WAAW,MAAM;AAAA,EACrH;AAAA,EAEA,MAAM,OAAO,IAAY,WAAwE;AAC/F,WAAO,KAAK,KAAK,OAAwC,uBAAuB,mBAAmB,EAAE,CAAC,IAAI,WAAW,MAAM;AAAA,EAC7H;AAAA,EAEA,MAAM,UAAU,IAAY,QAA4B,WAAyD;AAC/G,WAAO,KAAK,KAAK,KAAuB,uBAAuB,mBAAmB,EAAE,CAAC,cAAc,QAAQ,WAAW,MAAM;AAAA,EAC9H;AAAA,EAEA,MAAM,QAAQ,IAAY,QAAgC,WAAgE;AACxH,WAAO,KAAK,KAAK,KAA8B,uBAAuB,mBAAmB,EAAE,CAAC,YAAY,QAAQ,WAAW,MAAM;AAAA,EACnI;AAAA,EAEA,MAAM,KAAK,QAA4B,WAA0D;AAC/F,WAAO,KAAK,KAAK,KAAwB,4BAA4B,QAAQ,WAAW,MAAM;AAAA,EAChG;AAAA,EAcA,MAAM,SAAS,QAAgC,WAAoF;AACjI,WAAO,KAAK,KAAK,KAAkD,4BAA4B,QAAQ,WAAW,MAAM;AAAA,EAC1H;AAAA,EAEA,MAAM,MAAM,WAA8D;AACxE,WAAO,KAAK,KAAK,IAA2B,6BAA6B,QAAW,WAAW,MAAM;AAAA,EACvG;AACF;;;AClEA,SAAS,YAAY,QAA2B;AAC9C,SAAO,MAAM,QAAQ,MAAM,IAAI,OAAO,KAAK,GAAG,IAAI;AACpD;AAEO,IAAM,uBAAN,MAA2B;AAAA,EAChC,YAAoB,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAEvC,MAAM,KAAK,QAAiC,WAAiE;AAC3G,WAAO,KAAK,KAAK,IAA8B,4BAA4B,QAAmC,WAAW,MAAM;AAAA,EACjI;AAAA,EAEA,OAAO,QAAQ,QAA+C,WAA2D;AACvH,QAAI,OAAO;AACX,UAAM,QAAQ,QAAQ,SAAS;AAE/B,WAAO,MAAM;AACX,YAAM,SAAS,MAAM,KAAK,KAAK,EAAE,GAAG,QAAQ,MAAM,MAAM,GAAG,SAAS;AACpE,iBAAW,eAAe,OAAO,cAAc;AAC7C,cAAM;AAAA,MACR;AACA,UAAI,OAAO,aAAa,SAAS,MAAO;AACxC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,OAAO,QAAkC,WAAmE;AAChH,WAAO,KAAK,KAAK;AAAA,MACf;AAAA,MACA,EAAE,QAAQ,YAAY,OAAO,MAAM,EAAE;AAAA,MACrC,WAAW;AAAA,IACb;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,QAA8B,WAA4D;AAClG,WAAO,KAAK,KAAK,KAA0B,4BAA4B,QAAQ,WAAW,MAAM;AAAA,EAClG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QAAQ,QAAmC,WAAoE;AACnH,WAAO,KAAK,KAAK;AAAA,MACf;AAAA,MACA,EAAE,QAAQ,YAAY,OAAO,MAAM,GAAG,QAAQ,OAAO,OAAO;AAAA,MAC5D,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAAW,QAAsC,WAAuE;AAC5H,WAAO,KAAK,KAAK;AAAA,MACf;AAAA,MACA,EAAE,QAAQ,YAAY,OAAO,MAAM,EAAE;AAAA,MACrC,WAAW;AAAA,IACb;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,OAAe,WAA4D;AACtF,WAAO,KAAK,KAAK,OAA4B,4BAA4B,mBAAmB,KAAK,CAAC,IAAI,WAAW,MAAM;AAAA,EACzH;AACF;;;ACvFO,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAAoB,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAEvC,MAAM,OAAO,QAA6B,WAA8D;AACtG,WAAO,KAAK,KAAK,KAA4B,wBAAwB,QAAQ,WAAW,MAAM;AAAA,EAChG;AAAA,EAEA,MAAM,KAAK,WAA6D;AACtE,WAAO,KAAK,KAAK,IAA0B,wBAAwB,QAAW,WAAW,MAAM;AAAA,EACjG;AAAA,EAEA,MAAM,OAAO,IAAY,QAA6B,WAA8D;AAClH,WAAO,KAAK,KAAK,MAA6B,wBAAwB,mBAAmB,EAAE,CAAC,IAAI,QAAQ,WAAW,MAAM;AAAA,EAC3H;AAAA,EAEA,MAAM,OAAO,IAAY,WAAwE;AAC/F,WAAO,KAAK,KAAK,OAAwC,wBAAwB,mBAAmB,EAAE,CAAC,IAAI,WAAW,MAAM;AAAA,EAC9H;AACF;;;ACzBO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAAoB,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAEvC,MAAM,IAAI,WAA0D;AAClE,WAAO,KAAK,KAAK,IAAuB,yBAAyB,QAAW,WAAW,MAAM;AAAA,EAC/F;AAAA,EAEA,MAAM,MAAM,WAAsD;AAChE,WAAO,KAAK,KAAK,IAAmB,qBAAqB,QAAW,WAAW,MAAM;AAAA,EACvF;AACF;;;ACKO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAAoB,MAAkB;AAAlB;AAAA,EAAmB;AAAA;AAAA,EAGvC,MAAM,OAAO,WAA4D;AACvE,WAAO,KAAK,KAAK,IAAyB,oBAAoB,QAAW,WAAW,MAAM;AAAA,EAC5F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,MAAM,OAAe,WAA2D;AACpF,WAAO,KAAK,KAAK,KAAyB,mBAAmB,EAAE,MAAM,GAAG,WAAW,MAAM;AAAA,EAC3F;AACF;;;AC3BO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAAoB,MAAkB;AAAlB;AAAA,EAAmB;AAAA;AAAA,EAGvC,MAAM,KAAK,QAA8B,WAA8D;AACrG,WAAO,KAAK,KAAK;AAAA,MACf;AAAA,MACA;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,UACJ,YACA,QACA,WAC4B;AAC5B,WAAO,KAAK,KAAK;AAAA,MACf,yBAAyB,mBAAmB,UAAU,CAAC;AAAA,MACvD;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AACF;;;ACQO,IAAM,uBAAN,MAA2B;AAAA,EAChC,YAAoB,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAEvC,MAAM,OAAO,QAAiC,WAA+E;AAC3H,WAAO,KAAK,KAAK,KAAK,qBAAqB,QAAQ,WAAW,MAAM;AAAA,EACtE;AAAA,EAEA,MAAM,KAAK,QAAiC,WAAiE;AAC3G,WAAO,KAAK,KAAK,IAA8B,qBAAqB,QAAmC,WAAW,MAAM;AAAA,EAC1H;AAAA;AAAA,EAGA,OAAO,QAAQ,QAA+C,WAA2D;AACvH,UAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAI,OAAO;AACX,eAAS;AACP,YAAM,SAAS,MAAM,KAAK,KAAK,EAAE,GAAG,QAAQ,MAAM,MAAM,GAAG,SAAS;AACpE,iBAAW,QAAQ,OAAO,MAAO,OAAM;AACvC,UAAI,OAAO,MAAM,SAAS,MAAO;AACjC,cAAQ;AAAA,IACV;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,IAAI,QAAgB,WAA0D;AAClF,WAAO,KAAK,KAAK,IAAuB,qBAAqB,mBAAmB,MAAM,CAAC,IAAI,QAAW,WAAW,MAAM;AAAA,EACzH;AAAA,EAEA,MAAM,OAAO,QAAgB,QAAiC,WAA+E;AAC3I,WAAO,KAAK,KAAK,MAAM,qBAAqB,mBAAmB,MAAM,CAAC,IAAI,QAAQ,WAAW,MAAM;AAAA,EACrG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAAO,QAAgB,WAAyD;AACpF,WAAO,KAAK,KAAK,OAAyB,qBAAqB,mBAAmB,MAAM,CAAC,IAAI,WAAW,MAAM;AAAA,EAChH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,eAAe,QAAgB,QAA8B,WAA+D;AAChI,WAAO,KAAK,KAAK;AAAA,MACf,qBAAqB,mBAAmB,MAAM,CAAC;AAAA,MAAoB;AAAA,MAAQ,WAAW;AAAA,IACxF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SAAS,QAAgB,QAA6B,WAA6D;AACvH,WAAO,KAAK,KAAK;AAAA,MACf,qBAAqB,mBAAmB,MAAM,CAAC;AAAA,MAAa;AAAA,MAAmC,WAAW;AAAA,IAC5G;AAAA,EACF;AAAA;AAAA,EAGA,OAAO,YAAY,QAAgB,QAA6C,WAAuD;AACrI,QAAI;AACJ,eAAS;AACP,YAAM,SAAS,MAAM,KAAK,SAAS,QAAQ,EAAE,GAAG,QAAQ,OAAO,GAAG,SAAS;AAC3E,iBAAW,WAAW,OAAO,SAAU,OAAM;AAC7C,UAAI,CAAC,OAAO,WAAW,WAAW,CAAC,OAAO,WAAW,WAAY;AACjE,eAAS,OAAO,WAAW;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,QAAgB,QAA0B,WAA8E;AACvI,WAAO,KAAK,KAAK,KAAK,qBAAqB,mBAAmB,MAAM,CAAC,aAAa,QAAQ,WAAW,MAAM;AAAA,EAC7G;AAAA;AAAA,EAGA,MAAM,cAAc,QAAgB,WAAmB,QAA6B,WAA8E;AAChK,WAAO,KAAK,KAAK;AAAA,MACf,qBAAqB,mBAAmB,MAAM,CAAC,aAAa,mBAAmB,SAAS,CAAC;AAAA,MAAI;AAAA,MAAQ,WAAW;AAAA,IAClH;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,QAAgB,WAAmB,WAA6C;AAClG,UAAM,KAAK,KAAK;AAAA,MACd,qBAAqB,mBAAmB,MAAM,CAAC,aAAa,mBAAmB,SAAS,CAAC;AAAA,MAAI,WAAW;AAAA,IAC1G;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,mBAAmB,QAAgB,QAAkC,WAAmE;AAC5I,WAAO,KAAK,KAAK;AAAA,MACf,qBAAqB,mBAAmB,MAAM,CAAC;AAAA,MAAyB;AAAA,MAAQ,WAAW;AAAA,IAC7F;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAO,QAAgB,SAAiC,WAAkE;AAC9H,WAAO,KAAK,KAAK;AAAA,MACf,qBAAqB,mBAAmB,MAAM,CAAC;AAAA,MAC/C,SAAS,UAAU,EAAE,SAAS,OAAO,IAAI;AAAA,MACzC,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAAW,QAAgB,WAAyD;AACxF,WAAO,KAAK,KAAK,KAAuB,qBAAqB,mBAAmB,MAAM,CAAC,eAAe,CAAC,GAAG,WAAW,MAAM;AAAA,EAC7H;AAAA;AAAA,EAGA,MAAM,QAAQ,QAAgB,WAAmE;AAC/F,WAAO,KAAK,KAAK,KAAiC,qBAAqB,mBAAmB,MAAM,CAAC,YAAY,CAAC,GAAG,WAAW,MAAM;AAAA,EACpI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,YACJ,QACA,MACA,SACA,WACsC;AACtC,WAAO,KAAK,KAAK;AAAA,MACf,qBAAqB,mBAAmB,MAAM,CAAC,WAAW,mBAAmB,IAAI,CAAC;AAAA,MAClF,EAAE,MAAM,QAAQ;AAAA,MAChB,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YACJ,QACA,MACA,WACsC;AACtC,WAAO,KAAK,KAAK;AAAA,MACf,qBAAqB,mBAAmB,MAAM,CAAC,WAAW,mBAAmB,IAAI,CAAC;AAAA,MAClF,WAAW;AAAA,IACb;AAAA,EACF;AACF;;;ACrMA,IAAM,WAAW;AAEV,IAAM,WAAN,MAAe;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAAyB;AACnC,UAAM,WAA2B;AAAA,MAC/B,QAAQ,QAAQ;AAAA,MAChB,SAAS,QAAQ,WAAW;AAAA,MAC5B,SAAS,QAAQ,WAAW;AAAA,MAC5B,YAAY,QAAQ,cAAc;AAAA,MAClC,YAAY,QAAQ,cAAc;AAAA,IACpC;AAEA,UAAM,OAAO,IAAI,WAAW,QAAQ;AAEpC,SAAK,QAAQ,IAAI,cAAc,IAAI;AACnC,SAAK,YAAY,IAAI,kBAAkB,IAAI;AAC3C,SAAK,eAAe,IAAI,qBAAqB,IAAI;AACjD,SAAK,WAAW,IAAI,iBAAiB,IAAI;AACzC,SAAK,YAAY,IAAI,kBAAkB,IAAI;AAC3C,SAAK,QAAQ,IAAI,cAAc,IAAI;AACnC,SAAK,YAAY,IAAI,kBAAkB,IAAI;AAC3C,SAAK,eAAe,IAAI,qBAAqB,IAAI;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,uBACL,SACA,WACA,QACS;AAGT,UAAM,SAAS,QAAQ,QAAQ;AAC/B,UAAM,WAAW,OAAO,WAAW,UAAU,MAAM,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;AACjF,QAAI;AACF,aAAO,OAAO,gBAAgB,OAAO,KAAK,SAAS,GAAG,OAAO,KAAK,QAAQ,CAAC;AAAA,IAC7E,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
package/dist/index.mjs CHANGED
@@ -588,6 +588,30 @@ var ContactListsResource = class {
588
588
  async recount(listId, overrides) {
589
589
  return this.http.post(`/v1/contact-lists/${encodeURIComponent(listId)}/recount`, {}, overrides?.apiKey);
590
590
  }
591
+ /**
592
+ * Rename a column across every contact in the list. Returns 202: the rewrite runs
593
+ * as a chunked background job, so `fields` settles a moment later.
594
+ *
595
+ * Rejects a name that already exists on the list — merging two columns is a data
596
+ * decision (which value wins per contact?), not a rename.
597
+ */
598
+ async renameField(listId, name, newName, overrides) {
599
+ return this.http.patch(
600
+ `/v1/contact-lists/${encodeURIComponent(listId)}/fields/${encodeURIComponent(name)}`,
601
+ { name: newName },
602
+ overrides?.apiKey
603
+ );
604
+ }
605
+ /**
606
+ * Drop a column from every contact in the list. Returns 202.
607
+ * The values go with the column; this is not recoverable.
608
+ */
609
+ async deleteField(listId, name, overrides) {
610
+ return this.http.delete(
611
+ `/v1/contact-lists/${encodeURIComponent(listId)}/fields/${encodeURIComponent(name)}`,
612
+ overrides?.apiKey
613
+ );
614
+ }
591
615
  };
592
616
 
593
617
  // src/client.ts
@@ -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/resources/quota.ts","../src/resources/campaigns.ts","../src/resources/contactLists.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 ListSendResponse,\n JobStatusResponse,\n MessageStatusResponse,\n MessageContentResponse,\n CancelEmailParams,\n CancelEmailResponse,\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 /**\n * Send to many recipients at once.\n *\n * Three shapes, discriminated by what you pass:\n * - `emails[]` with a full `htmlBody` each — the original behaviour, unchanged.\n * - `emails[]` + a shared `htmlBody` + per-recipient `variables` — MAIL MERGE.\n * The template crosses the wire once instead of once per recipient.\n * - `listId` (+ `mapping`) — a saved contact list, with NO recipient cap. The\n * server materializes the recipients in the background and returns a job id.\n *\n * OVERLOADED rather than returning a union, so existing calls keep resolving to\n * `BulkEmailResponse` exactly as before. A bare union would have made\n * `res.recipientCount` a compile error for every caller that upgraded.\n */\n async bulk(params: BulkEmailParams & { listId: string }, overrides?: RequestOverrides): Promise<ListSendResponse>;\n async bulk(params: BulkEmailParams, overrides?: RequestOverrides): Promise<BulkEmailResponse>;\n async bulk(params: BulkEmailParams, overrides?: RequestOverrides): Promise<BulkEmailResponse | ListSendResponse> {\n return this.http.post<BulkEmailResponse | ListSendResponse>('/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 /**\n * Look up the current status of a single message by its `messageId` — the ID\n * returned from `send()`/`bulk()` and included in webhook payloads. Useful for\n * reconciling a message whose webhook was missed.\n *\n * Accepts **only** a message ID — not a job ID or SES message ID. The message\n * must belong to the tenant the API key is scoped to; otherwise a `NotFoundError`\n * is thrown. The status reflects the latest event recorded by the SES event\n * pipeline.\n */\n async getMessageStatus(messageId: string, overrides?: RequestOverrides): Promise<MessageStatusResponse> {\n return this.http.get<MessageStatusResponse>(`/v1/email/messages/${encodeURIComponent(messageId)}/status`, undefined, overrides?.apiKey);\n }\n\n /**\n * Fetch the content that was sent for a single message by its `messageId` — the\n * subject, envelope and `htmlBody`/`textBody`, exactly as sent (the HTML includes\n * the appended unsubscribe footer). This is the same content the dashboard renders\n * in its \"Preview\", so you can reconstruct or re-display a sent email on your side.\n *\n * Accepts **only** a message ID — not a job ID or SES message ID. The message must\n * belong to the tenant the API key is scoped to; otherwise a `NotFoundError` is\n * thrown. Attachments are not inlined.\n */\n async getMessageContent(messageId: string, overrides?: RequestOverrides): Promise<MessageContentResponse> {\n return this.http.get<MessageContentResponse>(`/v1/email/messages/${encodeURIComponent(messageId)}/content`, undefined, overrides?.apiKey);\n }\n\n /**\n * Cancel all queued/processing emails for a campaign or job.\n * Provide either `campaignId` (cancels all jobs in that campaign) or `jobId` (cancels one job).\n * Already-sent emails cannot be recalled — only recipients still in `queued` or `processing` state are cancelled.\n */\n async cancel(params: CancelEmailParams, overrides?: RequestOverrides): Promise<CancelEmailResponse> {\n if (!params.campaignId && !params.jobId) {\n throw new Error('cancel() requires either campaignId or jobId');\n }\n return this.http.post<CancelEmailResponse>('/v1/email/cancel', params, 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 ListSendResponse,\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 /**\n * Send a template to many recipients.\n *\n * Pass `recipients[]` (up to 1000) for an inline send, or `listId` (+ `mapping`)\n * to send to a whole saved contact list with no recipient cap — the server\n * expands the list in the background.\n *\n * Overloaded rather than returning a union, so existing calls keep resolving to\n * `TemplateBulkSendResponse` and upgrading the SDK cannot break a build.\n */\n async bulkSend(params: TemplateBulkSendParams & { listId: string }, overrides?: RequestOverrides): Promise<ListSendResponse>;\n async bulkSend(params: TemplateBulkSendParams, overrides?: RequestOverrides): Promise<TemplateBulkSendResponse>;\n async bulkSend(params: TemplateBulkSendParams, overrides?: RequestOverrides): Promise<TemplateBulkSendResponse | ListSendResponse> {\n return this.http.post<TemplateBulkSendResponse | ListSendResponse>('/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 EmailList,\n SearchSuppressionsParams,\n SearchSuppressionsResponse,\n BulkAddSuppressionsParams,\n BulkAddSuppressionsResponse,\n BulkRemoveSuppressionsParams,\n BulkRemoveSuppressionsResponse,\n RequestOverrides,\n} from '../types';\n\n/**\n * The API takes a comma-separated list on the wire. Arrays are the ergonomic\n * form for callers, so normalize here rather than making every caller join.\n */\nfunction toEmailList(emails: EmailList): string {\n return Array.isArray(emails) ? emails.join(',') : emails;\n}\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 /**\n * Look up specific addresses on the suppression list — exact, case-insensitive,\n * up to 100 per request. Every address is validated server-side before it is\n * queried, so a malformed entry comes back in `rejected` instead of failing the\n * whole call.\n *\n * For substring matching (e.g. every address on a domain), use\n * `list({ search: 'acme.com' })` instead.\n */\n async search(params: SearchSuppressionsParams, overrides?: RequestOverrides): Promise<SearchSuppressionsResponse> {\n return this.http.get<SearchSuppressionsResponse>(\n '/v1/tenants/suppressions/search',\n { emails: toEmailList(params.emails) },\n overrides?.apiKey,\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 /**\n * Suppress up to 1000 addresses in one request. Valid addresses are added and\n * reported in `added`; ones already on the list come back in `alreadySuppressed`\n * with their existing record untouched; ones that fail validation come back in\n * `rejected` and are never written.\n */\n async bulkAdd(params: BulkAddSuppressionsParams, overrides?: RequestOverrides): Promise<BulkAddSuppressionsResponse> {\n return this.http.post<BulkAddSuppressionsResponse>(\n '/v1/tenants/suppressions/bulk/add',\n { emails: toEmailList(params.emails), reason: params.reason },\n overrides?.apiKey,\n );\n }\n\n /**\n * Unsuppress up to 1000 addresses in one request. Unlike `remove()`, an address\n * that is not on the list is not an error: it is reported in `notFound`, so one\n * bad entry cannot fail the batch.\n */\n async bulkRemove(params: BulkRemoveSuppressionsParams, overrides?: RequestOverrides): Promise<BulkRemoveSuppressionsResponse> {\n return this.http.post<BulkRemoveSuppressionsResponse>(\n '/v1/tenants/suppressions/bulk/remove',\n { emails: toEmailList(params.emails) },\n overrides?.apiKey,\n );\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 type { HttpClient } from '../http';\nimport type {\n GlobalQuotaResponse,\n CheckQuotaResponse,\n RequestOverrides,\n} from '../types';\n\n/**\n * Account-global quota: the shared SES 24h cap across ALL tenants/sources.\n *\n * Sends are NOT gated — `email.send`/`email.bulk` always submit. This is an\n * OPT-IN routing aid: call `check(count)` before a batch to ask whether the\n * shared pool has room and atomically hold it against concurrent callers. An\n * `ok:false` is a normal answer (route that batch to a fallback vendor).\n *\n * `global()` is a cheap point-in-time read; `check()` is the atomic, concurrency-\n * safe primitive that most callers want.\n */\nexport class QuotaResource {\n constructor(private http: HttpClient) {}\n\n /** Read the global quota snapshot (point-in-time). For concurrency safety use `check()`. */\n async global(overrides?: RequestOverrides): Promise<GlobalQuotaResponse> {\n return this.http.get<GlobalQuotaResponse>('/v1/quota/global', undefined, overrides?.apiKey);\n }\n\n /**\n * Opt-in quota check. Atomically holds `count` against the shared pool and\n * returns whether it fit — so two concurrent `check(300)` calls against 500 of\n * headroom can't both succeed. `ok:false` is a normal response (route to a\n * fallback vendor), not an error. The hold auto-expires after `ttlSeconds`;\n * there is no reservationId and nothing to release.\n */\n async check(count: number, overrides?: RequestOverrides): Promise<CheckQuotaResponse> {\n return this.http.post<CheckQuotaResponse>('/v1/quota/check', { count }, overrides?.apiKey);\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n ListCampaignsParams,\n ListCampaignsResponse,\n CampaignAnalyticsParams,\n CampaignAnalytics,\n RequestOverrides,\n} from '../types';\n\nexport class CampaignsResource {\n constructor(private http: HttpClient) {}\n\n /** List the tenant's campaigns with headline send stats. */\n async list(params?: ListCampaignsParams, overrides?: RequestOverrides): Promise<ListCampaignsResponse> {\n return this.http.get<ListCampaignsResponse>(\n '/v1/tenants/campaigns',\n params as Record<string, unknown> | undefined,\n overrides?.apiKey,\n );\n }\n\n /** Full analytics report for one campaign (totals, rates, timeseries, breakdowns). */\n async analytics(\n campaignId: string,\n params?: CampaignAnalyticsParams,\n overrides?: RequestOverrides,\n ): Promise<CampaignAnalytics> {\n return this.http.get<CampaignAnalytics>(\n `/v1/tenants/campaigns/${encodeURIComponent(campaignId)}/analytics`,\n params as Record<string, unknown> | undefined,\n overrides?.apiKey,\n );\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n ContactList,\n ContactListDetail,\n CreateContactListParams,\n UpdateContactListParams,\n ListContactListsParams,\n ListContactListsResponse,\n ImportContactsParams,\n ImportContactsResponse,\n ListContactsParams,\n ListContactsResponse,\n AddContactParams,\n UpdateContactParams,\n Contact,\n BulkDeleteContactsParams,\n BulkDeleteContactsResponse,\n ContactListFieldsResponse,\n RecountContactListResponse,\n AcceptedResponse,\n RequestOverrides,\n} from '../types';\n\n/**\n * Contact lists: reusable audiences you can send to without a recipient limit.\n *\n * The per-request cap on `email.bulk` / `templates.bulkSend` exists because those\n * carry their recipients in the request body. A list send carries only a `listId`,\n * and the server expands the list in the background — so there is no cap, and the\n * caller gets one job id to track however large the audience is.\n *\n * ── Address hygiene ──\n * Every imported address is sanitized (display-name unwrapping, `mailto:`,\n * zero-width characters, quotes, case) and then validated with the SAME rules the\n * send path applies. Addresses that fail are STORED with `status: 'invalid'` rather\n * than discarded, so you can list them, export them and fix them. Addresses on your\n * suppression list are stored with the matching status. Only `subscribed` contacts\n * are ever sent to, and bounces, complaints and unsubscribes flow back onto the\n * contact automatically.\n */\nexport class ContactListsResource {\n constructor(private http: HttpClient) {}\n\n async create(params: CreateContactListParams, overrides?: RequestOverrides): Promise<{ message: string; list: ContactList }> {\n return this.http.post('/v1/contact-lists', params, overrides?.apiKey);\n }\n\n async list(params?: ListContactListsParams, overrides?: RequestOverrides): Promise<ListContactListsResponse> {\n return this.http.get<ListContactListsResponse>('/v1/contact-lists', params as Record<string, unknown>, overrides?.apiKey);\n }\n\n /** Auto-paginating iterator over every contact list, mirroring templates.listAll(). */\n async *listAll(params?: Omit<ListContactListsParams, 'page'>, overrides?: RequestOverrides): AsyncGenerator<ContactList> {\n const limit = params?.limit ?? 100;\n let page = 1;\n for (;;) {\n const result = await this.list({ ...params, page, limit }, overrides);\n for (const item of result.lists) yield item;\n if (result.lists.length < limit) return;\n page += 1;\n }\n }\n\n /** A list plus its per-status breakdown (how many are sendable, invalid, bounced...). */\n async get(listId: string, overrides?: RequestOverrides): Promise<ContactListDetail> {\n return this.http.get<ContactListDetail>(`/v1/contact-lists/${encodeURIComponent(listId)}`, undefined, overrides?.apiKey);\n }\n\n async update(listId: string, params: UpdateContactListParams, overrides?: RequestOverrides): Promise<{ message: string; list: ContactList }> {\n return this.http.patch(`/v1/contact-lists/${encodeURIComponent(listId)}`, params, overrides?.apiKey);\n }\n\n /**\n * Delete a list. Returns 202: the contacts are removed by a background job in\n * chunks, so a multi-million-row list does not block on one enormous transaction.\n * Fails with a conflict while a send is still expanding this list.\n */\n async delete(listId: string, overrides?: RequestOverrides): Promise<AcceptedResponse> {\n return this.http.delete<AcceptedResponse>(`/v1/contact-lists/${encodeURIComponent(listId)}`, overrides?.apiKey);\n }\n\n /**\n * Import a chunk of contacts (max 1000 rows per call).\n *\n * Pass the same `importId` with an incrementing `chunkIndex` for every chunk of\n * one file: that pair makes a retried chunk a no-op instead of a double-insert,\n * so a network failure mid-upload is safe to retry blindly.\n *\n * `onExisting: 'update'` merges attributes into contacts already in the list. It\n * never re-subscribes someone who bounced, complained or opted out.\n */\n async importContacts(listId: string, params: ImportContactsParams, overrides?: RequestOverrides): Promise<ImportContactsResponse> {\n return this.http.post<ImportContactsResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts/import`, params, overrides?.apiKey,\n );\n }\n\n /**\n * List contacts. KEYSET paginated: pass the previous response's\n * `pagination.nextCursor` as `cursor` to advance. There is no page number,\n * because offset paging degrades badly past a few hundred pages.\n */\n async contacts(listId: string, params?: ListContactsParams, overrides?: RequestOverrides): Promise<ListContactsResponse> {\n return this.http.get<ListContactsResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts`, params as Record<string, unknown>, overrides?.apiKey,\n );\n }\n\n /** Auto-paginating iterator over every contact in a list. */\n async *contactsAll(listId: string, params?: Omit<ListContactsParams, 'cursor'>, overrides?: RequestOverrides): AsyncGenerator<Contact> {\n let cursor: string | undefined;\n for (;;) {\n const result = await this.contacts(listId, { ...params, cursor }, overrides);\n for (const contact of result.contacts) yield contact;\n if (!result.pagination.hasMore || !result.pagination.nextCursor) return;\n cursor = result.pagination.nextCursor;\n }\n }\n\n async addContact(listId: string, params: AddContactParams, overrides?: RequestOverrides): Promise<{ message: string; contact: Contact }> {\n return this.http.post(`/v1/contact-lists/${encodeURIComponent(listId)}/contacts`, params, overrides?.apiKey);\n }\n\n /** `attributes` REPLACES the stored object wholesale here; import merges instead. */\n async updateContact(listId: string, contactId: string, params: UpdateContactParams, overrides?: RequestOverrides): Promise<{ message: string; contact: Contact }> {\n return this.http.patch(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts/${encodeURIComponent(contactId)}`, params, overrides?.apiKey,\n );\n }\n\n async deleteContact(listId: string, contactId: string, overrides?: RequestOverrides): Promise<void> {\n await this.http.delete(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts/${encodeURIComponent(contactId)}`, overrides?.apiKey,\n );\n }\n\n /**\n * Delete many contacts. Pass `contactIds` or `emails` (up to 1000), or a FILTER\n * — `{ status: 'invalid' }` or `{ all: true }` — which is how you clear tens of\n * thousands of dead addresses in one small request. Filtered deletes return 202\n * and run in the background.\n */\n async bulkDeleteContacts(listId: string, params: BulkDeleteContactsParams, overrides?: RequestOverrides): Promise<BulkDeleteContactsResponse> {\n return this.http.post<BulkDeleteContactsResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts/bulk-delete`, params, overrides?.apiKey,\n );\n }\n\n /**\n * The column names available for send-time variable mapping, with a sample value\n * for each. This is what tells you which `mapping` keys a list will accept.\n */\n async fields(listId: string, options?: { refresh?: boolean }, overrides?: RequestOverrides): Promise<ContactListFieldsResponse> {\n return this.http.get<ContactListFieldsResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/fields`,\n options?.refresh ? { refresh: 'true' } : undefined,\n overrides?.apiKey,\n );\n }\n\n /**\n * Re-run validation and re-sync suppression across the whole list. Useful after a\n * bulk suppression import, or to refresh a list that has been sitting. Returns 202.\n */\n async revalidate(listId: string, overrides?: RequestOverrides): Promise<AcceptedResponse> {\n return this.http.post<AcceptedResponse>(`/v1/contact-lists/${encodeURIComponent(listId)}/revalidate`, {}, overrides?.apiKey);\n }\n\n /** Reconcile the denormalized contact count with an exact COUNT. */\n async recount(listId: string, overrides?: RequestOverrides): Promise<RecountContactListResponse> {\n return this.http.post<RecountContactListResponse>(`/v1/contact-lists/${encodeURIComponent(listId)}/recount`, {}, 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 { QuotaResource } from './resources/quota';\nimport { CampaignsResource } from './resources/campaigns';\nimport { ContactListsResource } from './resources/contactLists';\nimport type { OutboundConfig, ResolvedConfig } from './types';\n\nconst BASE_URL = 'https://outbound-api.unionstack.in';\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 readonly quota: QuotaResource;\n readonly campaigns: CampaignsResource;\n readonly contactLists: ContactListsResource;\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 this.quota = new QuotaResource(http);\n this.campaigns = new CampaignsResource(http);\n this.contactLists = new ContactListsResource(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/resources/quota.ts","../src/resources/campaigns.ts","../src/resources/contactLists.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 ListSendResponse,\n JobStatusResponse,\n MessageStatusResponse,\n MessageContentResponse,\n CancelEmailParams,\n CancelEmailResponse,\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 /**\n * Send to many recipients at once.\n *\n * Three shapes, discriminated by what you pass:\n * - `emails[]` with a full `htmlBody` each — the original behaviour, unchanged.\n * - `emails[]` + a shared `htmlBody` + per-recipient `variables` — MAIL MERGE.\n * The template crosses the wire once instead of once per recipient.\n * - `listId` (+ `mapping`) — a saved contact list, with NO recipient cap. The\n * server materializes the recipients in the background and returns a job id.\n *\n * OVERLOADED rather than returning a union, so existing calls keep resolving to\n * `BulkEmailResponse` exactly as before. A bare union would have made\n * `res.recipientCount` a compile error for every caller that upgraded.\n */\n async bulk(params: BulkEmailParams & { listId: string }, overrides?: RequestOverrides): Promise<ListSendResponse>;\n async bulk(params: BulkEmailParams, overrides?: RequestOverrides): Promise<BulkEmailResponse>;\n async bulk(params: BulkEmailParams, overrides?: RequestOverrides): Promise<BulkEmailResponse | ListSendResponse> {\n return this.http.post<BulkEmailResponse | ListSendResponse>('/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 /**\n * Look up the current status of a single message by its `messageId` — the ID\n * returned from `send()`/`bulk()` and included in webhook payloads. Useful for\n * reconciling a message whose webhook was missed.\n *\n * Accepts **only** a message ID — not a job ID or SES message ID. The message\n * must belong to the tenant the API key is scoped to; otherwise a `NotFoundError`\n * is thrown. The status reflects the latest event recorded by the SES event\n * pipeline.\n */\n async getMessageStatus(messageId: string, overrides?: RequestOverrides): Promise<MessageStatusResponse> {\n return this.http.get<MessageStatusResponse>(`/v1/email/messages/${encodeURIComponent(messageId)}/status`, undefined, overrides?.apiKey);\n }\n\n /**\n * Fetch the content that was sent for a single message by its `messageId` — the\n * subject, envelope and `htmlBody`/`textBody`, exactly as sent (the HTML includes\n * the appended unsubscribe footer). This is the same content the dashboard renders\n * in its \"Preview\", so you can reconstruct or re-display a sent email on your side.\n *\n * Accepts **only** a message ID — not a job ID or SES message ID. The message must\n * belong to the tenant the API key is scoped to; otherwise a `NotFoundError` is\n * thrown. Attachments are not inlined.\n */\n async getMessageContent(messageId: string, overrides?: RequestOverrides): Promise<MessageContentResponse> {\n return this.http.get<MessageContentResponse>(`/v1/email/messages/${encodeURIComponent(messageId)}/content`, undefined, overrides?.apiKey);\n }\n\n /**\n * Cancel all queued/processing emails for a campaign or job.\n * Provide either `campaignId` (cancels all jobs in that campaign) or `jobId` (cancels one job).\n * Already-sent emails cannot be recalled — only recipients still in `queued` or `processing` state are cancelled.\n */\n async cancel(params: CancelEmailParams, overrides?: RequestOverrides): Promise<CancelEmailResponse> {\n if (!params.campaignId && !params.jobId) {\n throw new Error('cancel() requires either campaignId or jobId');\n }\n return this.http.post<CancelEmailResponse>('/v1/email/cancel', params, 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 ListSendResponse,\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 /**\n * Send a template to many recipients.\n *\n * Pass `recipients[]` (up to 1000) for an inline send, or `listId` (+ `mapping`)\n * to send to a whole saved contact list with no recipient cap — the server\n * expands the list in the background.\n *\n * Overloaded rather than returning a union, so existing calls keep resolving to\n * `TemplateBulkSendResponse` and upgrading the SDK cannot break a build.\n */\n async bulkSend(params: TemplateBulkSendParams & { listId: string }, overrides?: RequestOverrides): Promise<ListSendResponse>;\n async bulkSend(params: TemplateBulkSendParams, overrides?: RequestOverrides): Promise<TemplateBulkSendResponse>;\n async bulkSend(params: TemplateBulkSendParams, overrides?: RequestOverrides): Promise<TemplateBulkSendResponse | ListSendResponse> {\n return this.http.post<TemplateBulkSendResponse | ListSendResponse>('/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 EmailList,\n SearchSuppressionsParams,\n SearchSuppressionsResponse,\n BulkAddSuppressionsParams,\n BulkAddSuppressionsResponse,\n BulkRemoveSuppressionsParams,\n BulkRemoveSuppressionsResponse,\n RequestOverrides,\n} from '../types';\n\n/**\n * The API takes a comma-separated list on the wire. Arrays are the ergonomic\n * form for callers, so normalize here rather than making every caller join.\n */\nfunction toEmailList(emails: EmailList): string {\n return Array.isArray(emails) ? emails.join(',') : emails;\n}\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 /**\n * Look up specific addresses on the suppression list — exact, case-insensitive,\n * up to 100 per request. Every address is validated server-side before it is\n * queried, so a malformed entry comes back in `rejected` instead of failing the\n * whole call.\n *\n * For substring matching (e.g. every address on a domain), use\n * `list({ search: 'acme.com' })` instead.\n */\n async search(params: SearchSuppressionsParams, overrides?: RequestOverrides): Promise<SearchSuppressionsResponse> {\n return this.http.get<SearchSuppressionsResponse>(\n '/v1/tenants/suppressions/search',\n { emails: toEmailList(params.emails) },\n overrides?.apiKey,\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 /**\n * Suppress up to 1000 addresses in one request. Valid addresses are added and\n * reported in `added`; ones already on the list come back in `alreadySuppressed`\n * with their existing record untouched; ones that fail validation come back in\n * `rejected` and are never written.\n */\n async bulkAdd(params: BulkAddSuppressionsParams, overrides?: RequestOverrides): Promise<BulkAddSuppressionsResponse> {\n return this.http.post<BulkAddSuppressionsResponse>(\n '/v1/tenants/suppressions/bulk/add',\n { emails: toEmailList(params.emails), reason: params.reason },\n overrides?.apiKey,\n );\n }\n\n /**\n * Unsuppress up to 1000 addresses in one request. Unlike `remove()`, an address\n * that is not on the list is not an error: it is reported in `notFound`, so one\n * bad entry cannot fail the batch.\n */\n async bulkRemove(params: BulkRemoveSuppressionsParams, overrides?: RequestOverrides): Promise<BulkRemoveSuppressionsResponse> {\n return this.http.post<BulkRemoveSuppressionsResponse>(\n '/v1/tenants/suppressions/bulk/remove',\n { emails: toEmailList(params.emails) },\n overrides?.apiKey,\n );\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 type { HttpClient } from '../http';\nimport type {\n GlobalQuotaResponse,\n CheckQuotaResponse,\n RequestOverrides,\n} from '../types';\n\n/**\n * Account-global quota: the shared SES 24h cap across ALL tenants/sources.\n *\n * Sends are NOT gated — `email.send`/`email.bulk` always submit. This is an\n * OPT-IN routing aid: call `check(count)` before a batch to ask whether the\n * shared pool has room and atomically hold it against concurrent callers. An\n * `ok:false` is a normal answer (route that batch to a fallback vendor).\n *\n * `global()` is a cheap point-in-time read; `check()` is the atomic, concurrency-\n * safe primitive that most callers want.\n */\nexport class QuotaResource {\n constructor(private http: HttpClient) {}\n\n /** Read the global quota snapshot (point-in-time). For concurrency safety use `check()`. */\n async global(overrides?: RequestOverrides): Promise<GlobalQuotaResponse> {\n return this.http.get<GlobalQuotaResponse>('/v1/quota/global', undefined, overrides?.apiKey);\n }\n\n /**\n * Opt-in quota check. Atomically holds `count` against the shared pool and\n * returns whether it fit — so two concurrent `check(300)` calls against 500 of\n * headroom can't both succeed. `ok:false` is a normal response (route to a\n * fallback vendor), not an error. The hold auto-expires after `ttlSeconds`;\n * there is no reservationId and nothing to release.\n */\n async check(count: number, overrides?: RequestOverrides): Promise<CheckQuotaResponse> {\n return this.http.post<CheckQuotaResponse>('/v1/quota/check', { count }, overrides?.apiKey);\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n ListCampaignsParams,\n ListCampaignsResponse,\n CampaignAnalyticsParams,\n CampaignAnalytics,\n RequestOverrides,\n} from '../types';\n\nexport class CampaignsResource {\n constructor(private http: HttpClient) {}\n\n /** List the tenant's campaigns with headline send stats. */\n async list(params?: ListCampaignsParams, overrides?: RequestOverrides): Promise<ListCampaignsResponse> {\n return this.http.get<ListCampaignsResponse>(\n '/v1/tenants/campaigns',\n params as Record<string, unknown> | undefined,\n overrides?.apiKey,\n );\n }\n\n /** Full analytics report for one campaign (totals, rates, timeseries, breakdowns). */\n async analytics(\n campaignId: string,\n params?: CampaignAnalyticsParams,\n overrides?: RequestOverrides,\n ): Promise<CampaignAnalytics> {\n return this.http.get<CampaignAnalytics>(\n `/v1/tenants/campaigns/${encodeURIComponent(campaignId)}/analytics`,\n params as Record<string, unknown> | undefined,\n overrides?.apiKey,\n );\n }\n}\n","import type { HttpClient } from '../http';\nimport type {\n ContactList,\n ContactListDetail,\n CreateContactListParams,\n UpdateContactListParams,\n ListContactListsParams,\n ListContactListsResponse,\n ImportContactsParams,\n ImportContactsResponse,\n ListContactsParams,\n ListContactsResponse,\n AddContactParams,\n UpdateContactParams,\n Contact,\n BulkDeleteContactsParams,\n BulkDeleteContactsResponse,\n ContactListFieldsResponse,\n RecountContactListResponse,\n AcceptedResponse,\n RequestOverrides,\n ContactFieldRewriteResponse,\n} from '../types';\n\n/**\n * Contact lists: reusable audiences you can send to without a recipient limit.\n *\n * The per-request cap on `email.bulk` / `templates.bulkSend` exists because those\n * carry their recipients in the request body. A list send carries only a `listId`,\n * and the server expands the list in the background — so there is no cap, and the\n * caller gets one job id to track however large the audience is.\n *\n * ── Address hygiene ──\n * Every imported address is sanitized (display-name unwrapping, `mailto:`,\n * zero-width characters, quotes, case) and then validated with the SAME rules the\n * send path applies. Addresses that fail are STORED with `status: 'invalid'` rather\n * than discarded, so you can list them, export them and fix them. Addresses on your\n * suppression list are stored with the matching status. Only `subscribed` contacts\n * are ever sent to, and bounces, complaints and unsubscribes flow back onto the\n * contact automatically.\n */\nexport class ContactListsResource {\n constructor(private http: HttpClient) {}\n\n async create(params: CreateContactListParams, overrides?: RequestOverrides): Promise<{ message: string; list: ContactList }> {\n return this.http.post('/v1/contact-lists', params, overrides?.apiKey);\n }\n\n async list(params?: ListContactListsParams, overrides?: RequestOverrides): Promise<ListContactListsResponse> {\n return this.http.get<ListContactListsResponse>('/v1/contact-lists', params as Record<string, unknown>, overrides?.apiKey);\n }\n\n /** Auto-paginating iterator over every contact list, mirroring templates.listAll(). */\n async *listAll(params?: Omit<ListContactListsParams, 'page'>, overrides?: RequestOverrides): AsyncGenerator<ContactList> {\n const limit = params?.limit ?? 100;\n let page = 1;\n for (;;) {\n const result = await this.list({ ...params, page, limit }, overrides);\n for (const item of result.lists) yield item;\n if (result.lists.length < limit) return;\n page += 1;\n }\n }\n\n /** A list plus its per-status breakdown (how many are sendable, invalid, bounced...). */\n async get(listId: string, overrides?: RequestOverrides): Promise<ContactListDetail> {\n return this.http.get<ContactListDetail>(`/v1/contact-lists/${encodeURIComponent(listId)}`, undefined, overrides?.apiKey);\n }\n\n async update(listId: string, params: UpdateContactListParams, overrides?: RequestOverrides): Promise<{ message: string; list: ContactList }> {\n return this.http.patch(`/v1/contact-lists/${encodeURIComponent(listId)}`, params, overrides?.apiKey);\n }\n\n /**\n * Delete a list. Returns 202: the contacts are removed by a background job in\n * chunks, so a multi-million-row list does not block on one enormous transaction.\n * Fails with a conflict while a send is still expanding this list.\n */\n async delete(listId: string, overrides?: RequestOverrides): Promise<AcceptedResponse> {\n return this.http.delete<AcceptedResponse>(`/v1/contact-lists/${encodeURIComponent(listId)}`, overrides?.apiKey);\n }\n\n /**\n * Import a chunk of contacts (max 1000 rows per call).\n *\n * Pass the same `importId` with an incrementing `chunkIndex` for every chunk of\n * one file: that pair makes a retried chunk a no-op instead of a double-insert,\n * so a network failure mid-upload is safe to retry blindly.\n *\n * `onExisting: 'update'` merges attributes into contacts already in the list. It\n * never re-subscribes someone who bounced, complained or opted out.\n */\n async importContacts(listId: string, params: ImportContactsParams, overrides?: RequestOverrides): Promise<ImportContactsResponse> {\n return this.http.post<ImportContactsResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts/import`, params, overrides?.apiKey,\n );\n }\n\n /**\n * List contacts. KEYSET paginated: pass the previous response's\n * `pagination.nextCursor` as `cursor` to advance. There is no page number,\n * because offset paging degrades badly past a few hundred pages.\n */\n async contacts(listId: string, params?: ListContactsParams, overrides?: RequestOverrides): Promise<ListContactsResponse> {\n return this.http.get<ListContactsResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts`, params as Record<string, unknown>, overrides?.apiKey,\n );\n }\n\n /** Auto-paginating iterator over every contact in a list. */\n async *contactsAll(listId: string, params?: Omit<ListContactsParams, 'cursor'>, overrides?: RequestOverrides): AsyncGenerator<Contact> {\n let cursor: string | undefined;\n for (;;) {\n const result = await this.contacts(listId, { ...params, cursor }, overrides);\n for (const contact of result.contacts) yield contact;\n if (!result.pagination.hasMore || !result.pagination.nextCursor) return;\n cursor = result.pagination.nextCursor;\n }\n }\n\n async addContact(listId: string, params: AddContactParams, overrides?: RequestOverrides): Promise<{ message: string; contact: Contact }> {\n return this.http.post(`/v1/contact-lists/${encodeURIComponent(listId)}/contacts`, params, overrides?.apiKey);\n }\n\n /** `attributes` REPLACES the stored object wholesale here; import merges instead. */\n async updateContact(listId: string, contactId: string, params: UpdateContactParams, overrides?: RequestOverrides): Promise<{ message: string; contact: Contact }> {\n return this.http.patch(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts/${encodeURIComponent(contactId)}`, params, overrides?.apiKey,\n );\n }\n\n async deleteContact(listId: string, contactId: string, overrides?: RequestOverrides): Promise<void> {\n await this.http.delete(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts/${encodeURIComponent(contactId)}`, overrides?.apiKey,\n );\n }\n\n /**\n * Delete many contacts. Pass `contactIds` or `emails` (up to 1000), or a FILTER\n * — `{ status: 'invalid' }` or `{ all: true }` — which is how you clear tens of\n * thousands of dead addresses in one small request. Filtered deletes return 202\n * and run in the background.\n */\n async bulkDeleteContacts(listId: string, params: BulkDeleteContactsParams, overrides?: RequestOverrides): Promise<BulkDeleteContactsResponse> {\n return this.http.post<BulkDeleteContactsResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/contacts/bulk-delete`, params, overrides?.apiKey,\n );\n }\n\n /**\n * The column names available for send-time variable mapping, with a sample value\n * for each. This is what tells you which `mapping` keys a list will accept.\n */\n async fields(listId: string, options?: { refresh?: boolean }, overrides?: RequestOverrides): Promise<ContactListFieldsResponse> {\n return this.http.get<ContactListFieldsResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/fields`,\n options?.refresh ? { refresh: 'true' } : undefined,\n overrides?.apiKey,\n );\n }\n\n /**\n * Re-run validation and re-sync suppression across the whole list. Useful after a\n * bulk suppression import, or to refresh a list that has been sitting. Returns 202.\n */\n async revalidate(listId: string, overrides?: RequestOverrides): Promise<AcceptedResponse> {\n return this.http.post<AcceptedResponse>(`/v1/contact-lists/${encodeURIComponent(listId)}/revalidate`, {}, overrides?.apiKey);\n }\n\n /** Reconcile the denormalized contact count with an exact COUNT. */\n async recount(listId: string, overrides?: RequestOverrides): Promise<RecountContactListResponse> {\n return this.http.post<RecountContactListResponse>(`/v1/contact-lists/${encodeURIComponent(listId)}/recount`, {}, overrides?.apiKey);\n }\n\n /**\n * Rename a column across every contact in the list. Returns 202: the rewrite runs\n * as a chunked background job, so `fields` settles a moment later.\n *\n * Rejects a name that already exists on the list — merging two columns is a data\n * decision (which value wins per contact?), not a rename.\n */\n async renameField(\n listId: string,\n name: string,\n newName: string,\n overrides?: RequestOverrides,\n ): Promise<ContactFieldRewriteResponse> {\n return this.http.patch<ContactFieldRewriteResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/fields/${encodeURIComponent(name)}`,\n { name: newName },\n overrides?.apiKey,\n );\n }\n\n /**\n * Drop a column from every contact in the list. Returns 202.\n * The values go with the column; this is not recoverable.\n */\n async deleteField(\n listId: string,\n name: string,\n overrides?: RequestOverrides,\n ): Promise<ContactFieldRewriteResponse> {\n return this.http.delete<ContactFieldRewriteResponse>(\n `/v1/contact-lists/${encodeURIComponent(listId)}/fields/${encodeURIComponent(name)}`,\n overrides?.apiKey,\n );\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 { QuotaResource } from './resources/quota';\nimport { CampaignsResource } from './resources/campaigns';\nimport { ContactListsResource } from './resources/contactLists';\nimport type { OutboundConfig, ResolvedConfig } from './types';\n\nconst BASE_URL = 'https://outbound-api.unionstack.in';\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 readonly quota: QuotaResource;\n readonly campaigns: CampaignsResource;\n readonly contactLists: ContactListsResource;\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 this.quota = new QuotaResource(http);\n this.campaigns = new CampaignsResource(http);\n this.contactLists = new ContactListsResource(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.4.10",
3
+ "version": "0.4.12",
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",