sently 0.4.6 → 0.5.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.
Files changed (108) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/README.md +180 -43
  3. package/dist/adapters/bun.js +2 -183
  4. package/dist/adapters/bun.js.map +2 -2
  5. package/dist/adapters/cf.js +2 -77
  6. package/dist/adapters/cf.js.map +2 -2
  7. package/dist/adapters/deno.js +2 -72
  8. package/dist/adapters/deno.js.map +2 -2
  9. package/dist/adapters/node.js +2 -180
  10. package/dist/adapters/node.js.map +2 -2
  11. package/dist/auth/oauth2.js +2 -13
  12. package/dist/auth/oauth2.js.map +1 -1
  13. package/dist/chunk-32dj0v9g.js +5 -0
  14. package/dist/{chunk-794hc3m4.js.map → chunk-32dj0v9g.js.map} +2 -2
  15. package/dist/chunk-cvmk9h1r.js +4 -0
  16. package/dist/chunk-cvmk9h1r.js.map +10 -0
  17. package/dist/chunk-j5m37k1c.js +4 -0
  18. package/dist/{chunk-ym3zzv8b.js.map → chunk-j5m37k1c.js.map} +2 -2
  19. package/dist/chunk-kdqxhybf.js +4 -0
  20. package/dist/chunk-kdqxhybf.js.map +10 -0
  21. package/dist/chunk-m2njnxre.js +13 -0
  22. package/dist/{chunk-tymfm441.js.map → chunk-m2njnxre.js.map} +2 -2
  23. package/dist/chunk-nhec1319.js +5 -0
  24. package/dist/chunk-nhec1319.js.map +10 -0
  25. package/dist/chunk-nj3wmg69.js +3 -0
  26. package/dist/{chunk-7fqv71z1.js.map → chunk-nj3wmg69.js.map} +2 -2
  27. package/dist/chunk-ntqmn6pe.js +4 -0
  28. package/dist/chunk-ntqmn6pe.js.map +10 -0
  29. package/dist/chunk-pjzsvsm6.js +4 -0
  30. package/dist/chunk-pjzsvsm6.js.map +11 -0
  31. package/dist/chunk-rhade81v.js +4 -0
  32. package/dist/{chunk-v0bahtg2.js.map → chunk-rhade81v.js.map} +1 -1
  33. package/dist/chunk-zwm5bfa4.js +4 -0
  34. package/dist/chunk-zwm5bfa4.js.map +10 -0
  35. package/dist/core/idempotency-key.d.ts +6 -0
  36. package/dist/core/rate-limiter.d.ts +23 -0
  37. package/dist/core/smtp.js +2 -31
  38. package/dist/core/smtp.js.map +1 -1
  39. package/dist/core/types.d.ts +42 -0
  40. package/dist/detect.d.ts +2 -0
  41. package/dist/detect.js +2 -180
  42. package/dist/detect.js.map +4 -5
  43. package/dist/dkim.d.ts +21 -0
  44. package/dist/dkim.js +9 -0
  45. package/dist/dkim.js.map +10 -0
  46. package/dist/idempotency.d.ts +46 -0
  47. package/dist/idempotency.js +3 -0
  48. package/dist/idempotency.js.map +10 -0
  49. package/dist/index.d.ts +106 -16
  50. package/dist/index.js +115 -14
  51. package/dist/mailer.d.ts +17 -0
  52. package/dist/mailer.js +3 -0
  53. package/dist/mailer.js.map +9 -0
  54. package/dist/plugins/react.d.ts +35 -0
  55. package/dist/plugins/react.js +3 -0
  56. package/dist/plugins/react.js.map +10 -0
  57. package/dist/plugins/template.js +2 -28
  58. package/dist/plugins/template.js.map +2 -2
  59. package/dist/pool/pool.d.ts +1 -23
  60. package/dist/pool/pool.js +2 -16
  61. package/dist/pool/pool.js.map +5 -3
  62. package/dist/react.d.ts +20 -0
  63. package/dist/react.js +3 -0
  64. package/dist/react.js.map +9 -0
  65. package/dist/transports/brevo.js +2 -115
  66. package/dist/transports/brevo.js.map +2 -2
  67. package/dist/transports/mailgun.js +2 -119
  68. package/dist/transports/mailgun.js.map +2 -2
  69. package/dist/transports/postmark.js +2 -113
  70. package/dist/transports/postmark.js.map +2 -2
  71. package/dist/transports/preview.js +2 -72
  72. package/dist/transports/preview.js.map +2 -2
  73. package/dist/transports/resend.d.ts +16 -0
  74. package/dist/transports/resend.js +2 -109
  75. package/dist/transports/resend.js.map +3 -3
  76. package/dist/transports/retry.d.ts +2 -0
  77. package/dist/transports/retry.js +2 -78
  78. package/dist/transports/retry.js.map +3 -3
  79. package/dist/transports/sendgrid.d.ts +8 -0
  80. package/dist/transports/sendgrid.js +2 -132
  81. package/dist/transports/sendgrid.js.map +3 -3
  82. package/dist/transports/ses.js +5 -251
  83. package/dist/transports/ses.js.map +2 -2
  84. package/dist/transports/smtp.js +2 -26
  85. package/dist/transports/smtp.js.map +1 -1
  86. package/dist/webhooks/brevo.d.ts +3 -0
  87. package/dist/webhooks/mailgun.d.ts +13 -0
  88. package/dist/webhooks/postmark.d.ts +3 -0
  89. package/dist/webhooks/resend.d.ts +12 -0
  90. package/dist/webhooks/sendgrid.d.ts +3 -0
  91. package/dist/webhooks/ses.d.ts +6 -0
  92. package/dist/webhooks/timing-safe-equal.d.ts +9 -0
  93. package/dist/webhooks/types.d.ts +32 -0
  94. package/dist/webhooks.d.ts +26 -0
  95. package/dist/webhooks.js +3 -0
  96. package/dist/webhooks.js.map +9 -0
  97. package/package.json +45 -6
  98. package/dist/chunk-794hc3m4.js +0 -105
  99. package/dist/chunk-7fqv71z1.js +0 -251
  100. package/dist/chunk-f4c9ttmr.js +0 -154
  101. package/dist/chunk-f4c9ttmr.js.map +0 -11
  102. package/dist/chunk-mp5c9bfd.js +0 -270
  103. package/dist/chunk-mp5c9bfd.js.map +0 -11
  104. package/dist/chunk-tymfm441.js +0 -405
  105. package/dist/chunk-v0bahtg2.js +0 -6
  106. package/dist/chunk-x3szga4k.js +0 -367
  107. package/dist/chunk-x3szga4k.js.map +0 -11
  108. package/dist/chunk-ym3zzv8b.js +0 -74
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/transports/resend.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * @module\n * Resend HTTP API transport for sending email via api.resend.com.\n *\n * @example\n * ```ts\n * import { ResendTransport } from \"sently/transports/resend\";\n * import { createMailer } from \"sently\";\n *\n * const mailer = await createMailer({\n * transport: new ResendTransport({ apiKey: process.env.RESEND_API_KEY! }),\n * });\n *\n * await mailer.send({\n * from: \"onboarding@yourdomain.com\",\n * to: \"recipient@example.com\",\n * subject: \"Hello\",\n * html: \"<p>Sent via Resend</p>\",\n * });\n * ```\n */\nimport { extractEmails, parseAddresses, toMIMEHeader } from \"../core/address.js\";\nimport { encodeBase64 } from \"../core/base64.js\";\nimport type { MailOptions, SendResult, Transport, VerifyResult } from \"../core/types.js\";\nimport { resolveAttachments } from \"./resolve-attachments.js\";\n\n/** Resend API configuration. */\nexport interface ResendConfig {\n /** Resend API key (starts with `re_`). */\n apiKey: string;\n /** API base URL. Default: `https://api.resend.com`. */\n baseUrl?: string;\n}\n\n/** Error thrown when the Resend API returns a non-success response. */\nexport class ResendError extends Error {\n /** Creates a Resend API error with status code and response payload. */\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly apiError: unknown,\n ) {\n super(message);\n this.name = \"ResendError\";\n }\n}\n\n/**\n * Resend HTTP API transport.\n */\nexport class ResendTransport implements Transport {\n /** Resend API key for Bearer authentication. */\n private readonly apiKey: string;\n /** Resend API base URL. */\n private readonly baseUrl: string;\n\n /** Creates a Resend transport with the given API key. */\n constructor(config: ResendConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl ?? \"https://api.resend.com\";\n }\n\n /** Sends an email via the Resend HTTP API. */\n async send(options: MailOptions): Promise<SendResult> {\n const attachments = await resolveAttachments(options.attachments);\n const from = parseAddresses(options.from)[0];\n const body = {\n from: from ? toMIMEHeader(from) : \"\",\n to: extractEmails(options.to),\n subject: options.subject,\n ...(options.cc ? { cc: extractEmails(options.cc) } : {}),\n ...(options.bcc ? { bcc: extractEmails(options.bcc) } : {}),\n ...(options.replyTo ? { reply_to: extractEmails(options.replyTo) } : {}),\n ...(options.text ? { text: options.text } : {}),\n ...(options.html ? { html: options.html } : {}),\n ...(options.headers ? { headers: options.headers } : {}),\n ...(attachments.length > 0\n ? {\n attachments: attachments.map((att) => ({\n filename: att.filename,\n content:\n att.content instanceof Uint8Array\n ? encodeBase64(att.content).replace(/\\r\\n/g, \"\")\n : att.content,\n ...(att.contentType ? { content_type: att.contentType } : {}),\n })),\n }\n : {}),\n };\n\n const response = await fetch(`${this.baseUrl}/emails`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n\n const payload = (await response.json()) as { id?: string; message?: string };\n\n if (!response.ok) {\n throw new ResendError(payload.message ?? \"Resend API error\", response.status, payload);\n }\n\n const accepted = extractEmails(options.to);\n return {\n messageId: payload.id ?? options.messageId ?? \"\",\n accepted,\n rejected: [],\n response: payload.message ?? \"Email sent\",\n envelope: {\n from: from?.address ?? \"\",\n to: [\n ...extractEmails(options.to),\n ...(options.cc ? extractEmails(options.cc) : []),\n ...(options.bcc ? extractEmails(options.bcc) : []),\n ],\n },\n };\n }\n\n /** Verifies the Resend API key by listing domains. */\n async verify(): Promise<VerifyResult> {\n try {\n const response = await fetch(`${this.baseUrl}/domains`, {\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n },\n });\n\n if (!response.ok) {\n const payload = (await response.json().catch(() => ({}))) as { message?: string };\n return {\n ok: false,\n provider: \"resend\",\n message: payload.message ?? `HTTP ${response.status}`,\n };\n }\n\n return { ok: true, provider: \"resend\", message: \"API key is valid\" };\n } catch (err) {\n return {\n ok: false,\n provider: \"resend\",\n message: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n"
5
+ "/**\n * @module\n * Resend HTTP API transport for sending email via api.resend.com.\n *\n * @example\n * ```ts\n * import { ResendTransport } from \"sently/transports/resend\";\n * import { createMailer } from \"sently\";\n *\n * const mailer = await createMailer({\n * transport: new ResendTransport({ apiKey: process.env.RESEND_API_KEY! }),\n * });\n *\n * await mailer.send({\n * from: \"onboarding@yourdomain.com\",\n * to: \"recipient@example.com\",\n * subject: \"Hello\",\n * html: \"<p>Sent via Resend</p>\",\n * });\n * ```\n */\nimport { extractEmails, parseAddresses, toMIMEHeader } from \"../core/address.js\";\nimport { encodeBase64 } from \"../core/base64.js\";\nimport { resolveIdempotencyKey } from \"../core/idempotency-key.js\";\nimport { RateLimiter } from \"../core/rate-limiter.js\";\nimport type { MailOptions, SendResult, Transport, VerifyResult } from \"../core/types.js\";\nimport { resolveAttachments } from \"./resolve-attachments.js\";\n\n/** Resend API configuration. */\nexport interface ResendConfig {\n /** Resend API key (starts with `re_`). */\n apiKey: string;\n /** API base URL. Default: `https://api.resend.com`. */\n baseUrl?: string;\n /** Max batch HTTP requests per rate window. Default: `2` (Resend API limit). Set `0` to disable. */\n rateDelta?: number;\n /** Rate limit window in milliseconds. Default: `1000`. */\n rateLimit?: number;\n}\n\n/** Maximum messages per Resend batch request (overridable per account). */\nexport const RESEND_BATCH_MAX = 100;\n\n/** Error thrown when the Resend API returns a non-success response. */\nexport class ResendError extends Error {\n /** Creates a Resend API error with status code and response payload. */\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly apiError: unknown,\n ) {\n super(message);\n this.name = \"ResendError\";\n }\n}\n\n/**\n * Resend HTTP API transport.\n */\nexport class ResendTransport implements Transport {\n /** Resend API key for Bearer authentication. */\n private readonly apiKey: string;\n /** Resend API base URL. */\n private readonly baseUrl: string;\n /** Optional rate limiter for multi-chunk batch sends. */\n private readonly rateLimiter: RateLimiter | null;\n\n /** Maximum messages per batch HTTP request. */\n readonly batchMax = RESEND_BATCH_MAX;\n\n /** Creates a Resend transport with the given API key. */\n constructor(config: ResendConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl ?? \"https://api.resend.com\";\n\n const rateDelta = config.rateDelta ?? 2;\n if (rateDelta > 0) {\n this.rateLimiter = new RateLimiter(rateDelta, config.rateLimit ?? 1000);\n } else {\n this.rateLimiter = null;\n }\n }\n\n /** Build the JSON body for a single Resend email. */\n private async buildEmailBody(options: MailOptions): Promise<Record<string, unknown>> {\n const attachments = await resolveAttachments(options.attachments);\n const from = parseAddresses(options.from)[0];\n return {\n from: from ? toMIMEHeader(from) : \"\",\n to: extractEmails(options.to),\n subject: options.subject,\n ...(options.cc ? { cc: extractEmails(options.cc) } : {}),\n ...(options.bcc ? { bcc: extractEmails(options.bcc) } : {}),\n ...(options.replyTo ? { reply_to: extractEmails(options.replyTo) } : {}),\n ...(options.text ? { text: options.text } : {}),\n ...(options.html ? { html: options.html } : {}),\n ...(options.headers ? { headers: options.headers } : {}),\n ...(attachments.length > 0\n ? {\n attachments: attachments.map((att) => ({\n filename: att.filename,\n content:\n att.content instanceof Uint8Array\n ? encodeBase64(att.content).replace(/\\r\\n/g, \"\")\n : att.content,\n ...(att.contentType ? { content_type: att.contentType } : {}),\n })),\n }\n : {}),\n };\n }\n\n /** Map a Resend API response id to a normalized SendResult. */\n private toSendResult(\n options: MailOptions,\n payload: { id?: string; message?: string; batchError?: unknown },\n ): SendResult {\n const from = parseAddresses(options.from)[0];\n return {\n messageId: payload.id ?? options.messageId ?? \"\",\n accepted: extractEmails(options.to),\n rejected: [],\n response: payload.message ?? \"Email sent\",\n envelope: {\n from: from?.address ?? \"\",\n to: [\n ...extractEmails(options.to),\n ...(options.cc ? extractEmails(options.cc) : []),\n ...(options.bcc ? extractEmails(options.bcc) : []),\n ],\n },\n ...(payload.batchError !== undefined ? { batchError: payload.batchError } : {}),\n };\n }\n\n /** Sends an email via the Resend HTTP API. */\n async send(options: MailOptions): Promise<SendResult> {\n const body = await this.buildEmailBody(options);\n const idempotencyKey = resolveIdempotencyKey(options);\n\n const response = await fetch(`${this.baseUrl}/emails`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n ...(idempotencyKey ? { \"Idempotency-Key\": idempotencyKey } : {}),\n },\n body: JSON.stringify(body),\n });\n\n const payload = (await response.json()) as { id?: string; message?: string };\n\n if (!response.ok) {\n throw new ResendError(payload.message ?? \"Resend API error\", response.status, payload);\n }\n\n return this.toSendResult(options, payload);\n }\n\n /** Send up to {@link RESEND_BATCH_MAX} attachment-free messages per batch request. */\n async sendBatch(messages: MailOptions[]): Promise<SendResult[]> {\n if (messages.length === 0) {\n return [];\n }\n\n const results: SendResult[] = [];\n for (let offset = 0; offset < messages.length; offset += RESEND_BATCH_MAX) {\n if (offset > 0 && this.rateLimiter) {\n await this.rateLimiter.acquire();\n }\n\n const chunk = messages.slice(offset, offset + RESEND_BATCH_MAX);\n const bodies = await Promise.all(chunk.map((message) => this.buildEmailBody(message)));\n\n const response = await fetch(`${this.baseUrl}/emails/batch`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(bodies),\n });\n\n const payload = (await response.json()) as {\n data?: Array<{ id?: string; error?: string }>;\n message?: string;\n };\n\n if (!response.ok) {\n throw new ResendError(\n payload.message ?? \"Resend batch API error\",\n response.status,\n payload,\n );\n }\n\n const ids = payload.data ?? [];\n for (let i = 0; i < chunk.length; i++) {\n const message = chunk[i] as MailOptions;\n const item = ids[i];\n if (item?.id !== undefined) {\n results.push(\n this.toSendResult(message, {\n id: item.id,\n ...(payload.message !== undefined ? { message: payload.message } : {}),\n }),\n );\n continue;\n }\n\n const errorMessage = item?.error ?? \"Batch item failed\";\n results.push(\n this.toSendResult(message, {\n message: errorMessage,\n batchError: new ResendError(errorMessage, response.status, item ?? {}),\n }),\n );\n }\n }\n\n return results;\n }\n\n /** Verifies the Resend API key by listing domains. */\n async verify(): Promise<VerifyResult> {\n try {\n const response = await fetch(`${this.baseUrl}/domains`, {\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n },\n });\n\n if (!response.ok) {\n const payload = (await response.json().catch(() => ({}))) as { message?: string };\n return {\n ok: false,\n provider: \"resend\",\n message: payload.message ?? `HTTP ${response.status}`,\n };\n }\n\n return { ok: true, provider: \"resend\", message: \"API key is valid\" };\n } catch (err) {\n return {\n ok: false,\n provider: \"resend\",\n message: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "C97D4F9F26828E0A64756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "8E2BC77BDE920DD964756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -29,4 +29,6 @@ export declare class RetryTransport implements Transport {
29
29
  verify(): Promise<VerifyResult>;
