@automate.ax/integration-contracts 0.98.0 → 0.99.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.
@@ -14,133 +14,171 @@ export const RESEND_EMAIL_EVENT_TYPES = [
14
14
  "email.suppressed",
15
15
  ] as const
16
16
 
17
+ export const RESEND_CONTACT_EVENT_TYPES = [
18
+ "contact.created",
19
+ "contact.updated",
20
+ "contact.deleted",
21
+ ] as const
22
+
23
+ export const RESEND_DOMAIN_EVENT_TYPES = [
24
+ "domain.created",
25
+ "domain.updated",
26
+ "domain.deleted",
27
+ ] as const
28
+
29
+ export const RESEND_SUPPRESSION_EVENT_TYPES = [
30
+ "suppression.added",
31
+ "suppression.removed",
32
+ ] as const
33
+
34
+ /** Every webhook event currently supported by Resend. */
35
+ export const RESEND_EVENT_TYPES = [
36
+ ...RESEND_EMAIL_EVENT_TYPES,
37
+ ...RESEND_CONTACT_EVENT_TYPES,
38
+ ...RESEND_DOMAIN_EVENT_TYPES,
39
+ ...RESEND_SUPPRESSION_EVENT_TYPES,
40
+ ] as const
41
+
17
42
  const RESEND_EMAIL_DATA_SCHEMA = z.object({
18
- /** Stable broadcast campaign ID, when the email came from a broadcast. */
19
43
  broadcastId: z.string().optional(),
20
-
21
- /** When Resend created the email. */
22
44
  createdAt: z.iso.datetime({ offset: true }),
23
-
24
- /** Stable Resend email ID. */
25
45
  emailId: z.string(),
26
-
27
- /** Sender address, optionally including a display name. */
28
46
  from: z.string(),
29
-
30
- /** RFC Message-ID header value. */
31
- messageId: z.string().optional(),
32
-
33
- /** Email subject. */
47
+ headers: z.object({ name: z.string(), value: z.string() }).array().optional(),
48
+ messageId: z.string(),
34
49
  subject: z.string(),
35
-
36
- /** Tags associated with the email. */
37
50
  tags: z.record(z.string(), z.string()).optional(),
38
-
39
- /** Stable template ID, when the email used a template. */
40
51
  templateId: z.string().optional(),
41
-
42
- /** Recipient addresses affected by this event. */
43
52
  to: z.string().array(),
44
53
  })
45
54
 
46
55
  const RESEND_BOUNCE_SCHEMA = z
47
56
  .looseObject({
48
- /** SMTP diagnostic responses returned by the receiving server. */
49
57
  diagnosticCode: z.string().array().optional(),
50
-
51
- /** Detailed bounce message returned by the receiving server. */
52
58
  message: z.string(),
53
-
54
- /** Provider bounce subtype. */
55
59
  subType: z.string(),
56
-
57
- /** Provider bounce type. */
58
60
  type: z.string(),
59
61
  })
60
62
  .catchall(z.json())
61
63
 
62
64
  const RESEND_CLICK_SCHEMA = z
63
65
  .looseObject({
64
- /** IP address that requested the tracked link. */
65
66
  ipAddress: z.string(),
66
-
67
- /** URL requested through the tracked link. */
68
67
  link: z.string(),
69
-
70
- /** When the tracked link was requested. */
71
68
  timestamp: z.iso.datetime({ offset: true }),
72
-
73
- /** User agent that requested the tracked link. */
74
69
  userAgent: z.string(),
75
70
  })
76
71
  .catchall(z.json())
77
72
 
78
73
  const RESEND_FAILED_SCHEMA = z
79
- .looseObject({
80
- /** Provider reason for the send failure. */
81
- reason: z.string(),
82
- })
74
+ .looseObject({ reason: z.string() })
83
75
  .catchall(z.json())
84
76
 
85
- const RESEND_SUPPRESSED_SCHEMA = z
77
+ const RESEND_EMAIL_SUPPRESSED_SCHEMA = z
86
78
  .looseObject({
87
- /** Explanation of why Resend suppressed the email. */
79
+ diagnosticCode: z.string().array().optional(),
88
80
  message: z.string(),
89
-
90
- /** Provider suppression type. */
81
+ reason: z.string().optional(),
91
82
  type: z.string(),
92
83
  })
93
84
  .catchall(z.json())
94
85
 
95
86
  const RESEND_RECEIVED_EMAIL_ATTACHMENT_SCHEMA = z
96
87
  .looseObject({
97
- /** MIME content disposition, when supplied. */
98
88
  contentDisposition: z.string().nullable(),
99
-
100
- /** Content-ID header, when supplied. */
101
89
  contentId: z.string().nullable(),
102
-
103
- /** Attachment MIME type. */
104
90
  contentType: z.string(),
105
-
106
- /** Attachment filename, when supplied. */
107
91
  filename: z.string().nullable(),
108
-
109
- /** Stable Resend attachment ID. */
110
92
  id: z.string(),
111
93
  })
112
94
  .catchall(z.json())
113
95
 
