@porulle/adapter-resend 0.64.0 → 0.65.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -31
- package/package.json +11 -6
- package/src/index.ts +8 -43
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACnC,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,CAAC;IACrE;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,CAAC;IACtE;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG;IAC5D,IAAI,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9F,CA4CA"}
|
package/dist/index.js
CHANGED
|
@@ -1,24 +1,5 @@
|
|
|
1
|
+
import { renderEmail } from "@porulle/core";
|
|
1
2
|
import { Resend } from "resend";
|
|
2
|
-
const DEFAULT_SUBJECTS = {
|
|
3
|
-
"order-confirmation": (d) => `Order Confirmed${d.orderId ? ` - #${String(d.orderId).slice(0, 8)}` : ""}`,
|
|
4
|
-
"order-status-change": (d) => `Order Update - ${d.newStatus ?? "Status Changed"}`,
|
|
5
|
-
"password-reset": () => "Reset Your Password",
|
|
6
|
-
"email-verification": () => "Verify Your Email Address",
|
|
7
|
-
"appointment:reminder": (d) => `Appointment Reminder${d.reminderType === "1h" ? " - Starting Soon" : ""}`,
|
|
8
|
-
"appointment:confirmation-notice": () => "Appointment Confirmed",
|
|
9
|
-
"appointment:cancellation-notice": () => "Appointment Cancelled",
|
|
10
|
-
"appointment:no-show-notice": () => "Missed Appointment",
|
|
11
|
-
};
|
|
12
|
-
const DEFAULT_TEMPLATES = {
|
|
13
|
-
"order-confirmation": (d) => `<h2>Order Confirmed</h2><p>Thank you for your order${d.orderId ? ` <strong>#${String(d.orderId).slice(0, 8)}</strong>` : ""}.</p>${d.total ? `<p>Total: ${d.currency ?? "USD"} ${String(d.total)}</p>` : ""}`,
|
|
14
|
-
"order-status-change": (d) => `<h2>Order Update</h2><p>Your order${d.orderId ? ` <strong>#${String(d.orderId).slice(0, 8)}</strong>` : ""} status has been updated to <strong>${d.newStatus ?? "unknown"}</strong>.</p>`,
|
|
15
|
-
"password-reset": (d) => `<h2>Reset Your Password</h2><p>Click the link below to reset your password:</p><p><a href="${d.url ?? "#"}">Reset Password</a></p>`,
|
|
16
|
-
"email-verification": (d) => `<h2>Verify Your Email</h2><p>Click the link below to verify your email address:</p><p><a href="${d.url ?? "#"}">Verify Email</a></p>`,
|
|
17
|
-
"appointment:reminder": (d) => `<h2>Appointment Reminder</h2><p>This is a${d.reminderType === "1h" ? " 1-hour" : " 24-hour"} reminder for your upcoming appointment.</p><p>Booking ID: ${d.bookingId ?? "N/A"}</p>`,
|
|
18
|
-
"appointment:confirmation-notice": (d) => `<h2>Appointment Confirmed</h2><p>Your appointment has been confirmed.</p><p>Booking ID: ${d.bookingId ?? "N/A"}</p>`,
|
|
19
|
-
"appointment:cancellation-notice": (d) => `<h2>Appointment Cancelled</h2><p>Your appointment has been cancelled.</p><p>Booking ID: ${d.bookingId ?? "N/A"}</p>`,
|
|
20
|
-
"appointment:no-show-notice": (d) => `<h2>Missed Appointment</h2><p>You missed your appointment. Please contact us to rebook.</p><p>Booking ID: ${d.bookingId ?? "N/A"}</p>`,
|
|
21
|
-
};
|
|
22
3
|
/**
|
|
23
4
|
* Creates an email adapter backed by Resend.
|
|
24
5
|
*
|
|
@@ -39,13 +20,13 @@ const DEFAULT_TEMPLATES = {
|
|
|
39
20
|
*/
|
|
40
21
|
export function resendAdapter(options) {
|
|
41
22
|
const resend = new Resend(options.apiKey);
|
|
42
|
-
const subjects = { ...DEFAULT_SUBJECTS, ...options.subjects };
|
|
43
|
-
const templates = { ...DEFAULT_TEMPLATES, ...options.templates };
|
|
44
23
|
return {
|
|
45
24
|
async send(input) {
|
|
46
25
|
const data = input.data ?? {};
|
|
47
|
-
const
|
|
48
|
-
|
|
26
|
+
const rendered = renderEmail(input.template, data, {
|
|
27
|
+
...(options.subjects ? { subjects: options.subjects } : {}),
|
|
28
|
+
...(options.templates ? { templates: options.templates } : {}),
|
|
29
|
+
});
|
|
49
30
|
// If a Resend template ID is configured, use server-side template rendering
|
|
50
31
|
const resendTemplateId = options.resendTemplateIds?.[input.template];
|
|
51
32
|
if (resendTemplateId) {
|
|
@@ -54,7 +35,7 @@ export function resendAdapter(options) {
|
|
|
54
35
|
const { error: templateError } = await resend.emails.send({
|
|
55
36
|
from: options.from,
|
|
56
37
|
to: [input.to],
|
|
57
|
-
subject,
|
|
38
|
+
subject: rendered.subject,
|
|
58
39
|
template: {
|
|
59
40
|
id: resendTemplateId,
|
|
60
41
|
variables: data,
|
|
@@ -66,15 +47,11 @@ export function resendAdapter(options) {
|
|
|
66
47
|
return;
|
|
67
48
|
}
|
|
68
49
|
// Otherwise, use local HTML template
|
|
69
|
-
const templateFn = templates[input.template];
|
|
70
|
-
const html = templateFn
|
|
71
|
-
? templateFn(data)
|
|
72
|
-
: `<p>Notification: ${input.template}</p><pre>${JSON.stringify(data, null, 2)}</pre>`;
|
|
73
50
|
const { error } = await resend.emails.send({
|
|
74
51
|
from: options.from,
|
|
75
52
|
to: [input.to],
|
|
76
|
-
subject,
|
|
77
|
-
html,
|
|
53
|
+
subject: rendered.subject,
|
|
54
|
+
html: rendered.html,
|
|
78
55
|
});
|
|
79
56
|
if (error) {
|
|
80
57
|
throw new Error(`Resend email failed: ${error.message}`);
|
package/package.json
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@porulle/adapter-resend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.65.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
}
|
|
8
|
+
"@porulle/source": "./src/index.ts",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./package.json": "./package.json"
|
|
13
|
+
},
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=20.19.0"
|
|
12
16
|
},
|
|
13
17
|
"dependencies": {
|
|
14
|
-
"resend": "^4.0.0"
|
|
18
|
+
"resend": "^4.0.0",
|
|
19
|
+
"@porulle/core": "0.65.1"
|
|
15
20
|
},
|
|
16
21
|
"devDependencies": {
|
|
17
22
|
"@types/node": "^24.5.2",
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { renderEmail } from "@porulle/core";
|
|
1
2
|
import { Resend } from "resend";
|
|
2
3
|
|
|
3
4
|
export interface ResendAdapterOptions {
|
|
@@ -22,36 +23,6 @@ export interface ResendAdapterOptions {
|
|
|
22
23
|
resendTemplateIds?: Record<string, string>;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
const DEFAULT_SUBJECTS: Record<string, (data: Record<string, unknown>) => string> = {
|
|
26
|
-
"order-confirmation": (d) => `Order Confirmed${d.orderId ? ` - #${String(d.orderId).slice(0, 8)}` : ""}`,
|
|
27
|
-
"order-status-change": (d) => `Order Update - ${d.newStatus ?? "Status Changed"}`,
|
|
28
|
-
"password-reset": () => "Reset Your Password",
|
|
29
|
-
"email-verification": () => "Verify Your Email Address",
|
|
30
|
-
"appointment:reminder": (d) => `Appointment Reminder${d.reminderType === "1h" ? " - Starting Soon" : ""}`,
|
|
31
|
-
"appointment:confirmation-notice": () => "Appointment Confirmed",
|
|
32
|
-
"appointment:cancellation-notice": () => "Appointment Cancelled",
|
|
33
|
-
"appointment:no-show-notice": () => "Missed Appointment",
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const DEFAULT_TEMPLATES: Record<string, (data: Record<string, unknown>) => string> = {
|
|
37
|
-
"order-confirmation": (d) =>
|
|
38
|
-
`<h2>Order Confirmed</h2><p>Thank you for your order${d.orderId ? ` <strong>#${String(d.orderId).slice(0, 8)}</strong>` : ""}.</p>${d.total ? `<p>Total: ${d.currency ?? "USD"} ${String(d.total)}</p>` : ""}`,
|
|
39
|
-
"order-status-change": (d) =>
|
|
40
|
-
`<h2>Order Update</h2><p>Your order${d.orderId ? ` <strong>#${String(d.orderId).slice(0, 8)}</strong>` : ""} status has been updated to <strong>${d.newStatus ?? "unknown"}</strong>.</p>`,
|
|
41
|
-
"password-reset": (d) =>
|
|
42
|
-
`<h2>Reset Your Password</h2><p>Click the link below to reset your password:</p><p><a href="${d.url ?? "#"}">Reset Password</a></p>`,
|
|
43
|
-
"email-verification": (d) =>
|
|
44
|
-
`<h2>Verify Your Email</h2><p>Click the link below to verify your email address:</p><p><a href="${d.url ?? "#"}">Verify Email</a></p>`,
|
|
45
|
-
"appointment:reminder": (d) =>
|
|
46
|
-
`<h2>Appointment Reminder</h2><p>This is a${d.reminderType === "1h" ? " 1-hour" : " 24-hour"} reminder for your upcoming appointment.</p><p>Booking ID: ${d.bookingId ?? "N/A"}</p>`,
|
|
47
|
-
"appointment:confirmation-notice": (d) =>
|
|
48
|
-
`<h2>Appointment Confirmed</h2><p>Your appointment has been confirmed.</p><p>Booking ID: ${d.bookingId ?? "N/A"}</p>`,
|
|
49
|
-
"appointment:cancellation-notice": (d) =>
|
|
50
|
-
`<h2>Appointment Cancelled</h2><p>Your appointment has been cancelled.</p><p>Booking ID: ${d.bookingId ?? "N/A"}</p>`,
|
|
51
|
-
"appointment:no-show-notice": (d) =>
|
|
52
|
-
`<h2>Missed Appointment</h2><p>You missed your appointment. Please contact us to rebook.</p><p>Booking ID: ${d.bookingId ?? "N/A"}</p>`,
|
|
53
|
-
};
|
|
54
|
-
|
|
55
26
|
/**
|
|
56
27
|
* Creates an email adapter backed by Resend.
|
|
57
28
|
*
|
|
@@ -75,14 +46,13 @@ export function resendAdapter(options: ResendAdapterOptions): {
|
|
|
75
46
|
} {
|
|
76
47
|
const resend = new Resend(options.apiKey);
|
|
77
48
|
|
|
78
|
-
const subjects = { ...DEFAULT_SUBJECTS, ...options.subjects };
|
|
79
|
-
const templates = { ...DEFAULT_TEMPLATES, ...options.templates };
|
|
80
|
-
|
|
81
49
|
return {
|
|
82
50
|
async send(input) {
|
|
83
51
|
const data = input.data ?? {};
|
|
84
|
-
const
|
|
85
|
-
|
|
52
|
+
const rendered = renderEmail(input.template, data, {
|
|
53
|
+
...(options.subjects ? { subjects: options.subjects } : {}),
|
|
54
|
+
...(options.templates ? { templates: options.templates } : {}),
|
|
55
|
+
});
|
|
86
56
|
|
|
87
57
|
// If a Resend template ID is configured, use server-side template rendering
|
|
88
58
|
const resendTemplateId = options.resendTemplateIds?.[input.template];
|
|
@@ -92,7 +62,7 @@ export function resendAdapter(options: ResendAdapterOptions): {
|
|
|
92
62
|
const { error: templateError } = await resend.emails.send({
|
|
93
63
|
from: options.from,
|
|
94
64
|
to: [input.to],
|
|
95
|
-
subject,
|
|
65
|
+
subject: rendered.subject,
|
|
96
66
|
template: {
|
|
97
67
|
id: resendTemplateId,
|
|
98
68
|
variables: data as Record<string, string | number>,
|
|
@@ -105,16 +75,11 @@ export function resendAdapter(options: ResendAdapterOptions): {
|
|
|
105
75
|
}
|
|
106
76
|
|
|
107
77
|
// Otherwise, use local HTML template
|
|
108
|
-
const templateFn = templates[input.template];
|
|
109
|
-
const html = templateFn
|
|
110
|
-
? templateFn(data)
|
|
111
|
-
: `<p>Notification: ${input.template}</p><pre>${JSON.stringify(data, null, 2)}</pre>`;
|
|
112
|
-
|
|
113
78
|
const { error } = await resend.emails.send({
|
|
114
79
|
from: options.from,
|
|
115
80
|
to: [input.to],
|
|
116
|
-
subject,
|
|
117
|
-
html,
|
|
81
|
+
subject: rendered.subject,
|
|
82
|
+
html: rendered.html,
|
|
118
83
|
});
|
|
119
84
|
|
|
120
85
|
if (error) {
|