30
30
  /** Delegates close to the inner transport if available. */
31
31
  close(): Promise<void>;
32
+ /** Delegates batch sends to the inner transport when available. */
33
+ sendBatch(messages: MailOptions[]): Promise<SendResult[]>;
32
34
  }
@@ -1,79 +1,3 @@
1
- import {
2
- SMTPError
3
- } from "../chunk-tymfm441.js";
4
- import"../chunk-794hc3m4.js";
5
- import"../chunk-v0bahtg2.js";
1
+ import{v as G}from"../chunk-m2njnxre.js";import"../chunk-32dj0v9g.js";import"../chunk-rhade81v.js";var H=[429,500,502,503,504];function I(q,x,z){if(x==="exponential")return z*2**(q-1);if(x==="linear")return z*q;return z}function J(q,x){if(q instanceof G&&q.code===535)return!1;if(typeof q==="object"&&q!==null&&"statusCode"in q&&typeof q.statusCode==="number")return x.includes(q.statusCode);return!0}class K{inner;_sleep;maxAttempts;backoff;baseDelay;retryOn;onRetry;constructor(q,x,z=(B)=>new Promise((C)=>setTimeout(C,B))){this.inner=q;this._sleep=z;this.maxAttempts=x?.maxAttempts??3,this.backoff=x?.backoff??"exponential",this.baseDelay=x?.baseDelay??1000,this.retryOn=x?.retryOn??H,this.onRetry=x?.onRetry}async send(q){let x;for(let z=1;z<=this.maxAttempts;z++)try{return await this.inner.send(q)}catch(B){if(x=B,z===this.maxAttempts)throw B;if(!J(B,this.retryOn))throw B;let C=I(z,this.backoff,this.baseDelay);this.onRetry?.(z,B),await this._sleep(C)}throw x}async verify(){if(this.inner.verify)return this.inner.verify();return{ok:!0,provider:"retry"}}async close(){await this.inner.close?.()}async sendBatch(q){if(this.inner.sendBatch)return this.inner.sendBatch(q);return Promise.all(q.map((x)=>this.send(x)))}}export{K as RetryTransport};
6
2
 
