tosend 1.0.0 → 1.0.1

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
@@ -66,10 +66,12 @@ interface AccountInfo {
66
66
  domains: Domain[];
67
67
  }
68
68
  interface ToSendErrorResponse {
69
- error_code: number;
69
+ status_code: number;
70
+ error_type: ErrorType;
70
71
  message: string;
71
72
  errors?: Record<string, Record<string, string>>;
72
73
  }
74
+ type ErrorType = 'bad_request' | 'unauthorized' | 'forbidden' | 'not_found' | 'validation_error' | 'rate_limit_exceeded' | 'internal_error';
73
75
  interface ToSendConfig {
74
76
  /** Your ToSend API key */
75
77
  apiKey: string;
@@ -80,8 +82,10 @@ interface ToSendConfig {
80
82
  }
81
83
  declare class ToSendError extends Error {
82
84
  readonly code: number;
85
+ readonly errorType: ErrorType;
83
86
  readonly errors: Record<string, Record<string, string>>;
84
- constructor(message: string, code?: number, errors?: Record<string, Record<string, string>>);
87
+ private static readonly ERROR_TYPE_MAP;
88
+ constructor(message: string, code?: number, errors?: Record<string, Record<string, string>>, errorType?: ErrorType);
85
89
  get isValidationError(): boolean;
86
90
  get isAuthenticationError(): boolean;
87
91
  get isRateLimitError(): boolean;
@@ -151,4 +155,4 @@ declare class ToSend {
151
155
  private request;
152
156
  }
153
157
 
154
- export { type AccountInfo, type Address, type Attachment, type BatchEmailResponse, type BatchEmailResult, type Domain, type SendEmailParams, type SendEmailResponse, ToSend, type ToSendConfig, ToSendError, type ToSendErrorResponse, ToSend as default };
158
+ export { type AccountInfo, type Address, type Attachment, type BatchEmailResponse, type BatchEmailResult, type Domain, type ErrorType, type SendEmailParams, type SendEmailResponse, ToSend, type ToSendConfig, ToSendError, type ToSendErrorResponse, ToSend as default };
package/dist/index.d.ts CHANGED
@@ -66,10 +66,12 @@ interface AccountInfo {
66
66
  domains: Domain[];
67
67
  }
68
68
  interface ToSendErrorResponse {
69
- error_code: number;
69
+ status_code: number;
70
+ error_type: ErrorType;
70
71
  message: string;
71
72
  errors?: Record<string, Record<string, string>>;
72
73
  }
74
+ type ErrorType = 'bad_request' | 'unauthorized' | 'forbidden' | 'not_found' | 'validation_error' | 'rate_limit_exceeded' | 'internal_error';
73
75
  interface ToSendConfig {
74
76
  /** Your ToSend API key */
75
77
  apiKey: string;
@@ -80,8 +82,10 @@ interface ToSendConfig {
80
82
  }
81
83
  declare class ToSendError extends Error {
82
84
  readonly code: number;
85
+ readonly errorType: ErrorType;
83
86
  readonly errors: Record<string, Record<string, string>>;
84
- constructor(message: string, code?: number, errors?: Record<string, Record<string, string>>);
87
+ private static readonly ERROR_TYPE_MAP;
88
+ constructor(message: string, code?: number, errors?: Record<string, Record<string, string>>, errorType?: ErrorType);
85
89
  get isValidationError(): boolean;
86
90
  get isAuthenticationError(): boolean;
87
91
  get isRateLimitError(): boolean;
@@ -151,4 +155,4 @@ declare class ToSend {
151
155
  private request;
152
156
  }
153
157
 
154
- export { type AccountInfo, type Address, type Attachment, type BatchEmailResponse, type BatchEmailResult, type Domain, type SendEmailParams, type SendEmailResponse, ToSend, type ToSendConfig, ToSendError, type ToSendErrorResponse, ToSend as default };
158
+ export { type AccountInfo, type Address, type Attachment, type BatchEmailResponse, type BatchEmailResult, type Domain, type ErrorType, type SendEmailParams, type SendEmailResponse, ToSend, type ToSendConfig, ToSendError, type ToSendErrorResponse, ToSend as default };
package/dist/index.js CHANGED
@@ -25,23 +25,33 @@ __export(index_exports, {
25
25
  default: () => index_default
26
26
  });
27
27
  module.exports = __toCommonJS(index_exports);
28
- var ToSendError = class extends Error {
28
+ var ToSendError = class _ToSendError extends Error {
29
29
  code;
30
+ errorType;
30
31
  errors;
31
- constructor(message, code = 0, errors = {}) {
32
+ static ERROR_TYPE_MAP = {
33
+ 400: "bad_request",
34
+ 401: "unauthorized",
35
+ 403: "forbidden",
36
+ 404: "not_found",
37
+ 422: "validation_error",
38
+ 429: "rate_limit_exceeded"
39
+ };
40
+ constructor(message, code = 0, errors = {}, errorType) {
32
41
  super(message);
33
42
  this.name = "ToSendError";
34
43
  this.code = code;
35
44
  this.errors = errors;
45
+ this.errorType = errorType ?? _ToSendError.ERROR_TYPE_MAP[code] ?? "internal_error";
36
46
  }
37
47
  get isValidationError() {
38
- return this.code === 422;
48
+ return this.errorType === "validation_error" || this.code === 422;
39
49
  }
40
50
  get isAuthenticationError() {
41
- return this.code === 401 || this.code === 403;
51
+ return this.errorType === "unauthorized" || this.errorType === "forbidden" || this.code === 401 || this.code === 403;
42
52
  }
43
53
  get isRateLimitError() {
44
- return this.code === 429;
54
+ return this.errorType === "rate_limit_exceeded" || this.code === 429;
45
55
  }
46
56
  };
47
57
  var ToSend = class {
@@ -199,7 +209,8 @@ var ToSend = class {
199
209
  throw new ToSendError(
200
210
  data.message ?? "Unknown error",
201
211
  response.status,
202
- data.errors ?? {}
212
+ data.errors ?? {},
213
+ data.error_type
203
214
  );
204
215
  }
205
216
  return data;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * ToSend Node.js SDK\n *\n * Official SDK for the ToSend email API.\n * @see https://tosend.com/docs\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface Address {\n email: string;\n name?: string;\n}\n\nexport interface Attachment {\n /** MIME type (e.g., 'application/pdf') */\n type: string;\n /** Filename */\n name: string;\n /** Base64 encoded content */\n content: string;\n}\n\nexport interface SendEmailParams {\n /** Sender address */\n from: Address;\n /** Recipients (max 50) */\n to: Address[];\n /** Email subject */\n subject: string;\n /** HTML content */\n html?: string;\n /** Plain text content */\n text?: string;\n /** CC recipients */\n cc?: Address[];\n /** BCC recipients */\n bcc?: Address[];\n /** Reply-to address */\n reply_to?: Address;\n /** Custom headers */\n headers?: Record<string, string>;\n /** File attachments */\n attachments?: Attachment[];\n}\n\nexport interface SendEmailResponse {\n message_id: string;\n}\n\nexport interface BatchEmailResult {\n status: 'success' | 'error' | 'spam';\n message_id?: string;\n message?: string;\n errors?: Record<string, Record<string, string>>;\n}\n\nexport interface BatchEmailResponse {\n results: BatchEmailResult[];\n}\n\nexport interface Domain {\n domain_name: string;\n verification_status: 'pending' | 'verified' | 'failed';\n created_at: string;\n}\n\nexport interface AccountInfo {\n account: {\n title: string;\n plan_type: string;\n status: string;\n emails_usage_this_month: number;\n emails_sent_last_24hrs: number;\n };\n domains: Domain[];\n}\n\nexport interface ToSendErrorResponse {\n error_code: number;\n message: string;\n errors?: Record<string, Record<string, string>>;\n}\n\nexport interface ToSendConfig {\n /** Your ToSend API key */\n apiKey: string;\n /** Custom base URL (optional) */\n baseUrl?: string;\n /** Request timeout in ms (default: 30000) */\n timeout?: number;\n}\n\n// ============================================================================\n// Error Class\n// ============================================================================\n\nexport class ToSendError extends Error {\n readonly code: number;\n readonly errors: Record<string, Record<string, string>>;\n\n constructor(\n message: string,\n code: number = 0,\n errors: Record<string, Record<string, string>> = {}\n ) {\n super(message);\n this.name = 'ToSendError';\n this.code = code;\n this.errors = errors;\n }\n\n get isValidationError(): boolean {\n return this.code === 422;\n }\n\n get isAuthenticationError(): boolean {\n return this.code === 401 || this.code === 403;\n }\n\n get isRateLimitError(): boolean {\n return this.code === 429;\n }\n}\n\n// ============================================================================\n// Main Client\n// ============================================================================\n\nexport class ToSend {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(config: string | ToSendConfig) {\n if (typeof config === 'string') {\n this.apiKey = config;\n this.baseUrl = 'https://api.tosend.com';\n this.timeout = 30000;\n } else {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl?.replace(/\\/$/, '') ?? 'https://api.tosend.com';\n this.timeout = config.timeout ?? 30000;\n }\n\n if (!this.apiKey?.trim()) {\n throw new ToSendError('API key is required', 401);\n }\n }\n\n /**\n * Send a single email.\n *\n * @example\n * ```ts\n * const response = await tosend.send({\n * from: { email: 'hello@example.com', name: 'My App' },\n * to: [{ email: 'user@example.com' }],\n * subject: 'Hello!',\n * html: '<p>Welcome!</p>'\n * });\n * console.log(response.message_id);\n * ```\n */\n async send(params: SendEmailParams): Promise<SendEmailResponse> {\n this.validateEmailParams(params);\n return this.request<SendEmailResponse>('POST', '/v2/emails', params);\n }\n\n /**\n * Send multiple emails in a single request.\n *\n * @example\n * ```ts\n * const response = await tosend.batch([\n * {\n * from: { email: 'hello@example.com' },\n * to: [{ email: 'user1@example.com' }],\n * subject: 'Hello User 1',\n * html: '<p>Hi!</p>'\n * },\n * {\n * from: { email: 'hello@example.com' },\n * to: [{ email: 'user2@example.com' }],\n * subject: 'Hello User 2',\n * html: '<p>Hi!</p>'\n * }\n * ]);\n *\n * response.results.forEach(result => {\n * if (result.status === 'success') {\n * console.log('Sent:', result.message_id);\n * }\n * });\n * ```\n */\n async batch(emails: SendEmailParams[]): Promise<BatchEmailResponse> {\n if (!emails?.length) {\n throw new ToSendError('Emails array is required and cannot be empty', 422, {\n emails: { required: 'At least one email is required' },\n });\n }\n\n emails.forEach((email, index) => {\n try {\n this.validateEmailParams(email);\n } catch (error) {\n if (error instanceof ToSendError) {\n throw new ToSendError(\n `Email at index ${index}: ${error.message}`,\n error.code,\n error.errors\n );\n }\n throw error;\n }\n });\n\n return this.request<BatchEmailResponse>('POST', '/v2/emails/batch', { emails });\n }\n\n /**\n * Get account information and domains.\n *\n * @example\n * ```ts\n * const info = await tosend.getAccountInfo();\n * console.log(info.account.title);\n * console.log(info.account.emails_usage_this_month);\n * info.domains.forEach(d => console.log(d.domain_name, d.verification_status));\n * ```\n */\n async getAccountInfo(): Promise<AccountInfo> {\n return this.request<AccountInfo>('GET', '/v2/info');\n }\n\n // ==========================================================================\n // Private Methods\n // ==========================================================================\n\n private validateEmailParams(params: SendEmailParams): void {\n const errors: Record<string, Record<string, string>> = {};\n\n if (!params.from?.email) {\n errors.from = { required: 'From email is required' };\n } else if (!this.isValidEmail(params.from.email)) {\n errors.from = { invalid: 'From email is invalid' };\n }\n\n if (!params.to?.length) {\n errors.to = { required: 'To is required' };\n } else {\n const hasValidRecipient = params.to.some(\n (r) => r.email && this.isValidEmail(r.email)\n );\n if (!hasValidRecipient) {\n errors.to = { invalid: 'At least one valid recipient email is required' };\n }\n }\n\n if (!params.subject) {\n errors.subject = { required: 'Subject is required' };\n }\n\n if (!params.html && !params.text) {\n errors.content = { required: 'Either html or text content is required' };\n }\n\n if (Object.keys(errors).length > 0) {\n const firstError = Object.values(errors)[0];\n const message = Object.values(firstError)[0];\n throw new ToSendError(message, 422, errors);\n }\n }\n\n private isValidEmail(email: string): boolean {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);\n }\n\n private async request<T>(\n method: 'GET' | 'POST',\n endpoint: string,\n body?: unknown\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n const data = await response.json() as T & { message?: string; errors?: Record<string, Record<string, string>> };\n\n if (!response.ok) {\n throw new ToSendError(\n data.message ?? 'Unknown error',\n response.status,\n data.errors ?? {}\n );\n }\n\n return data;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof ToSendError) {\n throw error;\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new ToSendError('Request timeout', 408);\n }\n throw new ToSendError(error.message);\n }\n\n throw new ToSendError('Unknown error');\n }\n }\n}\n\n// ============================================================================\n// Default Export\n// ============================================================================\n\nexport default ToSend;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * ToSend Node.js SDK\n *\n * Official SDK for the ToSend email API.\n * @see https://tosend.com/docs\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface Address {\n email: string;\n name?: string;\n}\n\nexport interface Attachment {\n /** MIME type (e.g., 'application/pdf') */\n type: string;\n /** Filename */\n name: string;\n /** Base64 encoded content */\n content: string;\n}\n\nexport interface SendEmailParams {\n /** Sender address */\n from: Address;\n /** Recipients (max 50) */\n to: Address[];\n /** Email subject */\n subject: string;\n /** HTML content */\n html?: string;\n /** Plain text content */\n text?: string;\n /** CC recipients */\n cc?: Address[];\n /** BCC recipients */\n bcc?: Address[];\n /** Reply-to address */\n reply_to?: Address;\n /** Custom headers */\n headers?: Record<string, string>;\n /** File attachments */\n attachments?: Attachment[];\n}\n\nexport interface SendEmailResponse {\n message_id: string;\n}\n\nexport interface BatchEmailResult {\n status: 'success' | 'error' | 'spam';\n message_id?: string;\n message?: string;\n errors?: Record<string, Record<string, string>>;\n}\n\nexport interface BatchEmailResponse {\n results: BatchEmailResult[];\n}\n\nexport interface Domain {\n domain_name: string;\n verification_status: 'pending' | 'verified' | 'failed';\n created_at: string;\n}\n\nexport interface AccountInfo {\n account: {\n title: string;\n plan_type: string;\n status: string;\n emails_usage_this_month: number;\n emails_sent_last_24hrs: number;\n };\n domains: Domain[];\n}\n\nexport interface ToSendErrorResponse {\n status_code: number;\n error_type: ErrorType;\n message: string;\n errors?: Record<string, Record<string, string>>;\n}\n\nexport type ErrorType =\n | 'bad_request'\n | 'unauthorized'\n | 'forbidden'\n | 'not_found'\n | 'validation_error'\n | 'rate_limit_exceeded'\n | 'internal_error';\n\nexport interface ToSendConfig {\n /** Your ToSend API key */\n apiKey: string;\n /** Custom base URL (optional) */\n baseUrl?: string;\n /** Request timeout in ms (default: 30000) */\n timeout?: number;\n}\n\n// ============================================================================\n// Error Class\n// ============================================================================\n\nexport class ToSendError extends Error {\n readonly code: number;\n readonly errorType: ErrorType;\n readonly errors: Record<string, Record<string, string>>;\n\n private static readonly ERROR_TYPE_MAP: Record<number, ErrorType> = {\n 400: 'bad_request',\n 401: 'unauthorized',\n 403: 'forbidden',\n 404: 'not_found',\n 422: 'validation_error',\n 429: 'rate_limit_exceeded',\n };\n\n constructor(\n message: string,\n code: number = 0,\n errors: Record<string, Record<string, string>> = {},\n errorType?: ErrorType\n ) {\n super(message);\n this.name = 'ToSendError';\n this.code = code;\n this.errors = errors;\n this.errorType = errorType ?? ToSendError.ERROR_TYPE_MAP[code] ?? 'internal_error';\n }\n\n get isValidationError(): boolean {\n return this.errorType === 'validation_error' || this.code === 422;\n }\n\n get isAuthenticationError(): boolean {\n return (\n this.errorType === 'unauthorized' ||\n this.errorType === 'forbidden' ||\n this.code === 401 ||\n this.code === 403\n );\n }\n\n get isRateLimitError(): boolean {\n return this.errorType === 'rate_limit_exceeded' || this.code === 429;\n }\n}\n\n// ============================================================================\n// Main Client\n// ============================================================================\n\nexport class ToSend {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(config: string | ToSendConfig) {\n if (typeof config === 'string') {\n this.apiKey = config;\n this.baseUrl = 'https://api.tosend.com';\n this.timeout = 30000;\n } else {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl?.replace(/\\/$/, '') ?? 'https://api.tosend.com';\n this.timeout = config.timeout ?? 30000;\n }\n\n if (!this.apiKey?.trim()) {\n throw new ToSendError('API key is required', 401);\n }\n }\n\n /**\n * Send a single email.\n *\n * @example\n * ```ts\n * const response = await tosend.send({\n * from: { email: 'hello@example.com', name: 'My App' },\n * to: [{ email: 'user@example.com' }],\n * subject: 'Hello!',\n * html: '<p>Welcome!</p>'\n * });\n * console.log(response.message_id);\n * ```\n */\n async send(params: SendEmailParams): Promise<SendEmailResponse> {\n this.validateEmailParams(params);\n return this.request<SendEmailResponse>('POST', '/v2/emails', params);\n }\n\n /**\n * Send multiple emails in a single request.\n *\n * @example\n * ```ts\n * const response = await tosend.batch([\n * {\n * from: { email: 'hello@example.com' },\n * to: [{ email: 'user1@example.com' }],\n * subject: 'Hello User 1',\n * html: '<p>Hi!</p>'\n * },\n * {\n * from: { email: 'hello@example.com' },\n * to: [{ email: 'user2@example.com' }],\n * subject: 'Hello User 2',\n * html: '<p>Hi!</p>'\n * }\n * ]);\n *\n * response.results.forEach(result => {\n * if (result.status === 'success') {\n * console.log('Sent:', result.message_id);\n * }\n * });\n * ```\n */\n async batch(emails: SendEmailParams[]): Promise<BatchEmailResponse> {\n if (!emails?.length) {\n throw new ToSendError('Emails array is required and cannot be empty', 422, {\n emails: { required: 'At least one email is required' },\n });\n }\n\n emails.forEach((email, index) => {\n try {\n this.validateEmailParams(email);\n } catch (error) {\n if (error instanceof ToSendError) {\n throw new ToSendError(\n `Email at index ${index}: ${error.message}`,\n error.code,\n error.errors\n );\n }\n throw error;\n }\n });\n\n return this.request<BatchEmailResponse>('POST', '/v2/emails/batch', { emails });\n }\n\n /**\n * Get account information and domains.\n *\n * @example\n * ```ts\n * const info = await tosend.getAccountInfo();\n * console.log(info.account.title);\n * console.log(info.account.emails_usage_this_month);\n * info.domains.forEach(d => console.log(d.domain_name, d.verification_status));\n * ```\n */\n async getAccountInfo(): Promise<AccountInfo> {\n return this.request<AccountInfo>('GET', '/v2/info');\n }\n\n // ==========================================================================\n // Private Methods\n // ==========================================================================\n\n private validateEmailParams(params: SendEmailParams): void {\n const errors: Record<string, Record<string, string>> = {};\n\n if (!params.from?.email) {\n errors.from = { required: 'From email is required' };\n } else if (!this.isValidEmail(params.from.email)) {\n errors.from = { invalid: 'From email is invalid' };\n }\n\n if (!params.to?.length) {\n errors.to = { required: 'To is required' };\n } else {\n const hasValidRecipient = params.to.some(\n (r) => r.email && this.isValidEmail(r.email)\n );\n if (!hasValidRecipient) {\n errors.to = { invalid: 'At least one valid recipient email is required' };\n }\n }\n\n if (!params.subject) {\n errors.subject = { required: 'Subject is required' };\n }\n\n if (!params.html && !params.text) {\n errors.content = { required: 'Either html or text content is required' };\n }\n\n if (Object.keys(errors).length > 0) {\n const firstError = Object.values(errors)[0];\n const message = Object.values(firstError)[0];\n throw new ToSendError(message, 422, errors);\n }\n }\n\n private isValidEmail(email: string): boolean {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);\n }\n\n private async request<T>(\n method: 'GET' | 'POST',\n endpoint: string,\n body?: unknown\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n const data = await response.json() as T & {\n message?: string;\n errors?: Record<string, Record<string, string>>;\n error_type?: ErrorType;\n };\n\n if (!response.ok) {\n throw new ToSendError(\n data.message ?? 'Unknown error',\n response.status,\n data.errors ?? {},\n data.error_type\n );\n }\n\n return data;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof ToSendError) {\n throw error;\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new ToSendError('Request timeout', 408);\n }\n throw new ToSendError(error.message);\n }\n\n throw new ToSendError('Unknown error');\n }\n }\n}\n\n// ============================================================================\n// Default Export\n// ============================================================================\n\nexport default ToSend;\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -1,21 +1,31 @@
1
1
  // src/index.ts
2
- var ToSendError = class extends Error {
2
+ var ToSendError = class _ToSendError extends Error {
3
3
  code;
4
+ errorType;
4
5
  errors;
5
- constructor(message, code = 0, errors = {}) {
6
+ static ERROR_TYPE_MAP = {
7
+ 400: "bad_request",
8
+ 401: "unauthorized",
9
+ 403: "forbidden",
10
+ 404: "not_found",
11
+ 422: "validation_error",
12
+ 429: "rate_limit_exceeded"
13
+ };
14
+ constructor(message, code = 0, errors = {}, errorType) {
6
15
  super(message);
7
16
  this.name = "ToSendError";
8
17
  this.code = code;
9
18
  this.errors = errors;
19
+ this.errorType = errorType ?? _ToSendError.ERROR_TYPE_MAP[code] ?? "internal_error";
10
20
  }
11
21
  get isValidationError() {
12
- return this.code === 422;
22
+ return this.errorType === "validation_error" || this.code === 422;
13
23
  }
14
24
  get isAuthenticationError() {
15
- return this.code === 401 || this.code === 403;
25
+ return this.errorType === "unauthorized" || this.errorType === "forbidden" || this.code === 401 || this.code === 403;
16
26
  }
17
27
  get isRateLimitError() {
18
- return this.code === 429;
28
+ return this.errorType === "rate_limit_exceeded" || this.code === 429;
19
29
  }
20
30
  };
21
31
  var ToSend = class {
@@ -173,7 +183,8 @@ var ToSend = class {
173
183
  throw new ToSendError(
174
184
  data.message ?? "Unknown error",
175
185
  response.status,
176
- data.errors ?? {}
186
+ data.errors ?? {},
187
+ data.error_type
177
188
  );
178
189
  }
179
190
  return data;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * ToSend Node.js SDK\n *\n * Official SDK for the ToSend email API.\n * @see https://tosend.com/docs\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface Address {\n email: string;\n name?: string;\n}\n\nexport interface Attachment {\n /** MIME type (e.g., 'application/pdf') */\n type: string;\n /** Filename */\n name: string;\n /** Base64 encoded content */\n content: string;\n}\n\nexport interface SendEmailParams {\n /** Sender address */\n from: Address;\n /** Recipients (max 50) */\n to: Address[];\n /** Email subject */\n subject: string;\n /** HTML content */\n html?: string;\n /** Plain text content */\n text?: string;\n /** CC recipients */\n cc?: Address[];\n /** BCC recipients */\n bcc?: Address[];\n /** Reply-to address */\n reply_to?: Address;\n /** Custom headers */\n headers?: Record<string, string>;\n /** File attachments */\n attachments?: Attachment[];\n}\n\nexport interface SendEmailResponse {\n message_id: string;\n}\n\nexport interface BatchEmailResult {\n status: 'success' | 'error' | 'spam';\n message_id?: string;\n message?: string;\n errors?: Record<string, Record<string, string>>;\n}\n\nexport interface BatchEmailResponse {\n results: BatchEmailResult[];\n}\n\nexport interface Domain {\n domain_name: string;\n verification_status: 'pending' | 'verified' | 'failed';\n created_at: string;\n}\n\nexport interface AccountInfo {\n account: {\n title: string;\n plan_type: string;\n status: string;\n emails_usage_this_month: number;\n emails_sent_last_24hrs: number;\n };\n domains: Domain[];\n}\n\nexport interface ToSendErrorResponse {\n error_code: number;\n message: string;\n errors?: Record<string, Record<string, string>>;\n}\n\nexport interface ToSendConfig {\n /** Your ToSend API key */\n apiKey: string;\n /** Custom base URL (optional) */\n baseUrl?: string;\n /** Request timeout in ms (default: 30000) */\n timeout?: number;\n}\n\n// ============================================================================\n// Error Class\n// ============================================================================\n\nexport class ToSendError extends Error {\n readonly code: number;\n readonly errors: Record<string, Record<string, string>>;\n\n constructor(\n message: string,\n code: number = 0,\n errors: Record<string, Record<string, string>> = {}\n ) {\n super(message);\n this.name = 'ToSendError';\n this.code = code;\n this.errors = errors;\n }\n\n get isValidationError(): boolean {\n return this.code === 422;\n }\n\n get isAuthenticationError(): boolean {\n return this.code === 401 || this.code === 403;\n }\n\n get isRateLimitError(): boolean {\n return this.code === 429;\n }\n}\n\n// ============================================================================\n// Main Client\n// ============================================================================\n\nexport class ToSend {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(config: string | ToSendConfig) {\n if (typeof config === 'string') {\n this.apiKey = config;\n this.baseUrl = 'https://api.tosend.com';\n this.timeout = 30000;\n } else {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl?.replace(/\\/$/, '') ?? 'https://api.tosend.com';\n this.timeout = config.timeout ?? 30000;\n }\n\n if (!this.apiKey?.trim()) {\n throw new ToSendError('API key is required', 401);\n }\n }\n\n /**\n * Send a single email.\n *\n * @example\n * ```ts\n * const response = await tosend.send({\n * from: { email: 'hello@example.com', name: 'My App' },\n * to: [{ email: 'user@example.com' }],\n * subject: 'Hello!',\n * html: '<p>Welcome!</p>'\n * });\n * console.log(response.message_id);\n * ```\n */\n async send(params: SendEmailParams): Promise<SendEmailResponse> {\n this.validateEmailParams(params);\n return this.request<SendEmailResponse>('POST', '/v2/emails', params);\n }\n\n /**\n * Send multiple emails in a single request.\n *\n * @example\n * ```ts\n * const response = await tosend.batch([\n * {\n * from: { email: 'hello@example.com' },\n * to: [{ email: 'user1@example.com' }],\n * subject: 'Hello User 1',\n * html: '<p>Hi!</p>'\n * },\n * {\n * from: { email: 'hello@example.com' },\n * to: [{ email: 'user2@example.com' }],\n * subject: 'Hello User 2',\n * html: '<p>Hi!</p>'\n * }\n * ]);\n *\n * response.results.forEach(result => {\n * if (result.status === 'success') {\n * console.log('Sent:', result.message_id);\n * }\n * });\n * ```\n */\n async batch(emails: SendEmailParams[]): Promise<BatchEmailResponse> {\n if (!emails?.length) {\n throw new ToSendError('Emails array is required and cannot be empty', 422, {\n emails: { required: 'At least one email is required' },\n });\n }\n\n emails.forEach((email, index) => {\n try {\n this.validateEmailParams(email);\n } catch (error) {\n if (error instanceof ToSendError) {\n throw new ToSendError(\n `Email at index ${index}: ${error.message}`,\n error.code,\n error.errors\n );\n }\n throw error;\n }\n });\n\n return this.request<BatchEmailResponse>('POST', '/v2/emails/batch', { emails });\n }\n\n /**\n * Get account information and domains.\n *\n * @example\n * ```ts\n * const info = await tosend.getAccountInfo();\n * console.log(info.account.title);\n * console.log(info.account.emails_usage_this_month);\n * info.domains.forEach(d => console.log(d.domain_name, d.verification_status));\n * ```\n */\n async getAccountInfo(): Promise<AccountInfo> {\n return this.request<AccountInfo>('GET', '/v2/info');\n }\n\n // ==========================================================================\n // Private Methods\n // ==========================================================================\n\n private validateEmailParams(params: SendEmailParams): void {\n const errors: Record<string, Record<string, string>> = {};\n\n if (!params.from?.email) {\n errors.from = { required: 'From email is required' };\n } else if (!this.isValidEmail(params.from.email)) {\n errors.from = { invalid: 'From email is invalid' };\n }\n\n if (!params.to?.length) {\n errors.to = { required: 'To is required' };\n } else {\n const hasValidRecipient = params.to.some(\n (r) => r.email && this.isValidEmail(r.email)\n );\n if (!hasValidRecipient) {\n errors.to = { invalid: 'At least one valid recipient email is required' };\n }\n }\n\n if (!params.subject) {\n errors.subject = { required: 'Subject is required' };\n }\n\n if (!params.html && !params.text) {\n errors.content = { required: 'Either html or text content is required' };\n }\n\n if (Object.keys(errors).length > 0) {\n const firstError = Object.values(errors)[0];\n const message = Object.values(firstError)[0];\n throw new ToSendError(message, 422, errors);\n }\n }\n\n private isValidEmail(email: string): boolean {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);\n }\n\n private async request<T>(\n method: 'GET' | 'POST',\n endpoint: string,\n body?: unknown\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n const data = await response.json() as T & { message?: string; errors?: Record<string, Record<string, string>> };\n\n if (!response.ok) {\n throw new ToSendError(\n data.message ?? 'Unknown error',\n response.status,\n data.errors ?? {}\n );\n }\n\n return data;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof ToSendError) {\n throw error;\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new ToSendError('Request timeout', 408);\n }\n throw new ToSendError(error.message);\n }\n\n throw new ToSendError('Unknown error');\n }\n }\n}\n\n// ============================================================================\n// Default Export\n// ============================================================================\n\nexport default ToSend;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * ToSend Node.js SDK\n *\n * Official SDK for the ToSend email API.\n * @see https://tosend.com/docs\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface Address {\n email: string;\n name?: string;\n}\n\nexport interface Attachment {\n /** MIME type (e.g., 'application/pdf') */\n type: string;\n /** Filename */\n name: string;\n /** Base64 encoded content */\n content: string;\n}\n\nexport interface SendEmailParams {\n /** Sender address */\n from: Address;\n /** Recipients (max 50) */\n to: Address[];\n /** Email subject */\n subject: string;\n /** HTML content */\n html?: string;\n /** Plain text content */\n text?: string;\n /** CC recipients */\n cc?: Address[];\n /** BCC recipients */\n bcc?: Address[];\n /** Reply-to address */\n reply_to?: Address;\n /** Custom headers */\n headers?: Record<string, string>;\n /** File attachments */\n attachments?: Attachment[];\n}\n\nexport interface SendEmailResponse {\n message_id: string;\n}\n\nexport interface BatchEmailResult {\n status: 'success' | 'error' | 'spam';\n message_id?: string;\n message?: string;\n errors?: Record<string, Record<string, string>>;\n}\n\nexport interface BatchEmailResponse {\n results: BatchEmailResult[];\n}\n\nexport interface Domain {\n domain_name: string;\n verification_status: 'pending' | 'verified' | 'failed';\n created_at: string;\n}\n\nexport interface AccountInfo {\n account: {\n title: string;\n plan_type: string;\n status: string;\n emails_usage_this_month: number;\n emails_sent_last_24hrs: number;\n };\n domains: Domain[];\n}\n\nexport interface ToSendErrorResponse {\n status_code: number;\n error_type: ErrorType;\n message: string;\n errors?: Record<string, Record<string, string>>;\n}\n\nexport type ErrorType =\n | 'bad_request'\n | 'unauthorized'\n | 'forbidden'\n | 'not_found'\n | 'validation_error'\n | 'rate_limit_exceeded'\n | 'internal_error';\n\nexport interface ToSendConfig {\n /** Your ToSend API key */\n apiKey: string;\n /** Custom base URL (optional) */\n baseUrl?: string;\n /** Request timeout in ms (default: 30000) */\n timeout?: number;\n}\n\n// ============================================================================\n// Error Class\n// ============================================================================\n\nexport class ToSendError extends Error {\n readonly code: number;\n readonly errorType: ErrorType;\n readonly errors: Record<string, Record<string, string>>;\n\n private static readonly ERROR_TYPE_MAP: Record<number, ErrorType> = {\n 400: 'bad_request',\n 401: 'unauthorized',\n 403: 'forbidden',\n 404: 'not_found',\n 422: 'validation_error',\n 429: 'rate_limit_exceeded',\n };\n\n constructor(\n message: string,\n code: number = 0,\n errors: Record<string, Record<string, string>> = {},\n errorType?: ErrorType\n ) {\n super(message);\n this.name = 'ToSendError';\n this.code = code;\n this.errors = errors;\n this.errorType = errorType ?? ToSendError.ERROR_TYPE_MAP[code] ?? 'internal_error';\n }\n\n get isValidationError(): boolean {\n return this.errorType === 'validation_error' || this.code === 422;\n }\n\n get isAuthenticationError(): boolean {\n return (\n this.errorType === 'unauthorized' ||\n this.errorType === 'forbidden' ||\n this.code === 401 ||\n this.code === 403\n );\n }\n\n get isRateLimitError(): boolean {\n return this.errorType === 'rate_limit_exceeded' || this.code === 429;\n }\n}\n\n// ============================================================================\n// Main Client\n// ============================================================================\n\nexport class ToSend {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(config: string | ToSendConfig) {\n if (typeof config === 'string') {\n this.apiKey = config;\n this.baseUrl = 'https://api.tosend.com';\n this.timeout = 30000;\n } else {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl?.replace(/\\/$/, '') ?? 'https://api.tosend.com';\n this.timeout = config.timeout ?? 30000;\n }\n\n if (!this.apiKey?.trim()) {\n throw new ToSendError('API key is required', 401);\n }\n }\n\n /**\n * Send a single email.\n *\n * @example\n * ```ts\n * const response = await tosend.send({\n * from: { email: 'hello@example.com', name: 'My App' },\n * to: [{ email: 'user@example.com' }],\n * subject: 'Hello!',\n * html: '<p>Welcome!</p>'\n * });\n * console.log(response.message_id);\n * ```\n */\n async send(params: SendEmailParams): Promise<SendEmailResponse> {\n this.validateEmailParams(params);\n return this.request<SendEmailResponse>('POST', '/v2/emails', params);\n }\n\n /**\n * Send multiple emails in a single request.\n *\n * @example\n * ```ts\n * const response = await tosend.batch([\n * {\n * from: { email: 'hello@example.com' },\n * to: [{ email: 'user1@example.com' }],\n * subject: 'Hello User 1',\n * html: '<p>Hi!</p>'\n * },\n * {\n * from: { email: 'hello@example.com' },\n * to: [{ email: 'user2@example.com' }],\n * subject: 'Hello User 2',\n * html: '<p>Hi!</p>'\n * }\n * ]);\n *\n * response.results.forEach(result => {\n * if (result.status === 'success') {\n * console.log('Sent:', result.message_id);\n * }\n * });\n * ```\n */\n async batch(emails: SendEmailParams[]): Promise<BatchEmailResponse> {\n if (!emails?.length) {\n throw new ToSendError('Emails array is required and cannot be empty', 422, {\n emails: { required: 'At least one email is required' },\n });\n }\n\n emails.forEach((email, index) => {\n try {\n this.validateEmailParams(email);\n } catch (error) {\n if (error instanceof ToSendError) {\n throw new ToSendError(\n `Email at index ${index}: ${error.message}`,\n error.code,\n error.errors\n );\n }\n throw error;\n }\n });\n\n return this.request<BatchEmailResponse>('POST', '/v2/emails/batch', { emails });\n }\n\n /**\n * Get account information and domains.\n *\n * @example\n * ```ts\n * const info = await tosend.getAccountInfo();\n * console.log(info.account.title);\n * console.log(info.account.emails_usage_this_month);\n * info.domains.forEach(d => console.log(d.domain_name, d.verification_status));\n * ```\n */\n async getAccountInfo(): Promise<AccountInfo> {\n return this.request<AccountInfo>('GET', '/v2/info');\n }\n\n // ==========================================================================\n // Private Methods\n // ==========================================================================\n\n private validateEmailParams(params: SendEmailParams): void {\n const errors: Record<string, Record<string, string>> = {};\n\n if (!params.from?.email) {\n errors.from = { required: 'From email is required' };\n } else if (!this.isValidEmail(params.from.email)) {\n errors.from = { invalid: 'From email is invalid' };\n }\n\n if (!params.to?.length) {\n errors.to = { required: 'To is required' };\n } else {\n const hasValidRecipient = params.to.some(\n (r) => r.email && this.isValidEmail(r.email)\n );\n if (!hasValidRecipient) {\n errors.to = { invalid: 'At least one valid recipient email is required' };\n }\n }\n\n if (!params.subject) {\n errors.subject = { required: 'Subject is required' };\n }\n\n if (!params.html && !params.text) {\n errors.content = { required: 'Either html or text content is required' };\n }\n\n if (Object.keys(errors).length > 0) {\n const firstError = Object.values(errors)[0];\n const message = Object.values(firstError)[0];\n throw new ToSendError(message, 422, errors);\n }\n }\n\n private isValidEmail(email: string): boolean {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);\n }\n\n private async request<T>(\n method: 'GET' | 'POST',\n endpoint: string,\n body?: unknown\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n const data = await response.json() as T & {\n message?: string;\n errors?: Record<string, Record<string, string>>;\n error_type?: ErrorType;\n };\n\n if (!response.ok) {\n throw new ToSendError(\n data.message ?? 'Unknown error',\n response.status,\n data.errors ?? {},\n data.error_type\n );\n }\n\n return data;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof ToSendError) {\n throw error;\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new ToSendError('Request timeout', 408);\n }\n throw new ToSendError(error.message);\n }\n\n throw new ToSendError('Unknown error');\n }\n }\n}\n\n// ============================================================================\n// Default Export\n// ============================================================================\n\nexport default ToSend;\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tosend",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Official Node.js SDK for the ToSend email API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",