@particle-academy/resend-js 0.3.4 → 0.4.0

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/CHANGELOG.md CHANGED
@@ -7,6 +7,19 @@ The four packages share one version, because they are generated from one
7
7
  `provider/` definition and a version that meant something different in each
8
8
  would be a version nobody could reason about.
9
9
 
10
+ ## [0.4.0] — 2026-09-15
11
+
12
+ ### Added
13
+
14
+ - **`email_received` trigger — inbound email.** Resend delivers an `email.received` webhook when mail arrives at one of your receiving addresses, signed by Svix: `{svix-id}.{svix-timestamp}.{body}` under HMAC-SHA256, the signature base64 in `svix-signature` as a space-separated list of `v1,<sig>` of which ANY may match, and a `whsec_<base64>` secret whose HMAC key is the DECODED remainder. The connection stores the secret exactly as the dashboard shows it; the verifier strips the prefix and decodes it, and refuses a secret without its prefix, or one that is not base64, by name rather than failing like a wrong secret. A delivery without its `svix-id` is refused by name too. Five-minute replay window.
15
+ - **The trigger reads the email FIRST.** The webhook carries metadata only — no body, no headers, no attachment bytes — so the trigger's `then` block runs `email_get` with the delivery's `email_id` before the run starts and publishes the result under `email`: bodies, headers, message id, the raw download URL and the attachment list. A failed read fails the run rather than starting a flow that assumes the email was there. `verdicts` is published as an explicit `null`: Resend exposes no SPF, DKIM or DMARC verdicts, and a flow looking for them must find a null, not a missing key. Fake mode composes the faked delivery with the faked read, so `email.id` equals `data.email_id` on the canvas exactly as it does live.
16
+ - **`email_get`, `attachment_list`, `attachment_get`.** A received email in full (`GET /emails/receiving/{id}`); its attachments with signed download URLs (`…/attachments`, with `limit`, `after`, `before`); one attachment as a signed download URL with its id and expiry beside it (`…/attachments/{id}`). The bytes never pass through the connector.
17
+ - **`webhookSecret` credential**, optional, used only by the trigger.
18
+
19
+ ### Changed
20
+
21
+ - **Requires `fancy-connector-core` ≥ 0.9.0** — `particle-academy/fancy-connector-core` for php, `@particle-academy/fancy-connector-core` for js. The Svix scheme needs the core's `secretEncoding` / `secretPrefix`, its `{id}` payload slot and its any-of signature rule, all added in 0.9.0; `CONNECTOR_API_VERSION` is unchanged at 1.
22
+
10
23
  ## [0.3.4] — 2026-09-12
11
24
 
12
25
  ### Changed
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Resend
2
2
 
