payload-plugin-newsletter 0.7.1 → 0.8.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/dist/index.js CHANGED
@@ -59,6 +59,256 @@ var adminOrSelf = (config) => ({ req, id }) => {
59
59
  return false;
60
60
  };
61
61
 
62
+ // src/emails/render.tsx
63
+ import { render } from "@react-email/render";
64
+
65
+ // src/emails/MagicLink.tsx
66
+ import {
67
+ Body,
68
+ Button,
69
+ Container,
70
+ Head,
71
+ Hr,
72
+ Html,
73
+ Preview,
74
+ Text
75
+ } from "@react-email/components";
76
+
77
+ // src/emails/styles.ts
78
+ var styles = {
79
+ main: {
80
+ backgroundColor: "#f6f9fc",
81
+ fontFamily: '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif'
82
+ },
83
+ container: {
84
+ backgroundColor: "#ffffff",
85
+ border: "1px solid #f0f0f0",
86
+ borderRadius: "5px",
87
+ margin: "0 auto",
88
+ padding: "45px",
89
+ marginBottom: "64px",
90
+ maxWidth: "500px"
91
+ },
92
+ heading: {
93
+ fontSize: "24px",
94
+ letterSpacing: "-0.5px",
95
+ lineHeight: "1.3",
96
+ fontWeight: "600",
97
+ color: "#484848",
98
+ margin: "0 0 20px",
99
+ padding: "0"
100
+ },
101
+ text: {
102
+ fontSize: "16px",
103
+ lineHeight: "26px",
104
+ fontWeight: "400",
105
+ color: "#484848",
106
+ margin: "16px 0"
107
+ },
108
+ button: {
109
+ backgroundColor: "#000000",
110
+ borderRadius: "5px",
111
+ color: "#fff",
112
+ fontSize: "16px",
113
+ fontWeight: "bold",
114
+ textDecoration: "none",
115
+ textAlign: "center",
116
+ display: "block",
117
+ width: "100%",
118
+ padding: "14px 20px",
119
+ margin: "30px 0"
120
+ },
121
+ link: {
122
+ color: "#2754C5",
123
+ fontSize: "14px",
124
+ textDecoration: "underline",
125
+ wordBreak: "break-all"
126
+ },
127
+ hr: {
128
+ borderColor: "#e6ebf1",
129
+ margin: "30px 0"
130
+ },
131
+ footer: {
132
+ fontSize: "14px",
133
+ lineHeight: "24px",
134
+ color: "#9ca2ac",
135
+ textAlign: "center",
136
+ margin: "0"
137
+ },
138
+ code: {
139
+ display: "inline-block",
140
+ padding: "16px",
141
+ width: "100%",
142
+ backgroundColor: "#f4f4f4",
143
+ borderRadius: "5px",
144
+ border: "1px solid #eee",
145
+ fontSize: "14px",
146
+ fontFamily: "monospace",
147
+ textAlign: "center",
148
+ margin: "24px 0"
149
+ }
150
+ };
151
+
152
+ // src/emails/MagicLink.tsx
153
+ import { jsx, jsxs } from "react/jsx-runtime";
154
+ var MagicLinkEmail = ({
155
+ magicLink,
156
+ email,
157
+ siteName = "Newsletter",
158
+ expiresIn = "24 hours"
159
+ }) => {
160
+ const previewText = `Sign in to ${siteName}`;
161
+ return /* @__PURE__ */ jsxs(Html, { children: [
162
+ /* @__PURE__ */ jsx(Head, {}),
163
+ /* @__PURE__ */ jsx(Preview, { children: previewText }),
164
+ /* @__PURE__ */ jsx(Body, { style: styles.main, children: /* @__PURE__ */ jsxs(Container, { style: styles.container, children: [
165
+ /* @__PURE__ */ jsxs(Text, { style: styles.heading, children: [
166
+ "Sign in to ",
167
+ siteName
168
+ ] }),
169
+ /* @__PURE__ */ jsxs(Text, { style: styles.text, children: [
170
+ "Hi ",
171
+ email.split("@")[0],
172
+ ","
173
+ ] }),
174
+ /* @__PURE__ */ jsxs(Text, { style: styles.text, children: [
175
+ "We received a request to sign in to your ",
176
+ siteName,
177
+ " account. Click the button below to complete your sign in:"
178
+ ] }),
179
+ /* @__PURE__ */ jsxs(Button, { href: magicLink, style: styles.button, children: [
180
+ "Sign in to ",
181
+ siteName
182
+ ] }),
183
+ /* @__PURE__ */ jsx(Text, { style: styles.text, children: "Or copy and paste this URL into your browser:" }),
184
+ /* @__PURE__ */ jsx("code", { style: styles.code, children: magicLink }),
185
+ /* @__PURE__ */ jsx(Hr, { style: styles.hr }),
186
+ /* @__PURE__ */ jsxs(Text, { style: styles.footer, children: [
187
+ "This link will expire in ",
188
+ expiresIn,
189
+ ". If you didn't request this email, you can safely ignore it."
190
+ ] })
191
+ ] }) })
192
+ ] });
193
+ };
194
+
195
+ // src/emails/Welcome.tsx
196
+ import {
197
+ Body as Body2,
198
+ Button as Button2,
199
+ Container as Container2,
200
+ Head as Head2,
201
+ Hr as Hr2,
202
+ Html as Html2,
203
+ Preview as Preview2,
204
+ Text as Text2
205
+ } from "@react-email/components";
206
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
207
+ var WelcomeEmail = ({
208
+ email,
209
+ siteName = "Newsletter",
210
+ preferencesUrl
211
+ }) => {
212
+ const previewText = `Welcome to ${siteName}!`;
213
+ const firstName = email.split("@")[0];
214
+ return /* @__PURE__ */ jsxs2(Html2, { children: [
215
+ /* @__PURE__ */ jsx2(Head2, {}),
216
+ /* @__PURE__ */ jsx2(Preview2, { children: previewText }),
217
+ /* @__PURE__ */ jsx2(Body2, { style: styles.main, children: /* @__PURE__ */ jsxs2(Container2, { style: styles.container, children: [
218
+ /* @__PURE__ */ jsxs2(Text2, { style: styles.heading, children: [
219
+ "Welcome to ",
220
+ siteName,
221
+ "! \u{1F389}"
222
+ ] }),
223
+ /* @__PURE__ */ jsxs2(Text2, { style: styles.text, children: [
224
+ "Hi ",
225
+ firstName,
226
+ ","
227
+ ] }),
228
+ /* @__PURE__ */ jsxs2(Text2, { style: styles.text, children: [
229
+ "Thanks for subscribing to ",
230
+ siteName,
231
+ "! We're excited to have you as part of our community."
232
+ ] }),
233
+ /* @__PURE__ */ jsx2(Text2, { style: styles.text, children: "You'll receive our newsletter based on your preferences. Speaking of which, you can update your preferences anytime:" }),
234
+ preferencesUrl && /* @__PURE__ */ jsx2(Button2, { href: preferencesUrl, style: styles.button, children: "Manage Preferences" }),
235
+ /* @__PURE__ */ jsx2(Text2, { style: styles.text, children: "Here's what you can expect from us:" }),
236
+ /* @__PURE__ */ jsxs2(Text2, { style: styles.text, children: [
237
+ "\u2022 Regular updates based on your chosen frequency",
238
+ /* @__PURE__ */ jsx2("br", {}),
239
+ "\u2022 Content tailored to your interests",
240
+ /* @__PURE__ */ jsx2("br", {}),
241
+ "\u2022 Easy unsubscribe options in every email",
242
+ /* @__PURE__ */ jsx2("br", {}),
243
+ "\u2022 Your privacy respected always"
244
+ ] }),
245
+ /* @__PURE__ */ jsx2(Hr2, { style: styles.hr }),
246
+ /* @__PURE__ */ jsx2(Text2, { style: styles.footer, children: "If you have any questions, feel free to reply to this email. We're here to help!" })
247
+ ] }) })
248
+ ] });
249
+ };
250
+
251
+ // src/emails/SignIn.tsx
252
+ import { jsx as jsx3 } from "react/jsx-runtime";
253
+ var SignInEmail = (props) => {
254
+ return /* @__PURE__ */ jsx3(MagicLinkEmail, { ...props });
255
+ };
256
+
257
+ // src/emails/render.tsx
258
+ import { jsx as jsx4 } from "react/jsx-runtime";
259
+ async function renderEmail(template, data) {
260
+ try {
261
+ switch (template) {
262
+ case "magic-link": {
263
+ const magicLinkData = data;
264
+ return render(
265
+ /* @__PURE__ */ jsx4(
266
+ MagicLinkEmail,
267
+ {
268
+ magicLink: magicLinkData.magicLink || magicLinkData.verificationUrl || magicLinkData.magicLinkUrl || "",
269
+ email: magicLinkData.email || "",
270
+ siteName: magicLinkData.siteName,
271
+ expiresIn: magicLinkData.expiresIn
272
+ }
273
+ )
274
+ );
275
+ }
276
+ case "signin": {
277
+ const signinData = data;
278
+ return render(
279
+ /* @__PURE__ */ jsx4(
280
+ SignInEmail,
281
+ {
282
+ magicLink: signinData.magicLink || signinData.verificationUrl || signinData.magicLinkUrl || "",
283
+ email: signinData.email || "",
284
+ siteName: signinData.siteName,
285
+ expiresIn: signinData.expiresIn
286
+ }
287
+ )
288
+ );
289
+ }
290
+ case "welcome": {
291
+ const welcomeData = data;
292
+ return render(
293
+ /* @__PURE__ */ jsx4(
294
+ WelcomeEmail,
295
+ {
296
+ email: welcomeData.email || "",
297
+ siteName: welcomeData.siteName,
298
+ preferencesUrl: welcomeData.preferencesUrl
299
+ }
300
+ )
301
+ );
302
+ }
303
+ default:
304
+ throw new Error(`Unknown email template: ${template}`);
305
+ }
306
+ } catch (error) {
307
+ console.error(`Failed to render email template ${template}:`, error);
308
+ throw error;
309
+ }
310
+ }
311
+
62
312
  // src/collections/Subscribers.ts