7
- // src/transports/retry.ts
8
- var DEFAULT_RETRY_ON = [429, 500, 502, 503, 504];
9
- function computeDelay(attempt, backoff, base) {
10
- if (backoff === "exponential") {
11
- return base * 2 ** (attempt - 1);
12
- }
13
- if (backoff === "linear") {
14
- return base * attempt;
15
- }
16
- return base;
17
- }
18
- function shouldRetry(err, retryOn) {
19
- if (err instanceof SMTPError && err.code === 535) {
20
- return false;
21
- }
22
- if (typeof err === "object" && err !== null && "statusCode" in err && typeof err.statusCode === "number") {
23
- return retryOn.includes(err.statusCode);
24
- }
25
- return true;
26
- }
27
-
28
- class RetryTransport {
29
- inner;
30
- _sleep;
31
- maxAttempts;
32
- backoff;
33
- baseDelay;
34
- retryOn;
35
- onRetry;
36
- constructor(inner, config, _sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))) {
37
- this.inner = inner;
38
- this._sleep = _sleep;
39
- this.maxAttempts = config?.maxAttempts ?? 3;
40
- this.backoff = config?.backoff ?? "exponential";
41
- this.baseDelay = config?.baseDelay ?? 1000;
42
- this.retryOn = config?.retryOn ?? DEFAULT_RETRY_ON;
43
- this.onRetry = config?.onRetry;
44
- }
45
- async send(options) {
46
- let lastError;
47
- for (let attempt = 1;attempt <= this.maxAttempts; attempt++) {
48
- try {
49
- return await this.inner.send(options);
50
- } catch (err) {
51
- lastError = err;
52
- if (attempt === this.maxAttempts) {
53
- throw err;
54
- }
55
- if (!shouldRetry(err, this.retryOn)) {
56
- throw err;
57
- }
58
- const delay = computeDelay(attempt, this.backoff, this.baseDelay);
59
- this.onRetry?.(attempt, err);
60
- await this._sleep(delay);
61
- }
62
- }
63
- throw lastError;
64
- }
65
- async verify() {
66
- if (this.inner.verify) {
67
- return this.inner.verify();
68
- }
69
- return { ok: true, provider: "retry" };
70
- }
71
- async close() {
72
- await this.inner.close?.();
73
- }
74
- }
75
- export {
76
- RetryTransport
77
- };
78
-
79
- //# debugId=F5AD32E7B75CAE2A64756E2164756E21
3
+ //# debugId=EA36BC4991ED6EAB64756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/transports/retry.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * @module\n * RetryTransport — decorator that wraps any sently transport\n * and retries failed sends with configurable backoff.\n * Works with SMTP, Resend, SendGrid, SES, and any custom transport.\n *\n * @example\n * ```ts\n * import { RetryTransport } from 'sently/transports/retry'\n * import { ResendTransport } from 'sently/transports/resend'\n *\n * const transport = new RetryTransport(\n * new ResendTransport({ apiKey }),\n * { maxAttempts: 3, backoff: 'exponential', retryOn: [429, 503] }\n * )\n * ```\n */\nimport { SMTPError } from \"../core/smtp.js\";\nimport type {\n MailOptions,\n RetryConfig,\n SendResult,\n Transport,\n VerifyResult,\n} from \"../core/types.js\";\n\nconst DEFAULT_RETRY_ON = [429, 500, 502, 503, 504];\n\nfunction computeDelay(attempt: number, backoff: string, base: number): number {\n if (backoff === \"exponential\") {\n return base * 2 ** (attempt - 1);\n }\n if (backoff === \"linear\") {\n return base * attempt;\n }\n return base;\n}\n\nfunction shouldRetry(err: unknown, retryOn: number[]): boolean {\n if (err instanceof SMTPError && err.code === 535) {\n return false;\n }\n\n if (\n typeof err === \"object\" &&\n err !== null &&\n \"statusCode\" in err &&\n typeof (err as { statusCode: unknown }).statusCode === \"number\"\n ) {\n return retryOn.includes((err as { statusCode: number }).statusCode);\n }\n\n return true;\n}\n\n/**\n * Decorator transport that retries failed sends with configurable backoff.\n */\nexport class RetryTransport implements Transport {\n /** Maximum send attempts including the initial try. */\n private readonly maxAttempts: number;\n /** Backoff strategy between retries. */\n private readonly backoff: \"exponential\" | \"linear\" | \"fixed\";\n /** Base delay in milliseconds before the first retry. */\n private readonly baseDelay: number;\n /** HTTP status codes that trigger a retry. */\n private readonly retryOn: number[];\n /** Optional callback invoked before each retry attempt. */\n private readonly onRetry: RetryConfig[\"onRetry\"];\n\n /** Wraps an inner transport with retry logic and optional backoff configuration. */\n constructor(\n /** Transport that performs the actual send on each attempt. */\n private readonly inner: Transport,\n config?: RetryConfig,\n /** Injectable sleep function for testing backoff timing. */\n private readonly _sleep: (ms: number) => Promise<void> = (ms) =>\n new Promise((resolve) => setTimeout(resolve, ms)),\n ) {\n this.maxAttempts = config?.maxAttempts ?? 3;\n this.backoff = config?.backoff ?? \"exponential\";\n this.baseDelay = config?.baseDelay ?? 1000;\n this.retryOn = config?.retryOn ?? DEFAULT_RETRY_ON;\n this.onRetry = config?.onRetry;\n }\n\n /** Sends with retries according to configured backoff and retry rules. */\n async send(options: MailOptions): Promise<SendResult> {\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {\n try {\n return await this.inner.send(options);\n } catch (err) {\n lastError = err;\n if (attempt === this.maxAttempts) {\n throw err;\n }\n if (!shouldRetry(err, this.retryOn)) {\n throw err;\n }\n const delay = computeDelay(attempt, this.backoff, this.baseDelay);\n this.onRetry?.(attempt, err);\n await this._sleep(delay);\n }\n }\n\n throw lastError;\n }\n\n /** Delegates to the inner transport verify or returns a default success result. */\n async verify(): Promise<VerifyResult> {\n if (this.inner.verify) {\n return this.inner.verify();\n }\n return { ok: true, provider: \"retry\" };\n }\n\n /** Delegates close to the inner transport if available. */\n async close(): Promise<void> {\n await this.inner.close?.();\n }\n}\n"
5
+ "/**\n * @module\n * RetryTransport — decorator that wraps any sently transport\n * and retries failed sends with configurable backoff.\n * Works with SMTP, Resend, SendGrid, SES, and any custom transport.\n *\n * @example\n * ```ts\n * import { RetryTransport } from 'sently/transports/retry'\n * import { ResendTransport } from 'sently/transports/resend'\n *\n * const transport = new RetryTransport(\n * new ResendTransport({ apiKey }),\n * { maxAttempts: 3, backoff: 'exponential', retryOn: [429, 503] }\n * )\n * ```\n */\nimport { SMTPError } from \"../core/smtp.js\";\nimport type {\n MailOptions,\n RetryConfig,\n SendResult,\n Transport,\n VerifyResult,\n} from \"../core/types.js\";\n\nconst DEFAULT_RETRY_ON = [429, 500, 502, 503, 504];\n\nfunction computeDelay(attempt: number, backoff: string, base: number): number {\n if (backoff === \"exponential\") {\n return base * 2 ** (attempt - 1);\n }\n if (backoff === \"linear\") {\n return base * attempt;\n }\n return base;\n}\n\nfunction shouldRetry(err: unknown, retryOn: number[]): boolean {\n if (err instanceof SMTPError && err.code === 535) {\n return false;\n }\n\n if (\n typeof err === \"object\" &&\n err !== null &&\n \"statusCode\" in err &&\n typeof (err as { statusCode: unknown }).statusCode === \"number\"\n ) {\n return retryOn.includes((err as { statusCode: number }).statusCode);\n }\n\n return true;\n}\n\n/**\n * Decorator transport that retries failed sends with configurable backoff.\n */\nexport class RetryTransport implements Transport {\n /** Maximum send attempts including the initial try. */\n private readonly maxAttempts: number;\n /** Backoff strategy between retries. */\n private readonly backoff: \"exponential\" | \"linear\" | \"fixed\";\n /** Base delay in milliseconds before the first retry. */\n private readonly baseDelay: number;\n /** HTTP status codes that trigger a retry. */\n private readonly retryOn: number[];\n /** Optional callback invoked before each retry attempt. */\n private readonly onRetry: RetryConfig[\"onRetry\"];\n\n /** Wraps an inner transport with retry logic and optional backoff configuration. */\n constructor(\n /** Transport that performs the actual send on each attempt. */\n private readonly inner: Transport,\n config?: RetryConfig,\n /** Injectable sleep function for testing backoff timing. */\n private readonly _sleep: (ms: number) => Promise<void> = (ms) =>\n new Promise((resolve) => setTimeout(resolve, ms)),\n ) {\n this.maxAttempts = config?.maxAttempts ?? 3;\n this.backoff = config?.backoff ?? \"exponential\";\n this.baseDelay = config?.baseDelay ?? 1000;\n this.retryOn = config?.retryOn ?? DEFAULT_RETRY_ON;\n this.onRetry = config?.onRetry;\n }\n\n /** Sends with retries according to configured backoff and retry rules. */\n async send(options: MailOptions): Promise<SendResult> {\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {\n try {\n return await this.inner.send(options);\n } catch (err) {\n lastError = err;\n if (attempt === this.maxAttempts) {\n throw err;\n }\n if (!shouldRetry(err, this.retryOn)) {\n throw err;\n }\n const delay = computeDelay(attempt, this.backoff, this.baseDelay);\n this.onRetry?.(attempt, err);\n await this._sleep(delay);\n }\n }\n\n throw lastError;\n }\n\n /** Delegates to the inner transport verify or returns a default success result. */\n async verify(): Promise<VerifyResult> {\n if (this.inner.verify) {\n return this.inner.verify();\n }\n return { ok: true, provider: \"retry\" };\n }\n\n /** Delegates close to the inner transport if available. */\n async close(): Promise<void> {\n await this.inner.close?.();\n }\n\n /** Delegates batch sends to the inner transport when available. */\n async sendBatch(messages: MailOptions[]): Promise<SendResult[]> {\n if (this.inner.sendBatch) {\n return this.inner.sendBatch(messages);\n }\n return Promise.all(messages.map((message) => this.send(message)));\n }\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;AA0BA,IAAM,mBAAmB,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG;AAEjD,SAAS,YAAY,CAAC,SAAiB,SAAiB,MAAsB;AAAA,EAC5E,IAAI,YAAY,eAAe;AAAA,IAC7B,OAAO,OAAO,MAAM,UAAU;AAAA,EAChC;AAAA,EACA,IAAI,YAAY,UAAU;AAAA,IACxB,OAAO,OAAO;AAAA,EAChB;AAAA,EACA,OAAO;AAAA;AAGT,SAAS,WAAW,CAAC,KAAc,SAA4B;AAAA,EAC7D,IAAI,eAAe,aAAa,IAAI,SAAS,KAAK;AAAA,IAChD,OAAO;AAAA,EACT;AAAA,EAEA,IACE,OAAO,QAAQ,YACf,QAAQ,QACR,gBAAgB,OAChB,OAAQ,IAAgC,eAAe,UACvD;AAAA,IACA,OAAO,QAAQ,SAAU,IAA+B,UAAU;AAAA,EACpE;AAAA,EAEA,OAAO;AAAA;AAAA;AAMF,MAAM,eAAoC;AAAA,EAe5B;AAAA,EAGA;AAAA,EAhBF;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,EAGjB,WAAW,CAEQ,OACjB,QAEiB,SAAwC,CAAC,OACxD,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC,GAClD;AAAA,IALiB;AAAA,IAGA;AAAA,IAGjB,KAAK,cAAc,QAAQ,eAAe;AAAA,IAC1C,KAAK,UAAU,QAAQ,WAAW;AAAA,IAClC,KAAK,YAAY,QAAQ,aAAa;AAAA,IACtC,KAAK,UAAU,QAAQ,WAAW;AAAA,IAClC,KAAK,UAAU,QAAQ;AAAA;AAAA,OAInB,KAAI,CAAC,SAA2C;AAAA,IACpD,IAAI;AAAA,IAEJ,SAAS,UAAU,EAAG,WAAW,KAAK,aAAa,WAAW;AAAA,MAC5D,IAAI;AAAA,QACF,OAAO,MAAM,KAAK,MAAM,KAAK,OAAO;AAAA,QACpC,OAAO,KAAK;AAAA,QACZ,YAAY;AAAA,QACZ,IAAI,YAAY,KAAK,aAAa;AAAA,UAChC,MAAM;AAAA,QACR;AAAA,QACA,IAAI,CAAC,YAAY,KAAK,KAAK,OAAO,GAAG;AAAA,UACnC,MAAM;AAAA,QACR;AAAA,QACA,MAAM,QAAQ,aAAa,SAAS,KAAK,SAAS,KAAK,SAAS;AAAA,QAChE,KAAK,UAAU,SAAS,GAAG;AAAA,QAC3B,MAAM,KAAK,OAAO,KAAK;AAAA;AAAA,IAE3B;AAAA,IAEA,MAAM;AAAA;AAAA,OAIF,OAAM,GAA0B;AAAA,IACpC,IAAI,KAAK,MAAM,QAAQ;AAAA,MACrB,OAAO,KAAK,MAAM,OAAO;AAAA,IAC3B;AAAA,IACA,OAAO,EAAE,IAAI,MAAM,UAAU,QAAQ;AAAA;AAAA,OAIjC,MAAK,GAAkB;AAAA,IAC3B,MAAM,KAAK,MAAM,QAAQ;AAAA;AAE7B;",
8
- "debugId": "F5AD32E7B75CAE2A64756E2164756E21",
7
+ "mappings": "6GA0BA,DAAM,HAAmB,CAAC,IAAK,IAAK,IAAK,IAAK,GAAG,EAEjD,SAAS,CAAY,CAAC,EAAiB,EAAiB,EAAsB,CAC5E,GAAI,IAAY,cACd,OAAO,EAAO,IAAM,EAAU,GAEhC,GAAI,IAAY,SACd,OAAO,EAAO,EAEhB,OAAO,EAGT,SAAS,CAAW,CAAC,EAAc,EAA4B,CAC7D,GAAI,aAAe,GAAa,EAAI,OAAS,IAC3C,MAAO,GAGT,GACE,OAAO,IAAQ,UACf,IAAQ,MACR,eAAgB,GAChB,OAAQ,EAAgC,aAAe,SAEvD,OAAO,EAAQ,SAAU,EAA+B,UAAU,EAGpE,MAAO,GAMF,MAAM,CAAoC,CAe5B,MAGA,OAhBF,YAEA,QAEA,UAEA,QAEA,QAGjB,WAAW,CAEQ,EACjB,EAEiB,EAAwC,CAAC,IACxD,IAAI,QAAQ,CAAC,IAAY,WAAW,EAAS,CAAE,CAAC,EAClD,CALiB,aAGA,cAGjB,KAAK,YAAc,GAAQ,aAAe,EAC1C,KAAK,QAAU,GAAQ,SAAW,cAClC,KAAK,UAAY,GAAQ,WAAa,KACtC,KAAK,QAAU,GAAQ,SAAW,EAClC,KAAK,QAAU,GAAQ,aAInB,KAAI,CAAC,EAA2C,CACpD,IAAI,EAEJ,QAAS,EAAU,EAAG,GAAW,KAAK,YAAa,IACjD,GAAI,CACF,OAAO,MAAM,KAAK,MAAM,KAAK,CAAO,EACpC,MAAO,EAAK,CAEZ,GADA,EAAY,EACR,IAAY,KAAK,YACnB,MAAM,EAER,GAAI,CAAC,EAAY,EAAK,KAAK,OAAO,EAChC,MAAM,EAER,IAAM,EAAQ,EAAa,EAAS,KAAK,QAAS,KAAK,SAAS,EAChE,KAAK,UAAU,EAAS,CAAG,EAC3B,MAAM,KAAK,OAAO,CAAK,EAI3B,MAAM,OAIF,OAAM,EAA0B,CACpC,GAAI,KAAK,MAAM,OACb,OAAO,KAAK,MAAM,OAAO,EAE3B,MAAO,CAAE,GAAI,GAAM,SAAU,OAAQ,OAIjC,MAAK,EAAkB,CAC3B,MAAM,KAAK,MAAM,QAAQ,OAIrB,UAAS,CAAC,EAAgD,CAC9D,GAAI,KAAK,MAAM,UACb,OAAO,KAAK,MAAM,UAAU,CAAQ,EAEtC,OAAO,QAAQ,IAAI,EAAS,IAAI,CAAC,IAAY,KAAK,KAAK,CAAO,CAAC,CAAC,EAEpE",
8
+ "debugId": "EA36BC4991ED6EAB64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -19,8 +19,16 @@ export declare class SendGridTransport implements Transport {
19
19
  private readonly apiKey;