3
+ [![Fancified](art/fancified.svg)](https://particle.academy)
4
+
3
5
  Resend for [fancy-flow][flow] — as **four imported, versioned packages**, one
4
6
  per runtime. Not vendored source: a copy cannot be upgraded, and third-party APIs
5
7
  change.
@@ -33,13 +35,14 @@ Everything below is generated from `provider/manifest.json`, so it cannot disagr
33
35
 
34
36
  ### Credentials
35
37
 
36
- A Resend connection holds 1 value.
38
+ A Resend connection holds 2 values.
37
39
 
38
40
  Every value here is `account` scope: one per connected account, not one per installation.
39
41
 
40
42
  | Field | Scope | Secret | Where it comes from |
41
43
  |---|---|---|---|
42
44
  | **API key** | per connected account | **secret** | re_... from the Resend dashboard. There is only one estate, so this key sends real email. |
45
+ | **Webhook signing secret** *(optional)* | per connected account | **secret** | whsec_... from the webhook endpoint you added in the Resend dashboard, exactly as shown -- the prefix stays. Required only by the email_received trigger. |
43
46
 
44
47
  ### The estate
45
48
 
@@ -51,6 +54,40 @@ Every value here is `account` scope: one per connected account, not one per inst
51
54
 
52
55
  ### Actions
53
56
 
57
+ #### `attachment_get` — Get attachment
58
+
59
+ Turn one attachment of a received email into a signed download URL.
60
+
61
+ `GET /emails/receiving/{emailId}/attachments/{attachmentId}` · reads only — safe to replay
62
+
63
+ | Input | Required | What it is |
64
+ |---|---|---|
65
+ | `emailId` | yes | The received email's id -- `data.email_id` on the delivery, or `email.id` after the trigger's read. |
66
+ | `attachmentId` | yes | From `email.attachments[].id` on the trigger, or from attachment_list. |
67
+
68
+ #### `attachment_list` — List attachments
69
+
70
+ List a received email's attachments, each with a signed download URL.
71
+
72
+ `GET /emails/receiving/{emailId}/attachments` · reads only — safe to replay
73
+
74
+ | Input | Required | What it is |
75
+ |---|---|---|
76
+ | `emailId` | yes | The received email's id -- `data.email_id` on the delivery, or `email.id` after the trigger's read. |
77
+ | `limit` | no | Attachments per page, 1 to 100. Leave blank for all of them. |
78
+ | `after` | no | An attachment id: the page after it. Not together with `before`. |
79
+ | `before` | no | An attachment id: the page before it. Not together with `after`. |
80
+
81
+ #### `email_get` — Get received email
82
+
83
+ Read a received email in full: its bodies, its headers and the list of its attachments.
84
+
85
+ `GET /emails/receiving/{emailId}` · reads only — safe to replay
86
+
87
+ | Input | Required | What it is |
88
+ |---|---|---|
89
+ | `emailId` | yes | The received email's id -- `data.email_id` on an email.received delivery. Not the message_id: that is the RFC 5322 header, which Resend does not look up by. |
90
+
54
91
  #### `email_send` — Send email
55
92
 
56
93
  Send an email through Resend.
@@ -67,6 +104,18 @@ Send an email through Resend.
67
104
  | `replyTo` | no | Reply-To |
68
105
  | `headers` | no | Sent as the email's own headers. The usual use is a threading or reference id. |
69
106
 
107
+ ### Triggers
108
+
109
+ #### `email_received` — Email received
110
+
111
+ Start when an email arrives at one of your Resend receiving addresses, with the email read in full.
112
+
113
+ Delivered by webhook, and the signature is verified before anything runs. The delivery only names what arrived, so the run's first step reads it: `email_get` with `emailId` from `data.email_id`, published under `email`. A failed read fails the run.
114
+
115
+ **You have to set this up with the provider first:**
116
+
117
+ Point a receiving domain's MX record at Resend, then in the Resend dashboard (Webhooks → Add webhook) point an endpoint at the route your host mounts for this trigger and subscribe it to email.received. Put the endpoint's signing secret -- shown as whsec_… -- on the connection as `webhookSecret`, exactly as shown.
118
+
70
119
  ## Run it before you have credentials
71
120
 
72
121
  Every operation ships a **faker**, whether or not Resend has a sandbox. Set a
@@ -0,0 +1,26 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="128" height="28" role="img" aria-label="Fancified — built with Fancy UI">
2
+ <title>Fancified · built with Fancy UI</title>
3
+ <defs>
4
+ <linearGradient id="fcdBg" x1="0" y1="0" x2="1" y2="1">
5
+ <stop offset="0" stop-color="#6d28d9"/>
6
+ <stop offset=".5" stop-color="#9333ea"/>
7
+ <stop offset="1" stop-color="#d946ef"/>
8
+ </linearGradient>
9
+ <linearGradient id="fcdGloss" x1="0" y1="0" x2="0" y2="1">
10
+ <stop offset="0" stop-color="#ffffff" stop-opacity=".30"/>
11
+ <stop offset=".55" stop-color="#ffffff" stop-opacity="0"/>
12
+ </linearGradient>
13
+ <clipPath id="fcdClip"><rect width="128" height="28" rx="7"/></clipPath>
14
+ </defs>
15
+ <g clip-path="url(#fcdClip)">
16
+ <rect width="128" height="28" fill="url(#fcdBg)"/>
17
+ <rect width="34" height="28" fill="#3b0764" fill-opacity=".5"/>
18
+ <rect width="128" height="13" fill="url(#fcdGloss)"/>
19
+ <g fill="#fff">
20
+ <path transform="translate(17 14)" d="M0 -7 C.6 -2.2 2.2 -.6 7 0 C2.2 .6 .6 2.2 0 7 C-.6 2.2 -2.2 .6 -7 0 C-2.2 -.6 -.6 -2.2 0 -7 Z"/>
21
+ <path transform="translate(25.5 7.5) scale(.34)" fill-opacity=".85" d="M0 -7 C.6 -2.2 2.2 -.6 7 0 C2.2 .6 .6 2.2 0 7 C-.6 2.2 -2.2 .6 -7 0 C-2.2 -.6 -.6 -2.2 0 -7 Z"/>
22
+ </g>
23
+ <text x="81" y="18.5" fill="#ffffff" text-anchor="middle" font-family="'Segoe UI',Verdana,'DejaVu Sans',sans-serif" font-size="12" font-weight="700" letter-spacing=".3">Fancified</text>
24
+ </g>
25
+ <rect x=".5" y=".5" width="127" height="27" rx="6.5" fill="none" stroke="#ffffff" stroke-opacity=".22"/>
26
+ </svg>
@@ -0,0 +1,326 @@
1
+ import { callConnector, verifyDelivery } from '@particle-academy/fancy-connector-core';
2
+
3
+ // src/faker.ts
4
+ function fakeAttachmentGet({ config, fake }) {
5
+ return {
6
+ "object": "attachment",
7
+ "id": config.attachmentId !== void 0 && config.attachmentId !== null && config.attachmentId !== "" ? String(config.attachmentId) : `${fake.hex(8)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(12)}`,
8
+ "filename": "avatar.png",
9
+ "size": 4096,
10
+ "content_type": "image/png",
11
+ "content_disposition": "inline",
12
+ "content_id": "img001",
13
+ "download_url": "https://inbound-cdn.resend.com/4ef9a417-02e9-4d39-ad75-9611e0fcc33c/attachments/2a0c9ce0-3112-4728-976e-47ddcd16a318?signature=fake",
14
+ "expires_at": "2026-10-17T14:29:41.521Z"
15
+ };
16
+ }
17
+ function fakeAttachmentList({ config, fake }) {
18
+ return {
19
+ "object": "list",
20
+ "has_more": false,
21
+ "data": [
22
+ {
23
+ "id": `${fake.hex(8)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(12)}`,
24
+ "filename": "avatar.png",
25
+ "size": 4096,
26
+ "content_type": "image/png",
27
+ "content_disposition": "inline",
28
+ "content_id": "img001",
29
+ "download_url": "https://inbound-cdn.resend.com/4ef9a417-02e9-4d39-ad75-9611e0fcc33c/attachments/2a0c9ce0-3112-4728-976e-47ddcd16a318?signature=fake",
30
+ "expires_at": "2026-10-17T14:29:41.521Z"
31
+ }
32
+ ]
33
+ };
34
+ }
35
+ function fakeEmailGet({ config, fake }) {
36
+ return {
37
+ "object": "email",
38
+ "id": config.emailId !== void 0 && config.emailId !== null && config.emailId !== "" ? String(config.emailId) : `${fake.hex(8)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(12)}`,
39
+ "to": [
40
+ "inbox@yourdomain.test"
41
+ ],
42
+ "from": "ada@example.test",
43
+ "created_at": "2026-09-15T12:00:11.894Z",
44
+ "subject": "Sending this example",
45
+ "html": "Congrats on receiving your <strong>first email</strong>!",
46
+ "html_format": "data_uri",
47
+ "text": null,
48
+ "headers": {
49
+ "from": "Ada Lovelace <ada@example.test>",
50
+ "return-path": "ada@example.test",
51
+ "mime-version": "1.0"
52
+ },
53
+ "bcc": [],
54
+ "cc": [],
55
+ "reply_to": [],
56
+ "received_for": [],
57
+ "message_id": "<111-222-333@email.example.test>",
58
+ "raw": {
59
+ "download_url": "https://example.resend.com/receiving/raw/054da427-439a-4e91-b785-e4fb1966285f?Signature=fake",
60
+ "expires_at": "2026-09-15T13:00:11.894Z"
61
+ },
62
+ "attachments": [
63
+ {
64
+ "id": `${fake.hex(8)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(12)}`,
65
+ "filename": "avatar.png",
66
+ "content_type": "image/png",
67
+ "content_disposition": "inline",
68
+ "content_id": "img001",
69
+ "size": 4096
70
+ }
71
+ ]
72
+ };
73
+ }
74
+ function fakeEmailSend({ config, fake }) {
75
+ return {
76
+ "id": `${fake.hex(8)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(12)}`
77
+ };
78
+ }
79
+ function fakeEmailReceived({ config, fake }) {
80
+ const boundEmailid = `${fake.hex(8)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(12)}`;
81
+ return {
82
+ "type": "email.received",
83
+ "created_at": "2026-09-15T12:00:12.126Z",
84
+ "data": {
85
+ "email_id": boundEmailid,
86
+ "created_at": "2026-09-15T12:00:11.894Z",
87
+ "from": "ada@example.test",
88
+ "to": [
89
+ "inbox@yourdomain.test"
90
+ ],
91
+ "bcc": [],
92
+ "cc": [],
93
+ "received_for": [],
94
+ "message_id": "<111-222-333@email.example.test>",
95
+ "subject": "Sending this example",
96
+ "attachments": [
97
+ {
98
+ "id": `${fake.hex(8)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(12)}`,
99
+ "filename": "avatar.png",
100
+ "content_type": "image/png",
101
+ "content_disposition": "inline",
102
+ "content_id": "img001"
103
+ }
104
+ ]
105
+ }
106
+ };
107
+ }
108
+ var resendFaker = (operation, request) => {
109
+ switch (operation) {
110
+ case "attachment_get":
111
+ return fakeAttachmentGet(request);
112
+ case "attachment_list":
113
+ return fakeAttachmentList(request);
114
+ case "email_get":
115
+ return fakeEmailGet(request);
116
+ case "email_send":
117
+ return fakeEmailSend(request);
118
+ case "email_received":
119
+ return fakeEmailReceived(request);
120
+ default:
121
+ throw new Error(
122
+ `resend: no fake response is defined for "${operation}". Add a fixture under provider/fixtures/ and regenerate \u2014 a connector without a faker cannot be developed against, tested, or demonstrated.`
123
+ );
124
+ }
125
+ };
126
+
127
+ // src/service.ts
128
+ var CONNECTOR_API_VERSION = 1;
129
+ var RESEND_BASE_URLS = {
130
+ "live": "https://api.resend.com"
131
+ };
132
+ var RESEND_REQUIRES = [
133
+ "apiKey"
134
+ ];
135
+ function resendAuthorize(credentials, request, _mode) {
136
+ request.headers["User-Agent"] = "fancy-flow-connector";
137
+ request.headers.Authorization = `Bearer ${credentials.apiKey ?? ""}`;
138
+ }
139
+ var RESEND = {
140
+ service: "resend",
141
+ title: "Resend",
142
+ sandbox: "none",
143
+ baseUrls: { ...RESEND_BASE_URLS },
144
+ requires: [...RESEND_REQUIRES],
145
+ authorize: resendAuthorize,
146
+ // Resend honours this for 24 hours. It is what makes a retried durable run
147
+ // resend nothing instead of mailing the recipient twice -- the difference
148
+ // between `idempotent` and `unsafe-to-replay` is that this one is merely
149
+ // embarrassing, not financial, but the header costs nothing and removes it
150
+ // entirely.
151
+ idempotencyHeader: "Idempotency-Key",
152
+ faker: resendFaker
153
+ };
154
+ var ATTACHMENT_GET_OPERATION = "attachment_get";
155
+ async function resendAttachmentGet(options) {
156
+ const config = options.config ?? {};
157
+ if (config.emailId === void 0 || config.emailId === null || config.emailId === "") {
158
+ throw new Error(`attachment_get: "emailId" is required (Email ID).`);
159
+ }
160
+ if (config.attachmentId === void 0 || config.attachmentId === null || config.attachmentId === "") {
161
+ throw new Error(`attachment_get: "attachmentId" is required (Attachment ID).`);
162
+ }
163
+ return callConnector(RESEND, {
164
+ operation: ATTACHMENT_GET_OPERATION,
165
+ config,
166
+ input: options.input,
167
+ ...options.credentials === void 0 ? {} : { credentials: options.credentials },
168
+ ...options.mode === void 0 ? {} : { mode: options.mode },
169
+ ...options.connectionId === void 0 ? {} : { connectionId: options.connectionId },
170
+ ...options.attempts === void 0 ? {} : { attempts: options.attempts },
171
+ ...options.transport === void 0 ? {} : { transport: options.transport },
172
+ request: {
173
+ method: "GET",
174
+ path: `/emails/receiving/${encodeURIComponent(String(config.emailId))}/attachments/${encodeURIComponent(String(config.attachmentId))}`,
175
+ query: {}
176
+ }
177
+ });
178
+ }
179
+ var ATTACHMENT_LIST_OPERATION = "attachment_list";
180
+ async function resendAttachmentList(options) {
181
+ const config = options.config ?? {};
182
+ if (config.emailId === void 0 || config.emailId === null || config.emailId === "") {
183
+ throw new Error(`attachment_list: "emailId" is required (Email ID).`);
184
+ }
185
+ {
186
+ const n = Number(config.limit);
187
+ const given = config.limit !== void 0 && config.limit !== null && config.limit !== "";
188
+ if (given && !(Number.isInteger(n) && n >= 1 && n <= 100)) {
189
+ throw new Error(
190
+ `attachment_list: "limit" must be a integer, got ${JSON.stringify(config.limit)}.`
191
+ );
192
+ }
193
+ }
194
+ return callConnector(RESEND, {
195
+ operation: ATTACHMENT_LIST_OPERATION,
196
+ config,
197
+ input: options.input,
198
+ ...options.credentials === void 0 ? {} : { credentials: options.credentials },
199
+ ...options.mode === void 0 ? {} : { mode: options.mode },
200
+ ...options.connectionId === void 0 ? {} : { connectionId: options.connectionId },
201
+ ...options.attempts === void 0 ? {} : { attempts: options.attempts },
202
+ ...options.transport === void 0 ? {} : { transport: options.transport },
203
+ request: {
204
+ method: "GET",
205
+ path: `/emails/receiving/${encodeURIComponent(String(config.emailId))}/attachments`,
206
+ query: {
207
+ ...config.limit !== void 0 && config.limit !== null && config.limit !== "" ? { "limit": Math.trunc(Number(config.limit)) } : {},
208
+ ...config.after !== void 0 && config.after !== null && config.after !== "" ? { "after": String(config.after) } : {},
209
+ ...config.before !== void 0 && config.before !== null && config.before !== "" ? { "before": String(config.before) } : {}
210
+ }
211
+ }
212
+ });
213
+ }
214
+ var EMAIL_GET_OPERATION = "email_get";
215
+ async function resendEmailGet(options) {
216
+ const config = options.config ?? {};
217
+ if (config.emailId === void 0 || config.emailId === null || config.emailId === "") {
218
+ throw new Error(`email_get: "emailId" is required (Email ID).`);
219
+ }
220
+ return callConnector(RESEND, {
221
+ operation: EMAIL_GET_OPERATION,
222
+ config,
223
+ input: options.input,
224
+ ...options.credentials === void 0 ? {} : { credentials: options.credentials },
225
+ ...options.mode === void 0 ? {} : { mode: options.mode },
226
+ ...options.connectionId === void 0 ? {} : { connectionId: options.connectionId },
227
+ ...options.attempts === void 0 ? {} : { attempts: options.attempts },
228
+ ...options.transport === void 0 ? {} : { transport: options.transport },
229
+ request: {
230
+ method: "GET",
231
+ path: `/emails/receiving/${encodeURIComponent(String(config.emailId))}`,
232
+ query: {}
233
+ }
234
+ });
235
+ }
236
+ var EMAIL_SEND_OPERATION = "email_send";
237
+ async function resendEmailSend(options) {
238
+ const config = options.config ?? {};
239
+ if (config.from === void 0 || config.from === null || config.from === "") {
240
+ throw new Error(`email_send: "from" is required (From).`);
241
+ }
242
+ if (config.to === void 0 || config.to === null || config.to === "") {
243
+ throw new Error(`email_send: "to" is required (To).`);
244
+ }
245
+ if (!(config.html !== void 0 && config.html !== null && config.html !== "" || config.text !== void 0 && config.text !== null && config.text !== "")) {
246
+ throw new Error(`email_send: needs an "html" or "text" body \u2014 an empty email is never intended.`);
247
+ }
248
+ return callConnector(RESEND, {
249
+ operation: EMAIL_SEND_OPERATION,
250
+ config,
251
+ input: options.input,
252
+ ...options.credentials === void 0 ? {} : { credentials: options.credentials },
253
+ ...options.mode === void 0 ? {} : { mode: options.mode },
254
+ ...options.connectionId === void 0 ? {} : { connectionId: options.connectionId },
255
+ ...options.attempts === void 0 ? {} : { attempts: options.attempts },
256
+ ...options.transport === void 0 ? {} : { transport: options.transport },
257
+ ...options.idempotencyKey === void 0 ? {} : { idempotencyKey: options.idempotencyKey },
258
+ request: {
259
+ method: "POST",
260
+ path: "/emails",
261
+ json: {
262
+ "from": String(config.from),
263
+ "to": toList(config.to),
264
+ "subject": config.subject !== void 0 && config.subject !== null && config.subject !== "" ? String(config.subject) : "",
265
+ ...config.html !== void 0 && config.html !== null && config.html !== "" ? { "html": String(config.html) } : {},
266
+ ...config.text !== void 0 && config.text !== null && config.text !== "" ? { "text": String(config.text) } : {},
267
+ ...config.replyTo !== void 0 && config.replyTo !== null && config.replyTo !== "" ? { "reply_to": String(config.replyTo) } : {},
268
+ "headers": headersMap(config.headers)
269
+ }
270
+ }
271
+ });
272
+ }
273
+ function toList(value) {
274
+ const items = Array.isArray(value) ? value.map(String) : typeof value === "string" ? value.split(",") : [];
275
+ return items.map((item) => item.trim()).filter(Boolean);
276
+ }
277
+ function headersMap(value) {
278
+ if (!value || typeof value !== "object") return {};
279
+ const out = {};
280
+ for (const [key, item] of Object.entries(value)) {
281
+ if (item !== void 0 && item !== null && item !== "") out[key] = String(item);
282
+ }
283
+ return out;
284
+ }
285
+ var RESEND_EMAIL_RECEIVED_SIGNATURE_HEADER = "svix-signature";
286
+ var RESEND_EMAIL_RECEIVED_TOLERANCE = 300;
287
+ var RESEND_EMAIL_RECEIVED_SCHEME = {
288
+ algorithm: "SHA-256",
289
+ payload: (raw, timestamp, id) => `${id}.${timestamp}.${raw}`,
290
+ tolerance: RESEND_EMAIL_RECEIVED_TOLERANCE,
291
+ encoding: "base64",
292
+ secretEncoding: "base64",
293
+ secretPrefix: "whsec_"
294
+ };
295
+ function parseResendSignature(raw) {
296
+ const result = { signatures: [] };
297
+ for (const part of raw.split(" ")) {
298
+ const [key, value] = part.trim().split(",", 2);
299
+ if (value === void 0) continue;
300
+ if (key === "v1") {
301
+ result.signatures.push(value);
302
+ }
303
+ }
304
+ return result;
305
+ }
306
+ var RESEND_EMAIL_RECEIVED = {
307
+ service: "resend",
308
+ operation: "email_received",
309
+ delivery: "webhook",
310
+ setup: "Point a receiving domain's MX record at Resend, then in the Resend dashboard (Webhooks \u2192 Add webhook) point an endpoint at the route your host mounts for this trigger and subscribe it to email.received. Put the endpoint's signing secret -- shown as whsec_\u2026 -- on the connection as `webhookSecret`, exactly as shown.",
311
+ verification: {
312
+ signatureHeader: RESEND_EMAIL_RECEIVED_SIGNATURE_HEADER,
313
+ scheme: RESEND_EMAIL_RECEIVED_SCHEME,
314
+ timestampHeader: "svix-timestamp",
315
+ idHeader: "svix-id",
316
+ parse: parseResendSignature
317
+ },
318
+ faker: resendFaker
319
+ };
320
+ function verifyResendDelivery(delivery, webhookSecret, now) {
321
+ return verifyDelivery(RESEND_EMAIL_RECEIVED, delivery, webhookSecret, now);
322
+ }
323
+
324
+ export { ATTACHMENT_GET_OPERATION, ATTACHMENT_LIST_OPERATION, CONNECTOR_API_VERSION, EMAIL_GET_OPERATION, EMAIL_SEND_OPERATION, RESEND, RESEND_BASE_URLS, RESEND_EMAIL_RECEIVED, RESEND_EMAIL_RECEIVED_SCHEME, RESEND_EMAIL_RECEIVED_SIGNATURE_HEADER, RESEND_EMAIL_RECEIVED_TOLERANCE, RESEND_REQUIRES, parseResendSignature, resendAttachmentGet, resendAttachmentList, resendAuthorize, resendEmailGet, resendEmailSend, resendFaker, verifyResendDelivery };
325
+ //# sourceMappingURL=chunk-JEKUTTK2.js.map
326
+ //# sourceMappingURL=chunk-JEKUTTK2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/faker.ts","../src/service.ts","../src/actions/attachment-get.ts","../src/actions/attachment-list.ts","../src/actions/email-get.ts","../src/actions/email-send.ts","../src/triggers/email-received.ts"],"names":["callConnector"],"mappings":"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","file":"chunk-JEKUTTK2.js","sourcesContent":["/**\n * GENERATED FILE — do not edit.\n *\n * Emitted from provider/fixtures/ by weaver's generator.\n * A hand-edit here is destroyed by the next protocol sync, which is worse than\n * being rejected, because it works until it silently does not. Fix\n * provider/fixtures/ (or weaver's template/) and regenerate:\n *\n * npm run provider -- resend\n */\n\n/**\n * The Resend faker.\n *\n * Shapes, not behaviour: the goal is that a downstream node sees the field\n * NAMES Resend actually publishes, so an author can wire {{ $json.data.id }}\n * against a fake and have it keep working against the real thing.\n *\n * Deterministic — same inputs, same output. A faker returning a fresh uuid\n * every call cannot be asserted on, so its fixtures degrade to \"it did not\n * throw\", which is the assertion that catches nothing.\n */\n\nimport type { ConnectorFaker, FakeRequest } from \"@particle-academy/fancy-connector-core\";\n\nfunction fakeAttachmentGet({ config, fake }: FakeRequest): unknown {\n return {\n \"object\": \"attachment\",\n \"id\": (config.attachmentId !== undefined && config.attachmentId !== null && config.attachmentId !== \"\" ? String(config.attachmentId) : `${fake.hex(8)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(12)}`),\n \"filename\": \"avatar.png\",\n \"size\": 4096,\n \"content_type\": \"image/png\",\n \"content_disposition\": \"inline\",\n \"content_id\": \"img001\",\n \"download_url\": \"https://inbound-cdn.resend.com/4ef9a417-02e9-4d39-ad75-9611e0fcc33c/attachments/2a0c9ce0-3112-4728-976e-47ddcd16a318?signature=fake\",\n \"expires_at\": \"2026-10-17T14:29:41.521Z\",\n };\n}\n\nfunction fakeAttachmentList({ config, fake }: FakeRequest): unknown {\n return {\n \"object\": \"list\",\n \"has_more\": false,\n \"data\": [\n {\n \"id\": `${fake.hex(8)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(12)}`,\n \"filename\": \"avatar.png\",\n \"size\": 4096,\n \"content_type\": \"image/png\",\n \"content_disposition\": \"inline\",\n \"content_id\": \"img001\",\n \"download_url\": \"https://inbound-cdn.resend.com/4ef9a417-02e9-4d39-ad75-9611e0fcc33c/attachments/2a0c9ce0-3112-4728-976e-47ddcd16a318?signature=fake\",\n \"expires_at\": \"2026-10-17T14:29:41.521Z\",\n },\n ],\n };\n}\n\nfunction fakeEmailGet({ config, fake }: FakeRequest): unknown {\n return {\n \"object\": \"email\",\n \"id\": (config.emailId !== undefined && config.emailId !== null && config.emailId !== \"\" ? String(config.emailId) : `${fake.hex(8)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(12)}`),\n \"to\": [\n \"inbox@yourdomain.test\",\n ],\n \"from\": \"ada@example.test\",\n \"created_at\": \"2026-09-15T12:00:11.894Z\",\n \"subject\": \"Sending this example\",\n \"html\": \"Congrats on receiving your <strong>first email</strong>!\",\n \"html_format\": \"data_uri\",\n \"text\": null,\n \"headers\": {\n \"from\": \"Ada Lovelace <ada@example.test>\",\n \"return-path\": \"ada@example.test\",\n \"mime-version\": \"1.0\",\n },\n \"bcc\": [],\n \"cc\": [],\n \"reply_to\": [],\n \"received_for\": [],\n \"message_id\": \"<111-222-333@email.example.test>\",\n \"raw\": {\n \"download_url\": \"https://example.resend.com/receiving/raw/054da427-439a-4e91-b785-e4fb1966285f?Signature=fake\",\n \"expires_at\": \"2026-09-15T13:00:11.894Z\",\n },\n \"attachments\": [\n {\n \"id\": `${fake.hex(8)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(12)}`,\n \"filename\": \"avatar.png\",\n \"content_type\": \"image/png\",\n \"content_disposition\": \"inline\",\n \"content_id\": \"img001\",\n \"size\": 4096,\n },\n ],\n };\n}\n\nfunction fakeEmailSend({ config, fake }: FakeRequest): unknown {\n return {\n \"id\": `${fake.hex(8)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(12)}`,\n };\n}\n\nfunction fakeEmailReceived({ config, fake }: FakeRequest): unknown {\n const boundEmailid = `${fake.hex(8)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(12)}`;\n\n return {\n \"type\": \"email.received\",\n \"created_at\": \"2026-09-15T12:00:12.126Z\",\n \"data\": {\n \"email_id\": boundEmailid,\n \"created_at\": \"2026-09-15T12:00:11.894Z\",\n \"from\": \"ada@example.test\",\n \"to\": [\n \"inbox@yourdomain.test\",\n ],\n \"bcc\": [],\n \"cc\": [],\n \"received_for\": [],\n \"message_id\": \"<111-222-333@email.example.test>\",\n \"subject\": \"Sending this example\",\n \"attachments\": [\n {\n \"id\": `${fake.hex(8)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(4)}-${fake.hex(12)}`,\n \"filename\": \"avatar.png\",\n \"content_type\": \"image/png\",\n \"content_disposition\": \"inline\",\n \"content_id\": \"img001\",\n },\n ],\n },\n };\n}\n\nexport const resendFaker: ConnectorFaker = (operation, request) => {\n switch (operation) {\n case \"attachment_get\":\n return fakeAttachmentGet(request);\n\n case \"attachment_list\":\n return fakeAttachmentList(request);\n\n case \"email_get\":\n return fakeEmailGet(request);\n\n case \"email_send\":\n return fakeEmailSend(request);\n\n case \"email_received\":\n return fakeEmailReceived(request);\n\n default:\n // A faker asked for an operation it has no shape for must SAY so. Making\n // something up would produce a green run whose output silently has none\n // of the fields the author is about to reference.\n throw new Error(\n `resend: no fake response is defined for \"${operation}\". ` +\n \"Add a fixture under provider/fixtures/ and regenerate — a connector without a faker \" +\n \"cannot be developed against, tested, or demonstrated.\",\n );\n }\n};\n","/**\n * GENERATED FILE — do not edit.\n *\n * Emitted from provider/manifest.json by weaver's generator.\n * A hand-edit here is destroyed by the next protocol sync, which is worse than\n * being rejected, because it works until it silently does not. Fix\n * provider/manifest.json (or weaver's template/) and regenerate:\n *\n * npm run provider -- resend\n */\n\n/**\n * Resend, as one service descriptor shared by every Resend operation.\n *\n * @particle-academy/fancy-connector-core carries what is true of ALL\n * connectors. This carries what is true of Resend: its base URL, its auth\n * scheme, its idempotency header, and its faker.\n *\n * ## The sandbox trap, written down where it is used\n *\n * Resend has NO test estate, and somebody checked. Its simulator RECIPIENTS --\n * delivered@resend.dev, bounced@resend.dev, complained@resend.dev,\n * suppressed@resend.dev -- are not one: the send is real, it is billed, and it\n * counts against the quota. Modelling them as a sandbox would put a live send\n * behind a control labelled \"test\", so `mode` does not offer sandbox at all\n * and `fake` is the primary development mode rather than the fallback.\n */\n\nimport type { ConnectorMode, PreparedRequest, ServiceDescriptor } from \"@particle-academy/fancy-connector-core\";\n\nimport { resendFaker } from \"./faker.js\";\n\n/**\n * The connector API version this package was GENERATED against.\n *\n * A literal, never imported. An imported constant lets an upgrade rewrite the\n * very claim it exists to detect, after which the copy agrees with itself\n * forever.\n */\nexport const CONNECTOR_API_VERSION = 1;\n\nexport const RESEND_BASE_URLS = {\n \"live\": \"https://api.resend.com\"\n} as const;\n\n/** Credential keys a remote call cannot proceed without. */\nexport const RESEND_REQUIRES = [\n \"apiKey\"\n] as const;\n\n/**\n * Apply Resend's auth scheme to an outgoing request.\n *\n *\n *\n * The mode is passed in because for some providers auth and estate are the\n * same decision expressed in the URL; here it is unused, and saying so is\n * cheaper than wondering later whether it was forgotten.\n */\nexport function resendAuthorize(\n credentials: Record<string, string | undefined>,\n request: PreparedRequest,\n _mode: ConnectorMode,\n): void {\n request.headers[\"User-Agent\"] = \"fancy-flow-connector\";\n\n request.headers.Authorization = `Bearer ${credentials.apiKey ?? \"\"}`;\n}\n\n/** The Resend service, for the TypeScript runtime. */\nexport const RESEND: ServiceDescriptor = {\n service: \"resend\",\n title: \"Resend\",\n sandbox: \"none\",\n baseUrls: { ...RESEND_BASE_URLS },\n requires: [...RESEND_REQUIRES],\n authorize: resendAuthorize,\n // Resend honours this for 24 hours. It is what makes a retried durable run\n // resend nothing instead of mailing the recipient twice -- the difference\n // between `idempotent` and `unsafe-to-replay` is that this one is merely\n // embarrassing, not financial, but the header costs nothing and removes it\n // entirely.\n idempotencyHeader: \"Idempotency-Key\",\n faker: resendFaker,\n};\n","/**\n * GENERATED FILE — do not edit.\n *\n * Emitted from provider/actions/attachment-get.json by weaver's generator.\n * A hand-edit here is destroyed by the next protocol sync, which is worse than\n * being rejected, because it works until it silently does not. Fix\n * provider/actions/attachment-get.json (or weaver's template/) and regenerate:\n *\n * npm run provider -- resend\n */\n\n/**\n * Turn one attachment of a received email into a signed download URL.\n *\n * GET /emails/receiving/{emailId}/attachments/{attachmentId} —\n * https://resend.com/docs/api-reference/emails/retrieve-received-email-attachment\n *\n * Notice what is NOT here: no key, no base URL, no mode check, no retry loop,\n * no fake/real branch. This describes the request; callConnector resolves the\n * connection, picks the estate, and either calls Resend or calls the faker.\n */\n\nimport {\n callConnector,\n type ConnectorResult,\n type RequestedMode,\n type Transport,\n} from \"@particle-academy/fancy-connector-core\";\nimport { RESEND } from \"../service.js\";\n\nexport const ATTACHMENT_GET_OPERATION = \"attachment_get\";\n\nexport type AttachmentGetOptions = {\n /** The node's resolved config. Keys: emailId, attachmentId. */\n config: Record<string, unknown>;\n credentials?: Record<string, string | undefined>;\n mode?: RequestedMode;\n connectionId?: string | null;\n input?: unknown;\n attempts?: number;\n /** Override the transport. The only way to exercise this without a network. */\n transport?: Transport;\n};\n\nexport async function resendAttachmentGet(options: AttachmentGetOptions): Promise<ConnectorResult> {\n const config = options.config ?? {};\n\n if (config.emailId === undefined || config.emailId === null || config.emailId === \"\") {\n throw new Error(`attachment_get: \"emailId\" is required (Email ID).`);\n }\n\n if (config.attachmentId === undefined || config.attachmentId === null || config.attachmentId === \"\") {\n throw new Error(`attachment_get: \"attachmentId\" is required (Attachment ID).`);\n }\n\n return callConnector(RESEND, {\n operation: ATTACHMENT_GET_OPERATION,\n config,\n input: options.input,\n ...(options.credentials === undefined ? {} : { credentials: options.credentials }),\n ...(options.mode === undefined ? {} : { mode: options.mode }),\n ...(options.connectionId === undefined ? {} : { connectionId: options.connectionId }),\n ...(options.attempts === undefined ? {} : { attempts: options.attempts }),\n ...(options.transport === undefined ? {} : { transport: options.transport }),\n request: {\n method: \"GET\",\n path: `/emails/receiving/${encodeURIComponent(String(config.emailId))}/attachments/${encodeURIComponent(String(config.attachmentId))}`,\n query: {},\n },\n });\n}\n","/**\n * GENERATED FILE — do not edit.\n *\n * Emitted from provider/actions/attachment-list.json by weaver's generator.\n * A hand-edit here is destroyed by the next protocol sync, which is worse than\n * being rejected, because it works until it silently does not. Fix\n * provider/actions/attachment-list.json (or weaver's template/) and regenerate:\n *\n * npm run provider -- resend\n */\n\n/**\n * List a received email's attachments, each with a signed download URL.\n *\n * GET /emails/receiving/{emailId}/attachments —\n * https://resend.com/docs/api-reference/emails/list-received-email-attachments\n *\n * Notice what is NOT here: no key, no base URL, no mode check, no retry loop,\n * no fake/real branch. This describes the request; callConnector resolves the\n * connection, picks the estate, and either calls Resend or calls the faker.\n */\n\nimport {\n callConnector,\n type ConnectorResult,\n type RequestedMode,\n type Transport,\n} from \"@particle-academy/fancy-connector-core\";\nimport { RESEND } from \"../service.js\";\n\nexport const ATTACHMENT_LIST_OPERATION = \"attachment_list\";\n\nexport type AttachmentListOptions = {\n /** The node's resolved config. Keys: emailId, limit, after, before. */\n config: Record<string, unknown>;\n credentials?: Record<string, string | undefined>;\n mode?: RequestedMode;\n connectionId?: string | null;\n input?: unknown;\n attempts?: number;\n /** Override the transport. The only way to exercise this without a network. */\n transport?: Transport;\n};\n\nexport async function resendAttachmentList(options: AttachmentListOptions): Promise<ConnectorResult> {\n const config = options.config ?? {};\n\n if (config.emailId === undefined || config.emailId === null || config.emailId === \"\") {\n throw new Error(`attachment_list: \"emailId\" is required (Email ID).`);\n }\n\n {\n const n = Number(config.limit);\n const given = config.limit !== undefined && config.limit !== null && config.limit !== \"\";\n if (given && !(Number.isInteger(n) && n >= 1 && n <= 100)) {\n throw new Error(\n `attachment_list: \"limit\" must be a integer, got ${JSON.stringify(config.limit)}.`,\n );\n }\n }\n\n return callConnector(RESEND, {\n operation: ATTACHMENT_LIST_OPERATION,\n config,\n input: options.input,\n ...(options.credentials === undefined ? {} : { credentials: options.credentials }),\n ...(options.mode === undefined ? {} : { mode: options.mode }),\n ...(options.connectionId === undefined ? {} : { connectionId: options.connectionId }),\n ...(options.attempts === undefined ? {} : { attempts: options.attempts }),\n ...(options.transport === undefined ? {} : { transport: options.transport }),\n request: {\n method: \"GET\",\n path: `/emails/receiving/${encodeURIComponent(String(config.emailId))}/attachments`,\n query: {\n ...(config.limit !== undefined && config.limit !== null && config.limit !== \"\" ? { \"limit\": Math.trunc(Number(config.limit)) } : {}),\n ...(config.after !== undefined && config.after !== null && config.after !== \"\" ? { \"after\": String(config.after) } : {}),\n ...(config.before !== undefined && config.before !== null && config.before !== \"\" ? { \"before\": String(config.before) } : {}),\n },\n },\n });\n}\n","/**\n * GENERATED FILE — do not edit.\n *\n * Emitted from provider/actions/email-get.json by weaver's generator.\n * A hand-edit here is destroyed by the next protocol sync, which is worse than\n * being rejected, because it works until it silently does not. Fix\n * provider/actions/email-get.json (or weaver's template/) and regenerate:\n *\n * npm run provider -- resend\n */\n\n/**\n * Read a received email in full: its bodies, its headers and the list of its\n * attachments.\n *\n * GET /emails/receiving/{emailId} —\n * https://resend.com/docs/api-reference/emails/retrieve-received-email\n *\n * Notice what is NOT here: no key, no base URL, no mode check, no retry loop,\n * no fake/real branch. This describes the request; callConnector resolves the\n * connection, picks the estate, and either calls Resend or calls the faker.\n */\n\nimport {\n callConnector,\n type ConnectorResult,\n type RequestedMode,\n type Transport,\n} from \"@particle-academy/fancy-connector-core\";\nimport { RESEND } from \"../service.js\";\n\nexport const EMAIL_GET_OPERATION = \"email_get\";\n\nexport type EmailGetOptions = {\n /** The node's resolved config. Keys: emailId. */\n config: Record<string, unknown>;\n credentials?: Record<string, string | undefined>;\n mode?: RequestedMode;\n connectionId?: string | null;\n input?: unknown;\n attempts?: number;\n /** Override the transport. The only way to exercise this without a network. */\n transport?: Transport;\n};\n\nexport async function resendEmailGet(options: EmailGetOptions): Promise<ConnectorResult> {\n const config = options.config ?? {};\n\n if (config.emailId === undefined || config.emailId === null || config.emailId === \"\") {\n throw new Error(`email_get: \"emailId\" is required (Email ID).`);\n }\n\n return callConnector(RESEND, {\n operation: EMAIL_GET_OPERATION,\n config,\n input: options.input,\n ...(options.credentials === undefined ? {} : { credentials: options.credentials }),\n ...(options.mode === undefined ? {} : { mode: options.mode }),\n ...(options.connectionId === undefined ? {} : { connectionId: options.connectionId }),\n ...(options.attempts === undefined ? {} : { attempts: options.attempts }),\n ...(options.transport === undefined ? {} : { transport: options.transport }),\n request: {\n method: \"GET\",\n path: `/emails/receiving/${encodeURIComponent(String(config.emailId))}`,\n query: {},\n },\n });\n}\n","/**\n * GENERATED FILE — do not edit.\n *\n * Emitted from provider/actions/email-send.json by weaver's generator.\n * A hand-edit here is destroyed by the next protocol sync, which is worse than\n * being rejected, because it works until it silently does not. Fix\n * provider/actions/email-send.json (or weaver's template/) and regenerate:\n *\n * npm run provider -- resend\n */\n\n/**\n * Send an email through Resend.\n *\n * POST /emails — https://resend.com/docs/api-reference/emails/send-email\n *\n * Notice what is NOT here: no key, no base URL, no mode check, no retry loop,\n * no fake/real branch. This describes the request; callConnector resolves the\n * connection, picks the estate, and either calls Resend or calls the faker.\n */\n\nimport {\n callConnector,\n type ConnectorResult,\n type RequestedMode,\n type Transport,\n} from \"@particle-academy/fancy-connector-core\";\nimport { RESEND } from \"../service.js\";\n\nexport const EMAIL_SEND_OPERATION = \"email_send\";\n\nexport type EmailSendOptions = {\n /** The node's resolved config. Keys: from, to, subject, html, text, replyTo, headers. */\n config: Record<string, unknown>;\n credentials?: Record<string, string | undefined>;\n mode?: RequestedMode;\n connectionId?: string | null;\n input?: unknown;\n /** Derived from the run and the step, never fresh. See the note above. */\n idempotencyKey?: string;\n attempts?: number;\n /** Override the transport. The only way to exercise this without a network. */\n transport?: Transport;\n};\n\nexport async function resendEmailSend(options: EmailSendOptions): Promise<ConnectorResult> {\n const config = options.config ?? {};\n\n if (config.from === undefined || config.from === null || config.from === \"\") {\n throw new Error(`email_send: \"from\" is required (From).`);\n }\n\n if (config.to === undefined || config.to === null || config.to === \"\") {\n throw new Error(`email_send: \"to\" is required (To).`);\n }\n\n if (!((config.html !== undefined && config.html !== null && config.html !== \"\") || (config.text !== undefined && config.text !== null && config.text !== \"\"))) {\n throw new Error(`email_send: needs an \"html\" or \"text\" body — an empty email is never intended.`);\n }\n\n return callConnector(RESEND, {\n operation: EMAIL_SEND_OPERATION,\n config,\n input: options.input,\n ...(options.credentials === undefined ? {} : { credentials: options.credentials }),\n ...(options.mode === undefined ? {} : { mode: options.mode }),\n ...(options.connectionId === undefined ? {} : { connectionId: options.connectionId }),\n ...(options.attempts === undefined ? {} : { attempts: options.attempts }),\n ...(options.transport === undefined ? {} : { transport: options.transport }),\n ...(options.idempotencyKey === undefined ? {} : { idempotencyKey: options.idempotencyKey }),\n request: {\n method: \"POST\",\n path: \"/emails\",\n json: {\n \"from\": String(config.from),\n \"to\": toList(config.to),\n \"subject\": config.subject !== undefined && config.subject !== null && config.subject !== \"\" ? String(config.subject) : \"\",\n ...(config.html !== undefined && config.html !== null && config.html !== \"\" ? { \"html\": String(config.html) } : {}),\n ...(config.text !== undefined && config.text !== null && config.text !== \"\" ? { \"text\": String(config.text) } : {}),\n ...(config.replyTo !== undefined && config.replyTo !== null && config.replyTo !== \"\" ? { \"reply_to\": String(config.replyTo) } : {}),\n \"headers\": headersMap(config.headers),\n },\n },\n });\n}\n\n/** One value, a \",\"-separated string, or an array — all end up a list. */\nfunction toList(value: unknown): string[] {\n const items = Array.isArray(value)\n ? value.map(String)\n : typeof value === \"string\"\n ? value.split(\",\")\n : [];\n\n return items.map((item) => item.trim()).filter(Boolean);\n}\n\n/** `{ k: \"v\" }` → `{ \"headers\": { \"k\": \"v\" } }` — a JSON body wants the real object. */\nfunction headersMap(value: unknown): Record<string, string> {\n if (!value || typeof value !== \"object\") return {};\n\n const out: Record<string, string> = {};\n for (const [key, item] of Object.entries(value as Record<string, unknown>)) {\n if (item !== undefined && item !== null && item !== \"\") out[key] = String(item);\n }\n\n return out;\n}\n","/**\n * GENERATED FILE — do not edit.\n *\n * Emitted from provider/triggers/email-received.json by weaver's generator.\n * A hand-edit here is destroyed by the next protocol sync, which is worse than\n * being rejected, because it works until it silently does not. Fix\n * provider/triggers/email-received.json (or weaver's template/) and regenerate:\n *\n * npm run provider -- resend\n */\n\n/**\n * Resend's webhook trigger — the delivery contract.\n *\n * Kept beside the service descriptor rather than inside a node, because a\n * signature scheme is a fact about RESEND. Two Resend triggers must not be\n * able to disagree about how a delivery is verified.\n */\n\nimport { verifyDelivery, type HmacScheme, type InboundDelivery, type TriggerDescriptor, type WebhookVerification } from \"@particle-academy/fancy-connector-core\";\nimport { resendFaker } from \"../faker.js\";\n\nexport const RESEND_EMAIL_RECEIVED_SIGNATURE_HEADER = \"svix-signature\";\n/** The provider's documented replay window, in seconds. */\nexport const RESEND_EMAIL_RECEIVED_TOLERANCE = 300;\n\nexport const RESEND_EMAIL_RECEIVED_SCHEME: HmacScheme = {\n algorithm: \"SHA-256\",\n payload: (raw, timestamp, id) => `${id}.${timestamp}.${raw}`,\n tolerance: RESEND_EMAIL_RECEIVED_TOLERANCE,\n encoding: \"base64\",\n secretEncoding: \"base64\",\n secretPrefix: \"whsec_\",\n};\n\n/**\n * Split `v1,…` into its parts.\n *\n * EVERY signature the header carries is collected, and the delivery passes\n * when ANY matches: a provider rolling a secret signs once per active secret,\n * and a first-only rule refused the whole roll as a wrong secret.\n *\n * `v1,<base64> v1,<base64>` -- several during a secret rotation, and Svix says\n * yours must match ONE of them. Every `v1` is offered to the verifier; the\n * first-only rule that Stripe's header once carried refused a whole roll.\n */\nexport function parseResendSignature(raw: string): {\n signatures: string[];\n timestamp?: string;\n} {\n const result: { signatures: string[]; timestamp?: string } = { signatures: [] };\n\n for (const part of raw.split(\" \")) {\n const [key, value] = part.trim().split(\",\", 2);\n if (value === undefined) continue;\n\n if (key === \"v1\") {\n result.signatures.push(value);\n }\n }\n\n return result;\n}\n\nexport const RESEND_EMAIL_RECEIVED: TriggerDescriptor = {\n service: \"resend\",\n operation: \"email_received\",\n delivery: \"webhook\",\n setup:\n \"Point a receiving domain's MX record at Resend, then in the Resend dashboard (Webhooks → Add webhook) point an endpoint at the route your host mounts for this trigger and subscribe it to email.received. Put the endpoint's signing secret -- shown as whsec_… -- on the connection as `webhookSecret`, exactly as shown.\",\n verification: {\n signatureHeader: RESEND_EMAIL_RECEIVED_SIGNATURE_HEADER,\n scheme: RESEND_EMAIL_RECEIVED_SCHEME,\n timestampHeader: \"svix-timestamp\",\n idHeader: \"svix-id\",\n parse: parseResendSignature,\n },\n faker: resendFaker,\n};\n\n/**\n * Verify one inbound Resend delivery.\n *\n * The host calls this BEFORE starting a run, with the body exactly as\n * received. Re-serialised JSON changes key order and whitespace, and produces\n * a mismatch that looks precisely like a wrong secret — hours of debugging the\n * wrong thing.\n *\n * The secret is the connection's `webhookSecret`.\n */\nexport function verifyResendDelivery(\n delivery: InboundDelivery,\n webhookSecret: string | undefined,\n now?: number,\n): Promise<WebhookVerification> {\n return verifyDelivery(RESEND_EMAIL_RECEIVED, delivery, webhookSecret, now);\n}\n"]}