63
313
  var createSubscribersCollection = (pluginConfig) => {
64
314
  const slug = pluginConfig.subscribersSlug || "subscribers";
@@ -268,7 +518,24 @@ var createSubscribersCollection = (pluginConfig) => {
268
518
  }
269
519
  if (doc.subscriptionStatus === "active" && emailService) {
270
520
  try {
271
- } catch {
521
+ const settings = await req.payload.findGlobal({
522
+ slug: pluginConfig.settingsSlug || "newsletter-settings"
523
+ });
524
+ const serverURL = req.payload.config.serverURL || process.env.PAYLOAD_PUBLIC_SERVER_URL || "";
525
+ const html = await renderEmail("welcome", {
526
+ email: doc.email,
527
+ siteName: settings?.brandSettings?.siteName || "Newsletter",
528
+ preferencesUrl: `${serverURL}/account/preferences`
529
+ // This could be customized
530
+ });
531
+ await emailService.send({
532
+ to: doc.email,
533
+ subject: settings?.brandSettings?.siteName ? `Welcome to ${settings.brandSettings.siteName}!` : "Welcome!",
534
+ html
535
+ });
536
+ console.log(`Welcome email sent to: ${doc.email}`);
537
+ } catch (error) {
538
+ console.error("Failed to send welcome email:", error);
272
539
  }
273
540
  }
274
541
  if (pluginConfig.hooks?.afterSubscribe) {
@@ -1153,256 +1420,6 @@ function generateMagicLinkURL(token, baseURL, config) {
1153
1420
  return url.toString();
1154
1421
  }
1155
1422
 
1156
- // src/emails/render.tsx
1157
- import { render } from "@react-email/render";
1158
-
1159
- // src/emails/MagicLink.tsx
1160
- import {
1161
- Body,
1162
- Button,
1163
- Container,
1164
- Head,
1165
- Hr,
1166
- Html,
1167
- Preview,
1168
- Text
1169
- } from "@react-email/components";
1170
-
1171
- // src/emails/styles.ts
1172
- var styles = {
1173
- main: {
1174
- backgroundColor: "#f6f9fc",
1175
- fontFamily: '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif'
1176
- },
1177
- container: {
1178
- backgroundColor: "#ffffff",
1179
- border: "1px solid #f0f0f0",
1180
- borderRadius: "5px",
1181
- margin: "0 auto",
1182
- padding: "45px",
1183
- marginBottom: "64px",
1184
- maxWidth: "500px"
1185
- },
1186
- heading: {
1187
- fontSize: "24px",
1188
- letterSpacing: "-0.5px",
1189
- lineHeight: "1.3",
1190
- fontWeight: "600",
1191
- color: "#484848",
1192
- margin: "0 0 20px",
1193
- padding: "0"
1194
- },
1195
- text: {
1196
- fontSize: "16px",
1197
- lineHeight: "26px",
1198
- fontWeight: "400",
1199
- color: "#484848",
1200
- margin: "16px 0"
1201
- },
1202
- button: {
1203
- backgroundColor: "#000000",
1204
- borderRadius: "5px",
1205
- color: "#fff",
1206
- fontSize: "16px",
1207
- fontWeight: "bold",
1208
- textDecoration: "none",
1209
- textAlign: "center",
1210
- display: "block",
1211
- width: "100%",
1212
- padding: "14px 20px",
1213
- margin: "30px 0"
1214
- },
1215
- link: {
1216
- color: "#2754C5",
1217
- fontSize: "14px",
1218
- textDecoration: "underline",
1219
- wordBreak: "break-all"
1220
- },
1221
- hr: {
1222
- borderColor: "#e6ebf1",
1223
- margin: "30px 0"
1224
- },
1225
- footer: {
1226
- fontSize: "14px",
1227
- lineHeight: "24px",
1228
- color: "#9ca2ac",
1229
- textAlign: "center",
1230
- margin: "0"
1231
- },
1232
- code: {
1233
- display: "inline-block",
1234
- padding: "16px",
1235
- width: "100%",
1236
- backgroundColor: "#f4f4f4",
1237
- borderRadius: "5px",
1238
- border: "1px solid #eee",
1239
- fontSize: "14px",
1240
- fontFamily: "monospace",
1241
- textAlign: "center",
1242
- margin: "24px 0"
1243
- }
1244
- };
1245
-
1246
- // src/emails/MagicLink.tsx
1247
- import { jsx, jsxs } from "react/jsx-runtime";
1248
- var MagicLinkEmail = ({
1249
- magicLink,
1250
- email,
1251
- siteName = "Newsletter",
1252
- expiresIn = "24 hours"
1253
- }) => {
1254
- const previewText = `Sign in to ${siteName}`;
1255
- return /* @__PURE__ */ jsxs(Html, { children: [
1256
- /* @__PURE__ */ jsx(Head, {}),
1257
- /* @__PURE__ */ jsx(Preview, { children: previewText }),
1258
- /* @__PURE__ */ jsx(Body, { style: styles.main, children: /* @__PURE__ */ jsxs(Container, { style: styles.container, children: [
1259
- /* @__PURE__ */ jsxs(Text, { style: styles.heading, children: [
1260
- "Sign in to ",
1261
- siteName
1262
- ] }),
1263
- /* @__PURE__ */ jsxs(Text, { style: styles.text, children: [
1264
- "Hi ",
1265
- email.split("@")[0],
1266
- ","
1267
- ] }),
1268
- /* @__PURE__ */ jsxs(Text, { style: styles.text, children: [
1269
- "We received a request to sign in to your ",
1270
- siteName,
1271
- " account. Click the button below to complete your sign in:"
1272
- ] }),
1273
- /* @__PURE__ */ jsxs(Button, { href: magicLink, style: styles.button, children: [
1274
- "Sign in to ",
1275
- siteName
1276
- ] }),
1277
- /* @__PURE__ */ jsx(Text, { style: styles.text, children: "Or copy and paste this URL into your browser:" }),
1278
- /* @__PURE__ */ jsx("code", { style: styles.code, children: magicLink }),
1279
- /* @__PURE__ */ jsx(Hr, { style: styles.hr }),
1280
- /* @__PURE__ */ jsxs(Text, { style: styles.footer, children: [
1281
- "This link will expire in ",
1282
- expiresIn,
1283
- ". If you didn't request this email, you can safely ignore it."
1284
- ] })
1285
- ] }) })
1286
- ] });
1287
- };
1288
-
1289
- // src/emails/Welcome.tsx
1290
- import {
1291
- Body as Body2,
1292
- Button as Button2,
1293
- Container as Container2,
1294
- Head as Head2,
1295
- Hr as Hr2,
1296
- Html as Html2,
1297
- Preview as Preview2,
1298
- Text as Text2
1299
- } from "@react-email/components";
1300
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1301
- var WelcomeEmail = ({
1302
- email,
1303
- siteName = "Newsletter",
1304
- preferencesUrl
1305
- }) => {
1306
- const previewText = `Welcome to ${siteName}!`;
1307
- const firstName = email.split("@")[0];
1308
- return /* @__PURE__ */ jsxs2(Html2, { children: [
1309
- /* @__PURE__ */ jsx2(Head2, {}),
1310
- /* @__PURE__ */ jsx2(Preview2, { children: previewText }),
1311
- /* @__PURE__ */ jsx2(Body2, { style: styles.main, children: /* @__PURE__ */ jsxs2(Container2, { style: styles.container, children: [
1312
- /* @__PURE__ */ jsxs2(Text2, { style: styles.heading, children: [
1313
- "Welcome to ",
1314
- siteName,
1315
- "! \u{1F389}"
1316
- ] }),
1317
- /* @__PURE__ */ jsxs2(Text2, { style: styles.text, children: [
1318
- "Hi ",
1319
- firstName,
1320
- ","
1321
- ] }),
1322
- /* @__PURE__ */ jsxs2(Text2, { style: styles.text, children: [
1323
- "Thanks for subscribing to ",
1324
- siteName,
1325
- "! We're excited to have you as part of our community."
1326
- ] }),
1327
- /* @__PURE__ */ jsx2(Text2, { style: styles.text, children: "You'll receive our newsletter based on your preferences. Speaking of which, you can update your preferences anytime:" }),
1328
- preferencesUrl && /* @__PURE__ */ jsx2(Button2, { href: preferencesUrl, style: styles.button, children: "Manage Preferences" }),
1329
- /* @__PURE__ */ jsx2(Text2, { style: styles.text, children: "Here's what you can expect from us:" }),
1330
- /* @__PURE__ */ jsxs2(Text2, { style: styles.text, children: [
1331
- "\u2022 Regular updates based on your chosen frequency",
1332
- /* @__PURE__ */ jsx2("br", {}),
1333
- "\u2022 Content tailored to your interests",
1334
- /* @__PURE__ */ jsx2("br", {}),
1335
- "\u2022 Easy unsubscribe options in every email",
1336
- /* @__PURE__ */ jsx2("br", {}),
1337
- "\u2022 Your privacy respected always"
1338
- ] }),
1339
- /* @__PURE__ */ jsx2(Hr2, { style: styles.hr }),
1340
- /* @__PURE__ */ jsx2(Text2, { style: styles.footer, children: "If you have any questions, feel free to reply to this email. We're here to help!" })
1341
- ] }) })
1342
- ] });
1343
- };
1344
-
1345
- // src/emails/SignIn.tsx
1346
- import { jsx as jsx3 } from "react/jsx-runtime";
1347
- var SignInEmail = (props) => {
1348
- return /* @__PURE__ */ jsx3(MagicLinkEmail, { ...props });
1349
- };
1350
-
1351
- // src/emails/render.tsx
1352
- import { jsx as jsx4 } from "react/jsx-runtime";
1353
- async function renderEmail(template, data) {
1354
- try {
1355
- switch (template) {
1356
- case "magic-link": {
1357
- const magicLinkData = data;
1358
- return render(
1359
- /* @__PURE__ */ jsx4(
1360
- MagicLinkEmail,
1361
- {
1362
- magicLink: magicLinkData.magicLink || magicLinkData.verificationUrl || magicLinkData.magicLinkUrl || "",
1363
- email: magicLinkData.email || "",
1364
- siteName: magicLinkData.siteName,
1365
- expiresIn: magicLinkData.expiresIn
1366
- }
1367
- )
1368
- );
1369
- }
1370
- case "signin": {
1371
- const signinData = data;
1372
- return render(
1373
- /* @__PURE__ */ jsx4(
1374
- SignInEmail,
1375
- {
1376
- magicLink: signinData.magicLink || signinData.verificationUrl || signinData.magicLinkUrl || "",
1377
- email: signinData.email || "",
1378
- siteName: signinData.siteName,
1379
- expiresIn: signinData.expiresIn
1380
- }
1381
- )
1382
- );
1383
- }
1384
- case "welcome": {
1385
- const welcomeData = data;
1386
- return render(
1387
- /* @__PURE__ */ jsx4(
1388
- WelcomeEmail,
1389
- {
1390
- email: welcomeData.email || "",
1391
- siteName: welcomeData.siteName,
1392
- preferencesUrl: welcomeData.preferencesUrl
1393
- }
1394
- )
1395
- );
1396
- }
1397
- default:
1398
- throw new Error(`Unknown email template: ${template}`);
1399
- }
1400
- } catch (error) {
1401
- console.error(`Failed to render email template ${template}:`, error);
1402
- throw error;
1403
- }
1404
- }
1405
-
1406
1423
  // src/endpoints/subscribe.ts
1407
1424
  var createSubscribeEndpoint = (config) => {
1408
1425
  return {