20
20
  /** Creates a SendGrid transport with the given API key. */
21
21
  constructor(config: SendGridConfig);
22
+ /** Build a SendGrid personalization for one message. */
23
+ private buildPersonalization;
24
+ /** Build SendGrid content parts from text/html options. */
25
+ private buildContent;
26
+ /** Map a SendGrid response to a normalized SendResult for one message. */
27
+ private toSendResult;
22
28
  /** Sends an email via the SendGrid v3 HTTP API. */
23
29
  send(options: MailOptions): Promise<SendResult>;
30
+ /** Send multiple messages in one request using SendGrid personalizations. */
31
+ sendBatch(messages: MailOptions[]): Promise<SendResult[]>;
24
32
  /** Verifies the SendGrid API key by fetching the user profile. */
25
33
  verify(): Promise<VerifyResult>;
26
34
  }
@@ -1,133 +1,3 @@
1
- import {
2
- extractEmails,
3
- parseAddresses,
4
- resolveAttachments
5
- } from "../chunk-f4c9ttmr.js";
6
- import {
7
- encodeBase64
8
- } from "../chunk-794hc3m4.js";
9
- import"../chunk-v0bahtg2.js";
1
+ import{l as N}from"../chunk-cvmk9h1r.js";import{n as F,p as J}from"../chunk-kdqxhybf.js";import{G as M}from"../chunk-32dj0v9g.js";import"../chunk-rhade81v.js";class L extends Error{statusCode;apiError;constructor(q,z,C){super(q);this.statusCode=z;this.apiError=C;this.name="SendGridError"}}class O{apiKey;constructor(q){this.apiKey=q.apiKey}buildPersonalization(q){return{to:F(q.to).map((z)=>({email:z.address,name:z.name})),...q.cc?{cc:F(q.cc).map((z)=>({email:z.address,name:z.name}))}:{},...q.bcc?{bcc:F(q.bcc).map((z)=>({email:z.address,name:z.name}))}:{},subject:q.subject,...q.headers?{headers:q.headers}:{}}}buildContent(q){return[...q.text?[{type:"text/plain",value:q.text}]:[],...q.html?[{type:"text/html",value:q.html}]:[]]}toSendResult(q,z,C="Accepted"){let H=F(q.from)[0];return{messageId:z,accepted:J(q.to),rejected:[],response:C,envelope:{from:H?.address??"",to:[...J(q.to),...q.cc?J(q.cc):[],...q.bcc?J(q.bcc):[]]}}}async send(q){let z=await N(q.attachments),C=F(q.from)[0],H={personalizations:[this.buildPersonalization(q)],from:C?{email:C.address,...C.name?{name:C.name}:{}}:{email:""},...q.replyTo?{reply_to:F(q.replyTo).map((w)=>({email:w.address,name:w.name}))[0]}:{},content:this.buildContent(q),...z.length>0?{attachments:z.map((w)=>({filename:w.filename,type:w.contentType??"application/octet-stream",content:w.content instanceof Uint8Array?M(w.content).replace(/\r\n/g,""):w.content,...w.contentId?{content_id:w.contentId}:{},disposition:w.inline?"inline":"attachment"}))}:{}},D=await fetch("https://api.sendgrid.com/v3/mail/send",{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify(H)});if(!D.ok){let w=await D.text();throw new L("SendGrid API error",D.status,w)}let K=D.headers.get("x-message-id")??q.messageId??"";return this.toSendResult(q,K)}async sendBatch(q){if(q.length===0)return[];let z=q[0],C=F(z.from)[0],H={personalizations:q.map((w)=>this.buildPersonalization(w)),from:C?{email:C.address,...C.name?{name:C.name}:{}}:{email:""},...z.replyTo?{reply_to:F(z.replyTo).map((w)=>({email:w.address,name:w.name}))[0]}:{},content:this.buildContent(z)},D=await fetch("https://api.sendgrid.com/v3/mail/send",{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify(H)});if(!D.ok){let w=await D.text();throw new L("SendGrid API error",D.status,w)}let K=D.headers.get("x-message-id")??"";return q.map((w)=>this.toSendResult(w,K||w.messageId||""))}async verify(){try{let q=await fetch("https://api.sendgrid.com/v3/user/profile",{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!q.ok)return{ok:!1,provider:"sendgrid",message:await q.text().catch(()=>"")||`HTTP ${q.status}`};let z=await q.json();return{ok:!0,provider:"sendgrid",...z.username?{message:z.username}:{}}}catch(q){return{ok:!1,provider:"sendgrid",message:q instanceof Error?q.message:String(q)}}}}export{O as SendGridTransport,L as SendGridError};
10
2
 
11
- // src/transports/sendgrid.ts
12
- class SendGridError extends Error {
13
- statusCode;
14
- apiError;
15
- constructor(message, statusCode, apiError) {
16
- super(message);
17
- this.statusCode = statusCode;
18
- this.apiError = apiError;
19
- this.name = "SendGridError";
20
- }
21
- }
22
-
23
- class SendGridTransport {
24
- apiKey;
25
- constructor(config) {
26
- this.apiKey = config.apiKey;
27
- }
28
- async send(options) {
29
- const attachments = await resolveAttachments(options.attachments);
30
- const from = parseAddresses(options.from)[0];
31
- const personalization = {
32
- to: parseAddresses(options.to).map((addr) => ({ email: addr.address, name: addr.name })),
33
- ...options.cc ? {
34
- cc: parseAddresses(options.cc).map((addr) => ({
35
- email: addr.address,
36
- name: addr.name
37
- }))
38
- } : {},
39
- ...options.bcc ? {
40
- bcc: parseAddresses(options.bcc).map((addr) => ({
41
- email: addr.address,
42
- name: addr.name
43
- }))
44
- } : {}
45
- };
46
- const body = {
47
- personalizations: [personalization],
48
- from: from ? { email: from.address, ...from.name ? { name: from.name } : {} } : { email: "" },
49
- subject: options.subject,
50
- ...options.replyTo ? {
51
- reply_to: parseAddresses(options.replyTo).map((addr) => ({
52
- email: addr.address,
53
- name: addr.name
54
- }))[0]
55
- } : {},
56
- content: [
57
- ...options.text ? [{ type: "text/plain", value: options.text }] : [],
58
- ...options.html ? [{ type: "text/html", value: options.html }] : []
59
- ],
60
- ...attachments.length > 0 ? {
61
- attachments: attachments.map((att) => ({
62
- filename: att.filename,
63
- type: att.contentType ?? "application/octet-stream",
64
- content: att.content instanceof Uint8Array ? encodeBase64(att.content).replace(/\r\n/g, "") : att.content,
65
- ...att.contentId ? { content_id: att.contentId } : {},
66
- disposition: att.inline ? "inline" : "attachment"
67
- }))
68
- } : {}
69
- };
70
- const response = await fetch("https://api.sendgrid.com/v3/mail/send", {
71
- method: "POST",
72
- headers: {
73
- Authorization: `Bearer ${this.apiKey}`,
74
- "Content-Type": "application/json"
75
- },
76
- body: JSON.stringify(body)
77
- });
78
- if (!response.ok) {
79
- const apiError = await response.text();
80
- throw new SendGridError("SendGrid API error", response.status, apiError);
81
- }
82
- const messageId = response.headers.get("x-message-id") ?? options.messageId ?? "";
83
- return {
84
- messageId,
85
- accepted: extractEmails(options.to),
86
- rejected: [],
87
- response: "Accepted",
88
- envelope: {
89
- from: from?.address ?? "",
90
- to: [
91
- ...extractEmails(options.to),
92
- ...options.cc ? extractEmails(options.cc) : [],
93
- ...options.bcc ? extractEmails(options.bcc) : []
94
- ]
95
- }
96
- };
97
- }
98
- async verify() {
99
- try {
100
- const response = await fetch("https://api.sendgrid.com/v3/user/profile", {
101
- headers: {
102
- Authorization: `Bearer ${this.apiKey}`
103
- }
104
- });
105
- if (!response.ok) {
106
- const apiError = await response.text().catch(() => "");
107
- return {
108
- ok: false,
109
- provider: "sendgrid",
110
- message: apiError || `HTTP ${response.status}`
111
- };
112
- }
113
- const payload = await response.json();
114
- return {
115
- ok: true,
116
- provider: "sendgrid",
117
- ...payload.username ? { message: payload.username } : {}
118
- };
119
- } catch (err) {
120
- return {
121
- ok: false,
122
- provider: "sendgrid",
123
- message: err instanceof Error ? err.message : String(err)
124
- };
125
- }
126
- }
127
- }
128
- export {
129
- SendGridTransport,
130
- SendGridError
131
- };
132
-
133
- //# debugId=53D65F527A73629564756E2164756E21
3
+ //# debugId=86CABED9282C733164756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/transports/sendgrid.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * @module\n * SendGrid v3 HTTP API transport for sending email via api.sendgrid.com.\n *\n * @example\n * ```ts\n * import { SendGridTransport } from \"sently/transports/sendgrid\";\n * import { createMailer } from \"sently\";\n *\n * const mailer = await createMailer({\n * transport: new SendGridTransport({ apiKey: process.env.SENDGRID_API_KEY! }),\n * });\n *\n * await mailer.send({\n * from: \"sender@example.com\",\n * to: \"recipient@example.com\",\n * subject: \"Hello\",\n * text: \"Plain text body\",\n * });\n * ```\n */\nimport { extractEmails, parseAddresses } from \"../core/address.js\";\nimport { encodeBase64 } from \"../core/base64.js\";\nimport type { MailOptions, SendResult, Transport, VerifyResult } from \"../core/types.js\";\nimport { resolveAttachments } from \"./resolve-attachments.js\";\n\n/** SendGrid API configuration. */\nexport interface SendGridConfig {\n /** SendGrid API key (Bearer token). */\n apiKey: string;\n}\n\n/** Error thrown when the SendGrid API returns a non-success response. */\nexport class SendGridError extends Error {\n /** Creates a SendGrid API error with status code and response payload. */\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly apiError: unknown,\n ) {\n super(message);\n this.name = \"SendGridError\";\n }\n}\n\n/**\n * SendGrid v3 HTTP API transport.\n */\nexport class SendGridTransport implements Transport {\n /** SendGrid API key for Bearer authentication. */\n private readonly apiKey: string;\n\n /** Creates a SendGrid transport with the given API key. */\n constructor(config: SendGridConfig) {\n this.apiKey = config.apiKey;\n }\n\n /** Sends an email via the SendGrid v3 HTTP API. */\n async send(options: MailOptions): Promise<SendResult> {\n const attachments = await resolveAttachments(options.attachments);\n const from = parseAddresses(options.from)[0];\n\n const personalization = {\n to: parseAddresses(options.to).map((addr) => ({ email: addr.address, name: addr.name })),\n ...(options.cc\n ? {\n cc: parseAddresses(options.cc).map((addr) => ({\n email: addr.address,\n name: addr.name,\n })),\n }\n : {}),\n ...(options.bcc\n ? {\n bcc: parseAddresses(options.bcc).map((addr) => ({\n email: addr.address,\n name: addr.name,\n })),\n }\n : {}),\n };\n\n const body = {\n personalizations: [personalization],\n from: from\n ? { email: from.address, ...(from.name ? { name: from.name } : {}) }\n : { email: \"\" },\n subject: options.subject,\n ...(options.replyTo\n ? {\n reply_to: parseAddresses(options.replyTo).map((addr) => ({\n email: addr.address,\n name: addr.name,\n }))[0],\n }\n : {}),\n content: [\n ...(options.text ? [{ type: \"text/plain\", value: options.text }] : []),\n ...(options.html ? [{ type: \"text/html\", value: options.html }] : []),\n ],\n ...(attachments.length > 0\n ? {\n attachments: attachments.map((att) => ({\n filename: att.filename,\n type: att.contentType ?? \"application/octet-stream\",\n content:\n att.content instanceof Uint8Array\n ? encodeBase64(att.content).replace(/\\r\\n/g, \"\")\n : att.content,\n ...(att.contentId ? { content_id: att.contentId } : {}),\n disposition: att.inline ? \"inline\" : \"attachment\",\n })),\n }\n : {}),\n };\n\n const response = await fetch(\"https://api.sendgrid.com/v3/mail/send\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const apiError = await response.text();\n throw new SendGridError(\"SendGrid API error\", response.status, apiError);\n }\n\n const messageId = response.headers.get(\"x-message-id\") ?? options.messageId ?? \"\";\n\n return {\n messageId,\n accepted: extractEmails(options.to),\n rejected: [],\n response: \"Accepted\",\n envelope: {\n from: from?.address ?? \"\",\n to: [\n ...extractEmails(options.to),\n ...(options.cc ? extractEmails(options.cc) : []),\n ...(options.bcc ? extractEmails(options.bcc) : []),\n ],\n },\n };\n }\n\n /** Verifies the SendGrid API key by fetching the user profile. */\n async verify(): Promise<VerifyResult> {\n try {\n const response = await fetch(\"https://api.sendgrid.com/v3/user/profile\", {\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n },\n });\n\n if (!response.ok) {\n const apiError = await response.text().catch(() => \"\");\n return {\n ok: false,\n provider: \"sendgrid\",\n message: apiError || `HTTP ${response.status}`,\n };\n }\n\n const payload = (await response.json()) as { username?: string };\n return {\n ok: true,\n provider: \"sendgrid\",\n ...(payload.username ? { message: payload.username } : {}),\n };\n } catch (err) {\n return {\n ok: false,\n provider: \"sendgrid\",\n message: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n"
5
+ "/**\n * @module\n * SendGrid v3 HTTP API transport for sending email via api.sendgrid.com.\n *\n * @example\n * ```ts\n * import { SendGridTransport } from \"sently/transports/sendgrid\";\n * import { createMailer } from \"sently\";\n *\n * const mailer = await createMailer({\n * transport: new SendGridTransport({ apiKey: process.env.SENDGRID_API_KEY! }),\n * });\n *\n * await mailer.send({\n * from: \"sender@example.com\",\n * to: \"recipient@example.com\",\n * subject: \"Hello\",\n * text: \"Plain text body\",\n * });\n * ```\n */\nimport { extractEmails, parseAddresses } from \"../core/address.js\";\nimport { encodeBase64 } from \"../core/base64.js\";\nimport type { MailOptions, SendResult, Transport, VerifyResult } from \"../core/types.js\";\nimport { resolveAttachments } from \"./resolve-attachments.js\";\n\n/** SendGrid API configuration. */\nexport interface SendGridConfig {\n /** SendGrid API key (Bearer token). */\n apiKey: string;\n}\n\n/** Error thrown when the SendGrid API returns a non-success response. */\nexport class SendGridError extends Error {\n /** Creates a SendGrid API error with status code and response payload. */\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly apiError: unknown,\n ) {\n super(message);\n this.name = \"SendGridError\";\n }\n}\n\n/**\n * SendGrid v3 HTTP API transport.\n */\nexport class SendGridTransport implements Transport {\n /** SendGrid API key for Bearer authentication. */\n private readonly apiKey: string;\n\n /** Creates a SendGrid transport with the given API key. */\n constructor(config: SendGridConfig) {\n this.apiKey = config.apiKey;\n }\n\n /** Build a SendGrid personalization for one message. */\n private buildPersonalization(options: MailOptions): Record<string, unknown> {\n return {\n to: parseAddresses(options.to).map((addr) => ({ email: addr.address, name: addr.name })),\n ...(options.cc\n ? {\n cc: parseAddresses(options.cc).map((addr) => ({\n email: addr.address,\n name: addr.name,\n })),\n }\n : {}),\n ...(options.bcc\n ? {\n bcc: parseAddresses(options.bcc).map((addr) => ({\n email: addr.address,\n name: addr.name,\n })),\n }\n : {}),\n subject: options.subject,\n ...(options.headers ? { headers: options.headers } : {}),\n };\n }\n\n /** Build SendGrid content parts from text/html options. */\n private buildContent(options: MailOptions): Array<{ type: string; value: string }> {\n return [\n ...(options.text ? [{ type: \"text/plain\", value: options.text }] : []),\n ...(options.html ? [{ type: \"text/html\", value: options.html }] : []),\n ];\n }\n\n /** Map a SendGrid response to a normalized SendResult for one message. */\n private toSendResult(\n options: MailOptions,\n messageId: string,\n responseText = \"Accepted\",\n ): SendResult {\n const from = parseAddresses(options.from)[0];\n return {\n messageId,\n accepted: extractEmails(options.to),\n rejected: [],\n response: responseText,\n envelope: {\n from: from?.address ?? \"\",\n to: [\n ...extractEmails(options.to),\n ...(options.cc ? extractEmails(options.cc) : []),\n ...(options.bcc ? extractEmails(options.bcc) : []),\n ],\n },\n };\n }\n\n /** Sends an email via the SendGrid v3 HTTP API. */\n async send(options: MailOptions): Promise<SendResult> {\n const attachments = await resolveAttachments(options.attachments);\n const from = parseAddresses(options.from)[0];\n\n const body = {\n personalizations: [this.buildPersonalization(options)],\n from: from\n ? { email: from.address, ...(from.name ? { name: from.name } : {}) }\n : { email: \"\" },\n ...(options.replyTo\n ? {\n reply_to: parseAddresses(options.replyTo).map((addr) => ({\n email: addr.address,\n name: addr.name,\n }))[0],\n }\n : {}),\n content: this.buildContent(options),\n ...(attachments.length > 0\n ? {\n attachments: attachments.map((att) => ({\n filename: att.filename,\n type: att.contentType ?? \"application/octet-stream\",\n content:\n att.content instanceof Uint8Array\n ? encodeBase64(att.content).replace(/\\r\\n/g, \"\")\n : att.content,\n ...(att.contentId ? { content_id: att.contentId } : {}),\n disposition: att.inline ? \"inline\" : \"attachment\",\n })),\n }\n : {}),\n };\n\n const response = await fetch(\"https://api.sendgrid.com/v3/mail/send\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const apiError = await response.text();\n throw new SendGridError(\"SendGrid API error\", response.status, apiError);\n }\n\n const messageId = response.headers.get(\"x-message-id\") ?? options.messageId ?? \"\";\n\n return this.toSendResult(options, messageId);\n }\n\n /** Send multiple messages in one request using SendGrid personalizations. */\n async sendBatch(messages: MailOptions[]): Promise<SendResult[]> {\n if (messages.length === 0) {\n return [];\n }\n\n const first = messages[0] as MailOptions;\n const from = parseAddresses(first.from)[0];\n\n const body = {\n personalizations: messages.map((message) => this.buildPersonalization(message)),\n from: from\n ? { email: from.address, ...(from.name ? { name: from.name } : {}) }\n : { email: \"\" },\n ...(first.replyTo\n ? {\n reply_to: parseAddresses(first.replyTo).map((addr) => ({\n email: addr.address,\n name: addr.name,\n }))[0],\n }\n : {}),\n content: this.buildContent(first),\n };\n\n const response = await fetch(\"https://api.sendgrid.com/v3/mail/send\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const apiError = await response.text();\n throw new SendGridError(\"SendGrid API error\", response.status, apiError);\n }\n\n const messageId = response.headers.get(\"x-message-id\") ?? \"\";\n return messages.map((message) =>\n this.toSendResult(message, messageId || message.messageId || \"\"),\n );\n }\n\n /** Verifies the SendGrid API key by fetching the user profile. */\n async verify(): Promise<VerifyResult> {\n try {\n const response = await fetch(\"https://api.sendgrid.com/v3/user/profile\", {\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n },\n });\n\n if (!response.ok) {\n const apiError = await response.text().catch(() => \"\");\n return {\n ok: false,\n provider: \"sendgrid\",\n message: apiError || `HTTP ${response.status}`,\n };\n }\n\n const payload = (await response.json()) as { username?: string };\n return {\n ok: true,\n provider: \"sendgrid\",\n ...(payload.username ? { message: payload.username } : {}),\n };\n } catch (err) {\n return {\n ok: false,\n provider: \"sendgrid\",\n message: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "53D65F527A73629564756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "86CABED9282C733164756E2164756E21",
9
9
  "names": []
10
10
  }