114
96
  const RESEND_RECEIVED_EMAIL_DATA_SCHEMA = z.object({
115
- /** Metadata for attachments included with the inbound email. */
116
97
  attachments: RESEND_RECEIVED_EMAIL_ATTACHMENT_SCHEMA.array(),
117
-
118
- /** Blind-copy recipient addresses. */
119
98
  bcc: z.string().array(),
120
-
121
- /** Copy recipient addresses. */
122
99
  cc: z.string().array(),
100
+ createdAt: z.iso.datetime({ offset: true }),
101
+ emailId: z.string(),
102
+ from: z.string(),
103
+ messageId: z.string(),
104
+ receivedFor: z.string().array().optional(),
105
+ subject: z.string(),
106
+ to: z.string().array(),
107
+ })
123
108
 
124
- /** When Resend created the inbound email record. */
109
+ const RESEND_CONTACT_DATA_SCHEMA = z.object({
110
+ audienceId: z.string().optional(),
125
111
  createdAt: z.iso.datetime({ offset: true }),
112
+ email: z.email(),
113
+ firstName: z.string().nullable().optional(),
114
+ id: z.string(),
115
+ lastName: z.string().nullable().optional(),
116
+ segmentIds: z.string().array().optional(),
117
+ unsubscribed: z.boolean(),
118
+ updatedAt: z.iso.datetime({ offset: true }),
119
+ })
126
120
 
127
- /** Stable Resend email ID. */
128
- emailId: z.string(),
121
+ export const RESEND_DOMAIN_STATUSES = [
122
+ "verified",
123
+ "partially_verified",
124
+ "partially_failed",
125
+ "failed",
126
+ "pending",
127
+ "not_started",
128
+ ] as const
129
129
 
130
- /** Bare sender address. */
131
- from: z.string(),
130
+ export const RESEND_DOMAIN_REGIONS = [
131
+ "us-east-1",
132
+ "eu-west-1",
133
+ "sa-east-1",
134
+ "ap-northeast-1",
135
+ ] as const
132
136
 
133
- /** RFC Message-ID header value. */
134
- messageId: z.string(),
137
+ export const RESEND_DOMAIN_RECORD_STATUSES = [
138
+ "pending",
139
+ "verified",
140
+ "failed",
141
+ "temporary_failure",
142
+ "not_started",
143
+ ] as const
135
144
 
136
- /** Addresses the email was forwarded for. */
137
- receivedFor: z.string().array().optional(),
145
+ const RESEND_DOMAIN_CAPABILITIES_SCHEMA = z.object({
146
+ receiving: z.enum(["enabled", "disabled"]).optional(),
147
+ sending: z.enum(["enabled", "disabled"]).optional(),
148
+ })
138
149
 
139
- /** Email subject. */
140
- subject: z.string(),
150
+ const RESEND_DOMAIN_RECORD_SCHEMA = z.object({
151
+ name: z.string(),
152
+ priority: z.number().optional(),
153
+ record: z.enum(["SPF", "DKIM", "Receiving MX", "Tracking", "TrackingCAA"]),
154
+ status: z.enum(RESEND_DOMAIN_RECORD_STATUSES),
155
+ ttl: z.string(),
156
+ type: z.enum(["MX", "TXT", "CNAME", "CAA"]),
157
+ value: z.string(),
158
+ })
141
159
 
142
- /** Direct recipient addresses. */
143
- to: z.string().array(),
160
+ const RESEND_DOMAIN_DATA_SCHEMA = z.object({
161
+ capabilities: RESEND_DOMAIN_CAPABILITIES_SCHEMA.optional(),
162
+ createdAt: z.iso.datetime({ offset: true }),
163
+ id: z.string(),
164
+ name: z.string(),
165
+ records: RESEND_DOMAIN_RECORD_SCHEMA.array(),
166
+ region: z.enum(RESEND_DOMAIN_REGIONS),
167
+ status: z.enum(RESEND_DOMAIN_STATUSES),
168
+ })
169
+
170
+ export const RESEND_SUPPRESSION_ORIGINS = [
171
+ "bounce",
172
+ "complaint",
173
+ "manual",
174
+ ] as const
175
+
176
+ const RESEND_SUPPRESSION_DATA_SCHEMA = z.object({
177
+ createdAt: z.iso.datetime({ offset: true }),
178
+ email: z.email(),
179
+ id: z.string(),
180
+ origin: z.enum(RESEND_SUPPRESSION_ORIGINS),
181
+ sourceId: z.string().nullable(),
144
182
  })
145
183
 
146
184
  const RESEND_PROVIDER_EMAIL_DATA_SCHEMA = z
@@ -149,7 +187,11 @@ const RESEND_PROVIDER_EMAIL_DATA_SCHEMA = z
149
187
  created_at: z.iso.datetime({ offset: true }),
150
188
  email_id: z.string(),
151
189
  from: z.string(),
152
- message_id: z.string().optional(),
190
+ headers: z
191
+ .object({ name: z.string(), value: z.string() })
192
+ .array()
193
+ .optional(),
194
+ message_id: z.string(),
153
195
  subject: z.string(),
154
196
  tags: z.record(z.string(), z.string()).optional(),
155
197
  template_id: z.string().optional(),
@@ -181,67 +223,139 @@ const RESEND_PROVIDER_RECEIVED_EMAIL_DATA_SCHEMA = z
181
223
  })
182
224
  .catchall(z.json())
183
225
 
184
- const RESEND_PROVIDER_EMAIL_EVENT_SCHEMA = z
226
+ const RESEND_PROVIDER_CONTACT_DATA_SCHEMA = z
185
227
  .looseObject({
228
+ audience_id: z.string().optional(),
186
229
  created_at: z.iso.datetime({ offset: true }),
187
- data: RESEND_PROVIDER_EMAIL_DATA_SCHEMA,
188
- type: z.enum(RESEND_EMAIL_EVENT_TYPES),
230
+ email: z.email(),
231
+ first_name: z.string().nullable().optional(),
232
+ id: z.string(),
233
+ last_name: z.string().nullable().optional(),
234
+ segment_ids: z.string().array().optional(),
235
+ unsubscribed: z.boolean(),
236
+ updated_at: z.iso.datetime({ offset: true }),
189
237
  })
190
238
  .catchall(z.json())
191
239
 
192
- const RESEND_PROVIDER_EMAIL_SENT_EVENT_SCHEMA =
193
- RESEND_PROVIDER_EMAIL_EVENT_SCHEMA.extend({ type: z.literal("email.sent") })
194
- const RESEND_PROVIDER_EMAIL_DELIVERED_EVENT_SCHEMA =
195
- RESEND_PROVIDER_EMAIL_EVENT_SCHEMA.extend({
196
- type: z.literal("email.delivered"),
197
- })
198
- const RESEND_PROVIDER_EMAIL_BOUNCED_EVENT_SCHEMA =
199
- RESEND_PROVIDER_EMAIL_EVENT_SCHEMA.extend({
200
- data: RESEND_PROVIDER_EMAIL_DATA_SCHEMA.extend({
201
- bounce: RESEND_BOUNCE_SCHEMA,
202
- }),
203
- type: z.literal("email.bounced"),
204
- })
205
- const RESEND_PROVIDER_EMAIL_FAILED_EVENT_SCHEMA =
206
- RESEND_PROVIDER_EMAIL_EVENT_SCHEMA.extend({
207
- data: RESEND_PROVIDER_EMAIL_DATA_SCHEMA.extend({
208
- failed: RESEND_FAILED_SCHEMA,
209
- }),
210
- type: z.literal("email.failed"),
211
- })
212
- const RESEND_PROVIDER_EMAIL_OPENED_EVENT_SCHEMA =
213
- RESEND_PROVIDER_EMAIL_EVENT_SCHEMA.extend({ type: z.literal("email.opened") })
214
- const RESEND_PROVIDER_EMAIL_CLICKED_EVENT_SCHEMA =
215
- RESEND_PROVIDER_EMAIL_EVENT_SCHEMA.extend({
216
- data: RESEND_PROVIDER_EMAIL_DATA_SCHEMA.extend({
217
- click: RESEND_CLICK_SCHEMA,
218
- }),
219
- type: z.literal("email.clicked"),
220
- })
221
- const RESEND_PROVIDER_EMAIL_COMPLAINED_EVENT_SCHEMA =
222
- RESEND_PROVIDER_EMAIL_EVENT_SCHEMA.extend({
223
- type: z.literal("email.complained"),
224
- })
225
- const RESEND_PROVIDER_EMAIL_RECEIVED_EVENT_SCHEMA =
226
- RESEND_PROVIDER_EMAIL_EVENT_SCHEMA.extend({
227
- data: RESEND_PROVIDER_RECEIVED_EMAIL_DATA_SCHEMA,
228
- type: z.literal("email.received"),
229
- })
230
- const RESEND_PROVIDER_EMAIL_DELIVERY_DELAYED_EVENT_SCHEMA =
231
- RESEND_PROVIDER_EMAIL_EVENT_SCHEMA.extend({
232
- type: z.literal("email.delivery_delayed"),
233
- })
234
- const RESEND_PROVIDER_EMAIL_SCHEDULED_EVENT_SCHEMA =
235
- RESEND_PROVIDER_EMAIL_EVENT_SCHEMA.extend({
236
- type: z.literal("email.scheduled"),
240
+ const RESEND_PROVIDER_DOMAIN_DATA_SCHEMA = z
241
+ .looseObject({
242
+ capabilities: RESEND_DOMAIN_CAPABILITIES_SCHEMA.optional(),
243
+ created_at: z.iso.datetime({ offset: true }),
244
+ id: z.string(),
245
+ name: z.string(),
246
+ records: RESEND_DOMAIN_RECORD_SCHEMA.array(),
247
+ region: z.enum(RESEND_DOMAIN_REGIONS),
248
+ status: z.enum(RESEND_DOMAIN_STATUSES),
237
249
  })
238
- const RESEND_PROVIDER_EMAIL_SUPPRESSED_EVENT_SCHEMA =
239
- RESEND_PROVIDER_EMAIL_EVENT_SCHEMA.extend({
240
- data: RESEND_PROVIDER_EMAIL_DATA_SCHEMA.extend({
241
- suppressed: RESEND_SUPPRESSED_SCHEMA,
242
- }),
243
- type: z.literal("email.suppressed"),
250
+ .catchall(z.json())
251
+
252
+ const RESEND_PROVIDER_SUPPRESSION_DATA_SCHEMA = z
253
+ .looseObject({
254
+ created_at: z.iso.datetime({ offset: true }),
255
+ email: z.email(),
256
+ id: z.string(),
257
+ origin: z.enum(RESEND_SUPPRESSION_ORIGINS),
258
+ source_id: z.string().nullable(),
244
259
  })
260
+ .catchall(z.json())
261
+
262
+ /**
263
+ * Creates one provider webhook envelope schema.
264
+ *
265
+ * @param type - Exact Resend event type.
266
+ * @param data - Provider event data schema.
267
+ */
268
+ function providerEventSchema<TType extends string, TData extends z.ZodType>(
269
+ type: TType,
270
+ data: TData,
271
+ ) {
272
+ return z
273
+ .looseObject({
274
+ created_at: z.iso.datetime({ offset: true }),
275
+ data,
276
+ type: z.literal(type),
277
+ })
278
+ .catchall(z.json())
279
+ }
280
+
281
+ const RESEND_PROVIDER_EMAIL_SENT_EVENT_SCHEMA = providerEventSchema(
282
+ "email.sent",
283
+ RESEND_PROVIDER_EMAIL_DATA_SCHEMA,
284
+ )
285
+ const RESEND_PROVIDER_EMAIL_SCHEDULED_EVENT_SCHEMA = providerEventSchema(
286
+ "email.scheduled",
287
+ RESEND_PROVIDER_EMAIL_DATA_SCHEMA,
288
+ )
289
+ const RESEND_PROVIDER_EMAIL_DELIVERED_EVENT_SCHEMA = providerEventSchema(
290
+ "email.delivered",
291
+ RESEND_PROVIDER_EMAIL_DATA_SCHEMA,
292
+ )
293
+ const RESEND_PROVIDER_EMAIL_DELIVERY_DELAYED_EVENT_SCHEMA = providerEventSchema(
294
+ "email.delivery_delayed",
295
+ RESEND_PROVIDER_EMAIL_DATA_SCHEMA,
296
+ )
297
+ const RESEND_PROVIDER_EMAIL_COMPLAINED_EVENT_SCHEMA = providerEventSchema(
298
+ "email.complained",
299
+ RESEND_PROVIDER_EMAIL_DATA_SCHEMA,
300
+ )
301
+ const RESEND_PROVIDER_EMAIL_BOUNCED_EVENT_SCHEMA = providerEventSchema(
302
+ "email.bounced",
303
+ RESEND_PROVIDER_EMAIL_DATA_SCHEMA.extend({ bounce: RESEND_BOUNCE_SCHEMA }),
304
+ )
305
+ const RESEND_PROVIDER_EMAIL_OPENED_EVENT_SCHEMA = providerEventSchema(
306
+ "email.opened",
307
+ RESEND_PROVIDER_EMAIL_DATA_SCHEMA,
308
+ )
309
+ const RESEND_PROVIDER_EMAIL_CLICKED_EVENT_SCHEMA = providerEventSchema(
310
+ "email.clicked",
311
+ RESEND_PROVIDER_EMAIL_DATA_SCHEMA.extend({ click: RESEND_CLICK_SCHEMA }),
312
+ )
313
+ const RESEND_PROVIDER_EMAIL_RECEIVED_EVENT_SCHEMA = providerEventSchema(
314
+ "email.received",
315
+ RESEND_PROVIDER_RECEIVED_EMAIL_DATA_SCHEMA,
316
+ )
317
+ const RESEND_PROVIDER_EMAIL_FAILED_EVENT_SCHEMA = providerEventSchema(
318
+ "email.failed",
319
+ RESEND_PROVIDER_EMAIL_DATA_SCHEMA.extend({ failed: RESEND_FAILED_SCHEMA }),
320
+ )
321
+ const RESEND_PROVIDER_EMAIL_SUPPRESSED_EVENT_SCHEMA = providerEventSchema(
322
+ "email.suppressed",
323
+ RESEND_PROVIDER_EMAIL_DATA_SCHEMA.extend({
324
+ suppressed: RESEND_EMAIL_SUPPRESSED_SCHEMA,
325
+ }),
326
+ )
327
+ const RESEND_PROVIDER_CONTACT_CREATED_EVENT_SCHEMA = providerEventSchema(
328
+ "contact.created",
329
+ RESEND_PROVIDER_CONTACT_DATA_SCHEMA,
330
+ )
331
+ const RESEND_PROVIDER_CONTACT_UPDATED_EVENT_SCHEMA = providerEventSchema(
332
+ "contact.updated",
333
+ RESEND_PROVIDER_CONTACT_DATA_SCHEMA,
334
+ )
335
+ const RESEND_PROVIDER_CONTACT_DELETED_EVENT_SCHEMA = providerEventSchema(
336
+ "contact.deleted",
337
+ RESEND_PROVIDER_CONTACT_DATA_SCHEMA,
338
+ )
339
+ const RESEND_PROVIDER_DOMAIN_CREATED_EVENT_SCHEMA = providerEventSchema(
340
+ "domain.created",
341
+ RESEND_PROVIDER_DOMAIN_DATA_SCHEMA,
342
+ )
343
+ const RESEND_PROVIDER_DOMAIN_UPDATED_EVENT_SCHEMA = providerEventSchema(
344
+ "domain.updated",
345
+ RESEND_PROVIDER_DOMAIN_DATA_SCHEMA,
346
+ )
347
+ const RESEND_PROVIDER_DOMAIN_DELETED_EVENT_SCHEMA = providerEventSchema(
348
+ "domain.deleted",
349
+ RESEND_PROVIDER_DOMAIN_DATA_SCHEMA,
350
+ )
351
+ const RESEND_PROVIDER_SUPPRESSION_ADDED_EVENT_SCHEMA = providerEventSchema(
352
+ "suppression.added",
353
+ RESEND_PROVIDER_SUPPRESSION_DATA_SCHEMA,
354
+ )
355
+ const RESEND_PROVIDER_SUPPRESSION_REMOVED_EVENT_SCHEMA = providerEventSchema(
356
+ "suppression.removed",
357
+ RESEND_PROVIDER_SUPPRESSION_DATA_SCHEMA,
358
+ )
245
359
 
246
360
  const RESEND_PROVIDER_WEBHOOK_SCHEMA = z.discriminatedUnion("type", [
247
361
  RESEND_PROVIDER_EMAIL_BOUNCED_EVENT_SCHEMA,
@@ -255,86 +369,59 @@ const RESEND_PROVIDER_WEBHOOK_SCHEMA = z.discriminatedUnion("type", [
255
369
  RESEND_PROVIDER_EMAIL_SCHEDULED_EVENT_SCHEMA,
256
370
  RESEND_PROVIDER_EMAIL_SENT_EVENT_SCHEMA,
257
371
  RESEND_PROVIDER_EMAIL_SUPPRESSED_EVENT_SCHEMA,
372
+ RESEND_PROVIDER_CONTACT_CREATED_EVENT_SCHEMA,
373
+ RESEND_PROVIDER_CONTACT_UPDATED_EVENT_SCHEMA,
374
+ RESEND_PROVIDER_CONTACT_DELETED_EVENT_SCHEMA,
375
+ RESEND_PROVIDER_DOMAIN_CREATED_EVENT_SCHEMA,
376
+ RESEND_PROVIDER_DOMAIN_UPDATED_EVENT_SCHEMA,
377
+ RESEND_PROVIDER_DOMAIN_DELETED_EVENT_SCHEMA,
378
+ RESEND_PROVIDER_SUPPRESSION_ADDED_EVENT_SCHEMA,
379
+ RESEND_PROVIDER_SUPPRESSION_REMOVED_EVENT_SCHEMA,
258
380
  ])
259
381
 
260
- export const RESEND_EMAIL_SENT_EVENT_SCHEMA = RESEND_EMAIL_DATA_SCHEMA.extend({
261
- /** Original provider webhook envelope. */
262
- event: RESEND_PROVIDER_EMAIL_SENT_EVENT_SCHEMA,
263
- })
264
-
265
- export const RESEND_EMAIL_DELIVERED_EVENT_SCHEMA =
266
- RESEND_EMAIL_DATA_SCHEMA.extend({
267
- /** Original provider webhook envelope. */
268
- event: RESEND_PROVIDER_EMAIL_DELIVERED_EVENT_SCHEMA,
269
- })
270
-
271
- export const RESEND_EMAIL_BOUNCED_EVENT_SCHEMA =
272
- RESEND_EMAIL_DATA_SCHEMA.extend({
273
- /** Bounce details from the receiving server. */
274
- bounce: RESEND_BOUNCE_SCHEMA,
275
-
276
- /** Original provider webhook envelope. */
277
- event: RESEND_PROVIDER_EMAIL_BOUNCED_EVENT_SCHEMA,
278
- })
279
-
280
- export const RESEND_EMAIL_FAILED_EVENT_SCHEMA = RESEND_EMAIL_DATA_SCHEMA.extend(
281
- {
282
- /** Original provider webhook envelope. */
283
- event: RESEND_PROVIDER_EMAIL_FAILED_EVENT_SCHEMA,
382
+ /**
383
+ * Attaches one provider event envelope to normalized email data.
384
+ *
385
+ * @param event - Exact provider email-event schema.
386
+ */
387
+ function emailEventSchema<TEvent extends z.ZodType>(event: TEvent) {
388
+ return RESEND_EMAIL_DATA_SCHEMA.extend({ event })
389
+ }
284
390
 
285
- /** Send failure details. */
286
- failed: RESEND_FAILED_SCHEMA,
287
- },
391
+ export const RESEND_EMAIL_SENT_EVENT_SCHEMA = emailEventSchema(
392
+ RESEND_PROVIDER_EMAIL_SENT_EVENT_SCHEMA,
288
393
  )
289
-
290
- export const RESEND_EMAIL_OPENED_EVENT_SCHEMA = RESEND_EMAIL_DATA_SCHEMA.extend(
291
- {
292
- /** Original provider webhook envelope. */
293
- event: RESEND_PROVIDER_EMAIL_OPENED_EVENT_SCHEMA,
294
- },
394
+ export const RESEND_EMAIL_SCHEDULED_EVENT_SCHEMA = emailEventSchema(
395
+ RESEND_PROVIDER_EMAIL_SCHEDULED_EVENT_SCHEMA,
295
396
  )
296
-
297
- export const RESEND_EMAIL_CLICKED_EVENT_SCHEMA =
298
- RESEND_EMAIL_DATA_SCHEMA.extend({
299
- /** Click tracking details. */
300
- click: RESEND_CLICK_SCHEMA,
301
-
302
- /** Original provider webhook envelope. */
303
- event: RESEND_PROVIDER_EMAIL_CLICKED_EVENT_SCHEMA,
304
- })
305
-
306
- export const RESEND_EMAIL_COMPLAINED_EVENT_SCHEMA =
307
- RESEND_EMAIL_DATA_SCHEMA.extend({
308
- /** Original provider webhook envelope. */
309
- event: RESEND_PROVIDER_EMAIL_COMPLAINED_EVENT_SCHEMA,
310
- })
311
-
397
+ export const RESEND_EMAIL_DELIVERED_EVENT_SCHEMA = emailEventSchema(
398
+ RESEND_PROVIDER_EMAIL_DELIVERED_EVENT_SCHEMA,
399
+ )
400
+ export const RESEND_EMAIL_DELIVERY_DELAYED_EVENT_SCHEMA = emailEventSchema(
401
+ RESEND_PROVIDER_EMAIL_DELIVERY_DELAYED_EVENT_SCHEMA,
402
+ )
403
+ export const RESEND_EMAIL_COMPLAINED_EVENT_SCHEMA = emailEventSchema(
404
+ RESEND_PROVIDER_EMAIL_COMPLAINED_EVENT_SCHEMA,
405
+ )
406
+ export const RESEND_EMAIL_BOUNCED_EVENT_SCHEMA = emailEventSchema(
407
+ RESEND_PROVIDER_EMAIL_BOUNCED_EVENT_SCHEMA,
408
+ ).extend({ bounce: RESEND_BOUNCE_SCHEMA })
409
+ export const RESEND_EMAIL_OPENED_EVENT_SCHEMA = emailEventSchema(
410
+ RESEND_PROVIDER_EMAIL_OPENED_EVENT_SCHEMA,
411
+ )
412
+ export const RESEND_EMAIL_CLICKED_EVENT_SCHEMA = emailEventSchema(
413
+ RESEND_PROVIDER_EMAIL_CLICKED_EVENT_SCHEMA,
414
+ ).extend({ click: RESEND_CLICK_SCHEMA })
312
415
  export const RESEND_EMAIL_RECEIVED_EVENT_SCHEMA =
313
416
  RESEND_RECEIVED_EMAIL_DATA_SCHEMA.extend({
314
- /** Original provider webhook envelope. */
315
417
  event: RESEND_PROVIDER_EMAIL_RECEIVED_EVENT_SCHEMA,
316
418
  })
317
-
318
- export const RESEND_EMAIL_DELIVERY_DELAYED_EVENT_SCHEMA =
319
- RESEND_EMAIL_DATA_SCHEMA.extend({
320
- /** Original provider webhook envelope. */
321
- event: RESEND_PROVIDER_EMAIL_DELIVERY_DELAYED_EVENT_SCHEMA,
322
- })
323
-
324
- export const RESEND_EMAIL_SCHEDULED_EVENT_SCHEMA =
325
- RESEND_EMAIL_DATA_SCHEMA.extend({
326
- /** Original provider webhook envelope. */
327
- event: RESEND_PROVIDER_EMAIL_SCHEDULED_EVENT_SCHEMA,
328
- })
329
-
330
- export const RESEND_EMAIL_SUPPRESSED_EVENT_SCHEMA =
331
- RESEND_EMAIL_DATA_SCHEMA.extend({
332
- /** Original provider webhook envelope. */
333
- event: RESEND_PROVIDER_EMAIL_SUPPRESSED_EVENT_SCHEMA,
334
-
335
- /** Details explaining why Resend suppressed the email. */
336
- suppressed: RESEND_SUPPRESSED_SCHEMA,
337
- })
419
+ export const RESEND_EMAIL_FAILED_EVENT_SCHEMA = emailEventSchema(
420
+ RESEND_PROVIDER_EMAIL_FAILED_EVENT_SCHEMA,
421
+ ).extend({ failed: RESEND_FAILED_SCHEMA })
422
+ export const RESEND_EMAIL_SUPPRESSED_EVENT_SCHEMA = emailEventSchema(
423
+ RESEND_PROVIDER_EMAIL_SUPPRESSED_EVENT_SCHEMA,
424
+ ).extend({ suppressed: RESEND_EMAIL_SUPPRESSED_SCHEMA })
338
425
 
339
426
  export const RESEND_EMAIL_EVENT_SCHEMA = z.union([
340
427
  RESEND_EMAIL_BOUNCED_EVENT_SCHEMA,
@@ -350,14 +437,107 @@ export const RESEND_EMAIL_EVENT_SCHEMA = z.union([
350
437
  RESEND_EMAIL_SUPPRESSED_EVENT_SCHEMA,
351
438
  ])
352
439
 
440
+ /**
441
+ * Attaches one provider event envelope to normalized contact data.
442
+ *
443
+ * @param event - Exact provider contact-event schema.
444
+ */
445
+ function contactEventSchema<TEvent extends z.ZodType>(event: TEvent) {
446
+ return RESEND_CONTACT_DATA_SCHEMA.extend({ event })
447
+ }
448
+
449
+ export const RESEND_CONTACT_CREATED_EVENT_SCHEMA = contactEventSchema(
450
+ RESEND_PROVIDER_CONTACT_CREATED_EVENT_SCHEMA,
451
+ )
452
+ export const RESEND_CONTACT_UPDATED_EVENT_SCHEMA = contactEventSchema(
453
+ RESEND_PROVIDER_CONTACT_UPDATED_EVENT_SCHEMA,
454
+ )
455
+ export const RESEND_CONTACT_DELETED_EVENT_SCHEMA = contactEventSchema(
456
+ RESEND_PROVIDER_CONTACT_DELETED_EVENT_SCHEMA,
457
+ )
458
+ export const RESEND_CONTACT_EVENT_SCHEMA = z.union([
459
+ RESEND_CONTACT_CREATED_EVENT_SCHEMA,
460
+ RESEND_CONTACT_UPDATED_EVENT_SCHEMA,
461
+ RESEND_CONTACT_DELETED_EVENT_SCHEMA,
462
+ ])
463
+
464
+ /**
465
+ * Attaches one provider event envelope to normalized domain data.
466
+ *
467
+ * @param event - Exact provider domain-event schema.
468
+ */
469
+ function domainEventSchema<TEvent extends z.ZodType>(event: TEvent) {
470
+ return RESEND_DOMAIN_DATA_SCHEMA.extend({ event })
471
+ }
472
+
473
+ export const RESEND_DOMAIN_CREATED_EVENT_SCHEMA = domainEventSchema(
474
+ RESEND_PROVIDER_DOMAIN_CREATED_EVENT_SCHEMA,
475
+ )
476
+ export const RESEND_DOMAIN_UPDATED_EVENT_SCHEMA = domainEventSchema(
477
+ RESEND_PROVIDER_DOMAIN_UPDATED_EVENT_SCHEMA,
478
+ )
479
+ export const RESEND_DOMAIN_DELETED_EVENT_SCHEMA = domainEventSchema(
480
+ RESEND_PROVIDER_DOMAIN_DELETED_EVENT_SCHEMA,
481
+ )
482
+ export const RESEND_DOMAIN_EVENT_SCHEMA = z.union([
483
+ RESEND_DOMAIN_CREATED_EVENT_SCHEMA,
484
+ RESEND_DOMAIN_UPDATED_EVENT_SCHEMA,
485
+ RESEND_DOMAIN_DELETED_EVENT_SCHEMA,
486
+ ])
487
+
488
+ /**
489
+ * Attaches one provider event envelope to normalized suppression data.
490
+ *
491
+ * @param event - Exact provider suppression-event schema.
492
+ */
493
+ function suppressionEventSchema<TEvent extends z.ZodType>(event: TEvent) {
494
+ return RESEND_SUPPRESSION_DATA_SCHEMA.extend({ event })
495
+ }
496
+
497
+ export const RESEND_SUPPRESSION_ADDED_EVENT_SCHEMA = suppressionEventSchema(
498
+ RESEND_PROVIDER_SUPPRESSION_ADDED_EVENT_SCHEMA,
499
+ )
500
+ export const RESEND_SUPPRESSION_REMOVED_EVENT_SCHEMA = suppressionEventSchema(
501
+ RESEND_PROVIDER_SUPPRESSION_REMOVED_EVENT_SCHEMA,
502
+ )
503
+ export const RESEND_SUPPRESSION_EVENT_SCHEMA = z.union([
504
+ RESEND_SUPPRESSION_ADDED_EVENT_SCHEMA,
505
+ RESEND_SUPPRESSION_REMOVED_EVENT_SCHEMA,
506
+ ])
507
+
508
+ export const RESEND_EVENT_SCHEMA = z.union([
509
+ RESEND_EMAIL_EVENT_SCHEMA,
510
+ RESEND_CONTACT_EVENT_SCHEMA,
511
+ RESEND_DOMAIN_EVENT_SCHEMA,
512
+ RESEND_SUPPRESSION_EVENT_SCHEMA,
513
+ ])
514
+
515
+ /**
516
+ * Normalizes one authenticated Resend webhook.
517
+ *
518
+ * @param value - Untrusted provider webhook payload.
519
+ */
520
+ export function normalizeResendEvent(value: unknown) {
521
+ return normalizeProviderEvent(RESEND_PROVIDER_WEBHOOK_SCHEMA.parse(value))
522
+ }
523
+
353
524
  /**
354
525
  * Normalizes one authenticated Resend email webhook.
355
526
  *
356
527
  * @param value - Untrusted provider webhook payload.
357
528
  */
358
529
  export function normalizeResendEmailEvent(value: unknown) {
359
- const event = RESEND_PROVIDER_WEBHOOK_SCHEMA.parse(value)
530
+ return RESEND_EMAIL_EVENT_SCHEMA.parse(normalizeResendEvent(value))
531
+ }
360
532
 
533
+ /**
534
+ * Normalizes one validated provider event by its exact type.
535
+ *
536
+ * @param event - Validated Resend provider event.
537
+ */
538
+ function normalizeProviderEvent(
539
+ event: z.output<typeof RESEND_PROVIDER_WEBHOOK_SCHEMA>,
540
+ ) {
361
541
  switch (event.type) {
362
542
  case "email.bounced":
363
543
  return RESEND_EMAIL_BOUNCED_EVENT_SCHEMA.parse({
@@ -406,42 +586,42 @@ export function normalizeResendEmailEvent(value: unknown) {
406
586
  suppressed: event.data.suppressed,
407
587
  })
408
588
  case "email.complained":
409
- return RESEND_EMAIL_COMPLAINED_EVENT_SCHEMA.parse({
410
- ...normalizeResendEmailData(event.data),
411
- event,
412
- })
413
589
  case "email.delivered":
414
- return RESEND_EMAIL_DELIVERED_EVENT_SCHEMA.parse({
415
- ...normalizeResendEmailData(event.data),
416
- event,
417
- })
418
590
  case "email.delivery_delayed":
419
- return RESEND_EMAIL_DELIVERY_DELAYED_EVENT_SCHEMA.parse({
420
- ...normalizeResendEmailData(event.data),
421
- event,
422
- })
423
591
  case "email.opened":
424
- return RESEND_EMAIL_OPENED_EVENT_SCHEMA.parse({
425
- ...normalizeResendEmailData(event.data),
426
- event,
427
- })
428
592
  case "email.scheduled":
429
- return RESEND_EMAIL_SCHEDULED_EVENT_SCHEMA.parse({
430
- ...normalizeResendEmailData(event.data),
431
- event,
432
- })
433
593
  case "email.sent":
434
- return RESEND_EMAIL_SENT_EVENT_SCHEMA.parse({
594
+ return {
435
595
  ...normalizeResendEmailData(event.data),
436
596
  event,
437
- })
597
+ }
598
+ case "contact.created":
599
+ case "contact.updated":
600
+ case "contact.deleted":
601
+ return {
602
+ ...normalizeResendContactData(event.data),
603
+ event,
604
+ }
605
+ case "domain.created":
606
+ case "domain.updated":
607
+ case "domain.deleted":
608
+ return {
609
+ ...normalizeResendDomainData(event.data),
610
+ event,
611
+ }
612
+ case "suppression.added":
613
+ case "suppression.removed":
614
+ return {
615
+ ...normalizeResendSuppressionData(event.data),
616
+ event,
617
+ }
438
618
  }
439
619
  }
440
620
 
441
621
  /**
442
- * Normalizes common outbound email webhook data.
622
+ * Normalizes shared Resend email event fields.
443
623
  *
444
- * @param data - Provider-native email data.
624
+ * @param data - Provider email event data.
445
625
  */
446
626
  function normalizeResendEmailData(
447
627
  data: z.output<typeof RESEND_PROVIDER_EMAIL_DATA_SCHEMA>,
@@ -453,10 +633,70 @@ function normalizeResendEmailData(
453
633
  createdAt: data.created_at,
454
634
  emailId: data.email_id,
455
635
  from: data.from,
456
- ...(data.message_id === undefined ? {} : { messageId: data.message_id }),
636
+ ...(data.headers === undefined ? {} : { headers: data.headers }),
637
+ messageId: data.message_id,
457
638
  subject: data.subject,
458
639
  ...(data.tags === undefined ? {} : { tags: data.tags }),
459
640
  ...(data.template_id === undefined ? {} : { templateId: data.template_id }),
460
641
  to: data.to,
461
642
  }
462
643
  }
644
+
645
+ /**
646
+ * Normalizes shared Resend contact event fields.
647
+ *
648
+ * @param data - Provider contact event data.
649
+ */
650
+ function normalizeResendContactData(
651
+ data: z.output<typeof RESEND_PROVIDER_CONTACT_DATA_SCHEMA>,
652
+ ) {
653
+ return {
654
+ ...(data.audience_id === undefined ? {} : { audienceId: data.audience_id }),
655
+ createdAt: data.created_at,
656
+ email: data.email,
657
+ ...(data.first_name === undefined ? {} : { firstName: data.first_name }),
658
+ id: data.id,
659
+ ...(data.last_name === undefined ? {} : { lastName: data.last_name }),
660
+ ...(data.segment_ids === undefined ? {} : { segmentIds: data.segment_ids }),
661
+ unsubscribed: data.unsubscribed,
662
+ updatedAt: data.updated_at,
663
+ }
664
+ }
665
+
666
+ /**
667
+ * Normalizes shared Resend domain event fields.
668
+ *
669
+ * @param data - Provider domain event data.
670
+ */
671
+ function normalizeResendDomainData(
672
+ data: z.output<typeof RESEND_PROVIDER_DOMAIN_DATA_SCHEMA>,
673
+ ) {
674
+ return {
675
+ ...(data.capabilities === undefined
676
+ ? {}
677
+ : { capabilities: data.capabilities }),
678
+ createdAt: data.created_at,
679
+ id: data.id,
680
+ name: data.name,
681
+ records: data.records,
682
+ region: data.region,
683
+ status: data.status,
684
+ }
685
+ }
686
+
687
+ /**
688
+ * Normalizes shared Resend suppression event fields.
689
+ *
690
+ * @param data - Provider suppression event data.
691
+ */
692
+ function normalizeResendSuppressionData(
693
+ data: z.output<typeof RESEND_PROVIDER_SUPPRESSION_DATA_SCHEMA>,
694
+ ) {
695
+ return {
696
+ createdAt: data.created_at,
697
+ email: data.email,
698
+ id: data.id,
699
+ origin: data.origin,
700
+ sourceId: data.source_id,
701
+ }
702
+ }