@contentgrowth/content-emailing 0.7.5 → 0.7.7
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/backend/EmailService.cjs +19 -0
- package/dist/backend/EmailService.cjs.map +1 -1
- package/dist/backend/EmailService.d.cts +2 -0
- package/dist/backend/EmailService.d.ts +2 -0
- package/dist/backend/EmailService.js +19 -0
- package/dist/backend/EmailService.js.map +1 -1
- package/dist/backend/index.cjs +139 -46
- package/dist/backend/index.cjs.map +1 -1
- package/dist/backend/index.d.cts +1 -0
- package/dist/backend/index.d.ts +1 -0
- package/dist/backend/index.js +139 -46
- package/dist/backend/index.js.map +1 -1
- package/dist/backend/routes/index.cjs +174 -47
- package/dist/backend/routes/index.cjs.map +1 -1
- package/dist/backend/routes/index.d.cts +23 -6
- package/dist/backend/routes/index.d.ts +23 -6
- package/dist/backend/routes/index.js +172 -47
- package/dist/backend/routes/index.js.map +1 -1
- package/dist/index.cjs +139 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +139 -46
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -30,14 +30,72 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
var routes_exports = {};
|
|
31
31
|
__export(routes_exports, {
|
|
32
32
|
createEmailRoutes: () => createEmailRoutes,
|
|
33
|
-
|
|
33
|
+
createLogRoutes: () => createLogRoutes2,
|
|
34
|
+
createSettingsRoutes: () => createSettingsRoutes,
|
|
35
|
+
createTemplateRoutes: () => createTemplateRoutes2,
|
|
34
36
|
createTrackingRoutes: () => createTrackingRoutes
|
|
35
37
|
});
|
|
36
38
|
module.exports = __toCommonJS(routes_exports);
|
|
37
|
-
var
|
|
39
|
+
var import_hono5 = require("hono");
|
|
38
40
|
|
|
39
|
-
// src/backend/routes/
|
|
41
|
+
// src/backend/routes/settings.js
|
|
40
42
|
var import_hono = require("hono");
|
|
43
|
+
function createSettingsRoutes(config = {}) {
|
|
44
|
+
const app = new import_hono.Hono();
|
|
45
|
+
const tableName = config.tableName || "system_settings";
|
|
46
|
+
const keyPrefix = config.keyPrefix || "system_email.";
|
|
47
|
+
const getSettings = async (db) => {
|
|
48
|
+
try {
|
|
49
|
+
const { results } = await db.prepare(`SELECT * FROM ${tableName} WHERE key LIKE ?`).bind(`${keyPrefix}%`).all();
|
|
50
|
+
const settings = {};
|
|
51
|
+
for (const row of results) {
|
|
52
|
+
const cleanKey = row.key.slice(keyPrefix.length);
|
|
53
|
+
settings[cleanKey] = row.value;
|
|
54
|
+
}
|
|
55
|
+
return settings;
|
|
56
|
+
} catch (e) {
|
|
57
|
+
console.warn(`[Settings] Failed to fetch from ${tableName}:`, e.message);
|
|
58
|
+
return {};
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
app.get("/", async (c) => {
|
|
62
|
+
try {
|
|
63
|
+
const settings = await getSettings(c.env.DB);
|
|
64
|
+
return c.json(settings);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error("Failed to fetch settings:", error);
|
|
67
|
+
return c.json({ error: error.message }, 500);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
app.post("/", async (c) => {
|
|
71
|
+
try {
|
|
72
|
+
const body = await c.req.json();
|
|
73
|
+
const db = c.env.DB;
|
|
74
|
+
const updates = Object.entries(body).map(([k, v]) => ({
|
|
75
|
+
key: `${keyPrefix}${k}`,
|
|
76
|
+
value: v
|
|
77
|
+
}));
|
|
78
|
+
if (updates.length === 0) return c.json({ success: true });
|
|
79
|
+
const stmt = db.prepare(`
|
|
80
|
+
INSERT INTO ${tableName} (key, value, updated_at)
|
|
81
|
+
VALUES (?, ?, strftime('%s', 'now'))
|
|
82
|
+
ON CONFLICT(key) DO UPDATE SET
|
|
83
|
+
value = excluded.value,
|
|
84
|
+
updated_at = excluded.updated_at
|
|
85
|
+
`);
|
|
86
|
+
const batch = updates.map((u) => stmt.bind(u.key, u.value === void 0 || u.value === null ? "" : String(u.value)));
|
|
87
|
+
await db.batch(batch);
|
|
88
|
+
return c.json({ success: true });
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.error("Failed to save settings:", error);
|
|
91
|
+
return c.json({ error: error.message }, 500);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
return app;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// src/backend/routes/templates.js
|
|
98
|
+
var import_hono2 = require("hono");
|
|
41
99
|
|
|
42
100
|
// src/backend/EmailService.js
|
|
43
101
|
var import_marked = require("marked");
|
|
@@ -518,6 +576,9 @@ var EmailService = class {
|
|
|
518
576
|
// Updater function to save settings to backend
|
|
519
577
|
// Signature: async (profile, tenantId, settings) => void
|
|
520
578
|
settingsUpdater: config.settingsUpdater || null,
|
|
579
|
+
// Settings configuration
|
|
580
|
+
settingsTableName: config.settingsTableName || "system_settings",
|
|
581
|
+
settingsKeyPrefix: config.settingsKeyPrefix || "system_email.",
|
|
521
582
|
// Branding configuration for email templates
|
|
522
583
|
branding: {
|
|
523
584
|
brandName: config.branding?.brandName || "Your App",
|
|
@@ -566,6 +627,22 @@ var EmailService = class {
|
|
|
566
627
|
console.warn("[EmailService] settingsLoader failed:", e);
|
|
567
628
|
}
|
|
568
629
|
}
|
|
630
|
+
if (!settings && profile === "system" && this.db) {
|
|
631
|
+
try {
|
|
632
|
+
const tableName = this.config.settingsTableName;
|
|
633
|
+
const prefix = this.config.settingsKeyPrefix;
|
|
634
|
+
const { results } = await this.db.prepare(`SELECT * FROM ${tableName} WHERE key LIKE ?`).bind(`${prefix}%`).all();
|
|
635
|
+
if (results && results.length > 0) {
|
|
636
|
+
settings = {};
|
|
637
|
+
for (const row of results) {
|
|
638
|
+
const cleanKey = row.key.slice(prefix.length);
|
|
639
|
+
settings[cleanKey] = row.value;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
} catch (e) {
|
|
643
|
+
console.warn("[EmailService] Failed to load settings from DB:", e.message);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
569
646
|
if (settings) {
|
|
570
647
|
if (this.cache && this.cache.putSettings) {
|
|
571
648
|
try {
|
|
@@ -1096,78 +1173,88 @@ var EmailService = class {
|
|
|
1096
1173
|
};
|
|
1097
1174
|
|
|
1098
1175
|
// src/backend/routes/templates.js
|
|
1099
|
-
function
|
|
1100
|
-
const app = new
|
|
1101
|
-
|
|
1102
|
-
|
|
1176
|
+
function createTemplateRoutes2(config = {}) {
|
|
1177
|
+
const app = new import_hono2.Hono();
|
|
1178
|
+
app.get("/", async (c) => {
|
|
1179
|
+
const emailService = new EmailService(c.env, config);
|
|
1103
1180
|
try {
|
|
1104
1181
|
const templates = await emailService.getAllTemplates();
|
|
1105
|
-
return c.json(
|
|
1182
|
+
return c.json(templates);
|
|
1106
1183
|
} catch (err) {
|
|
1107
|
-
return c.json({
|
|
1184
|
+
return c.json({ error: err.message }, 500);
|
|
1108
1185
|
}
|
|
1109
1186
|
});
|
|
1110
|
-
app.get("
|
|
1187
|
+
app.get("/:id", async (c) => {
|
|
1188
|
+
const emailService = new EmailService(c.env, config);
|
|
1111
1189
|
try {
|
|
1112
1190
|
const template = await emailService.getTemplate(c.req.param("id"));
|
|
1113
|
-
if (!template) return c.json({
|
|
1114
|
-
return c.json(
|
|
1191
|
+
if (!template) return c.json({ error: "Template not found" }, 404);
|
|
1192
|
+
return c.json(template);
|
|
1115
1193
|
} catch (err) {
|
|
1116
|
-
return c.json({
|
|
1194
|
+
return c.json({ error: err.message }, 500);
|
|
1117
1195
|
}
|
|
1118
1196
|
});
|
|
1119
|
-
app.post("/
|
|
1197
|
+
app.post("/", async (c) => {
|
|
1198
|
+
const emailService = new EmailService(c.env, config);
|
|
1120
1199
|
try {
|
|
1121
1200
|
const data = await c.req.json();
|
|
1122
|
-
|
|
1123
|
-
|
|
1201
|
+
let userId = "admin";
|
|
1202
|
+
const user = c.get("dbUser") || c.get("user");
|
|
1203
|
+
if (user && user.id) userId = user.id;
|
|
1204
|
+
if (!data.template_id || !data.subject_template) {
|
|
1205
|
+
return c.json({ error: "Missing required fields (template_id, subject_template)" }, 400);
|
|
1206
|
+
}
|
|
1207
|
+
const result = await emailService.saveTemplate(data, userId);
|
|
1208
|
+
return c.json({ success: true, message: "Template saved", result });
|
|
1124
1209
|
} catch (err) {
|
|
1125
|
-
return c.json({
|
|
1210
|
+
return c.json({ error: err.message }, 500);
|
|
1126
1211
|
}
|
|
1127
1212
|
});
|
|
1128
|
-
app.
|
|
1213
|
+
app.post("/send-test", async (c) => {
|
|
1214
|
+
const emailService = new EmailService(c.env, config);
|
|
1215
|
+
try {
|
|
1216
|
+
const { template_id, to, variables } = await c.req.json();
|
|
1217
|
+
let tid = template_id;
|
|
1218
|
+
if (!tid || !to) {
|
|
1219
|
+
return c.json({ error: "Missing required fields (template_id, to)" }, 400);
|
|
1220
|
+
}
|
|
1221
|
+
const user = c.get("dbUser") || c.get("user");
|
|
1222
|
+
const recipientUserId = user?.id || null;
|
|
1223
|
+
const result = await emailService.sendViaTemplate(tid, variables || {}, {
|
|
1224
|
+
to,
|
|
1225
|
+
profile: "test",
|
|
1226
|
+
recipientUserId
|
|
1227
|
+
});
|
|
1228
|
+
return c.json({ success: true, result });
|
|
1229
|
+
} catch (err) {
|
|
1230
|
+
return c.json({ error: `Failed to send test email: ${err.message}` }, 500);
|
|
1231
|
+
}
|
|
1232
|
+
});
|
|
1233
|
+
app.delete("/:id", async (c) => {
|
|
1234
|
+
const emailService = new EmailService(c.env, config);
|
|
1129
1235
|
try {
|
|
1130
1236
|
await emailService.deleteTemplate(c.req.param("id"));
|
|
1131
1237
|
return c.json({ success: true, message: "Template deleted" });
|
|
1132
1238
|
} catch (err) {
|
|
1133
|
-
return c.json({
|
|
1239
|
+
return c.json({ error: err.message }, 500);
|
|
1134
1240
|
}
|
|
1135
1241
|
});
|
|
1136
|
-
app.post("
|
|
1242
|
+
app.post("/:id/preview", async (c) => {
|
|
1243
|
+
const emailService = new EmailService(c.env, config);
|
|
1137
1244
|
try {
|
|
1138
1245
|
const id = c.req.param("id");
|
|
1139
1246
|
const data = await c.req.json();
|
|
1140
1247
|
const result = await emailService.renderTemplate(id, data);
|
|
1141
1248
|
return c.json({ success: true, preview: result });
|
|
1142
1249
|
} catch (err) {
|
|
1143
|
-
return c.json({
|
|
1144
|
-
}
|
|
1145
|
-
});
|
|
1146
|
-
app.post("/templates/:id/test", async (c) => {
|
|
1147
|
-
try {
|
|
1148
|
-
const id = c.req.param("id");
|
|
1149
|
-
const { to, data } = await c.req.json();
|
|
1150
|
-
const { subject, html, plainText } = await emailService.renderTemplate(id, data);
|
|
1151
|
-
const result = await emailService.sendEmail({
|
|
1152
|
-
to,
|
|
1153
|
-
subject: `[TEST] ${subject}`,
|
|
1154
|
-
html,
|
|
1155
|
-
text: plainText
|
|
1156
|
-
});
|
|
1157
|
-
if (result.success) {
|
|
1158
|
-
return c.json({ success: true, message: "Test email sent" });
|
|
1159
|
-
} else {
|
|
1160
|
-
return c.json({ success: false, error: result.error }, 500);
|
|
1161
|
-
}
|
|
1162
|
-
} catch (err) {
|
|
1163
|
-
return c.json({ success: false, error: err.message }, 500);
|
|
1250
|
+
return c.json({ error: err.message }, 500);
|
|
1164
1251
|
}
|
|
1165
1252
|
});
|
|
1166
1253
|
return app;
|
|
1167
1254
|
}
|
|
1168
1255
|
|
|
1169
1256
|
// src/backend/routes/tracking.js
|
|
1170
|
-
var
|
|
1257
|
+
var import_hono3 = require("hono");
|
|
1171
1258
|
var TRACKING_PIXEL = new Uint8Array([
|
|
1172
1259
|
71,
|
|
1173
1260
|
73,
|
|
@@ -1213,7 +1300,7 @@ var TRACKING_PIXEL = new Uint8Array([
|
|
|
1213
1300
|
59
|
|
1214
1301
|
]);
|
|
1215
1302
|
function createTrackingRoutes(env, config = {}) {
|
|
1216
|
-
const app = new
|
|
1303
|
+
const app = new import_hono3.Hono();
|
|
1217
1304
|
const db = env.DB;
|
|
1218
1305
|
const tablePrefix = config.emailTablePrefix || config.tableNamePrefix || "system_email_";
|
|
1219
1306
|
app.get("/track/open/:token", async (c) => {
|
|
@@ -1341,16 +1428,56 @@ function createTrackingRoutes(env, config = {}) {
|
|
|
1341
1428
|
return app;
|
|
1342
1429
|
}
|
|
1343
1430
|
|
|
1431
|
+
// src/backend/routes/logs.js
|
|
1432
|
+
var import_hono4 = require("hono");
|
|
1433
|
+
function createLogRoutes2(config = {}) {
|
|
1434
|
+
const app = new import_hono4.Hono();
|
|
1435
|
+
app.get("/", async (c) => {
|
|
1436
|
+
const limit = Math.min(parseInt(c.req.query("limit") || "50"), 100);
|
|
1437
|
+
const offset = parseInt(c.req.query("offset") || "0");
|
|
1438
|
+
const env = c.env;
|
|
1439
|
+
try {
|
|
1440
|
+
const table = `${config.emailTablePrefix || "system_email_"}logs`;
|
|
1441
|
+
const { results } = await env.DB.prepare(`
|
|
1442
|
+
SELECT * FROM ${table}
|
|
1443
|
+
ORDER BY created_at DESC
|
|
1444
|
+
LIMIT ? OFFSET ?
|
|
1445
|
+
`).bind(limit, offset).all();
|
|
1446
|
+
const countResult = await env.DB.prepare(`SELECT COUNT(*) as exact_count FROM ${table}`).first();
|
|
1447
|
+
return c.json({
|
|
1448
|
+
logs: results.map((row) => ({
|
|
1449
|
+
...row,
|
|
1450
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : null
|
|
1451
|
+
})),
|
|
1452
|
+
total: countResult.exact_count,
|
|
1453
|
+
limit,
|
|
1454
|
+
offset
|
|
1455
|
+
});
|
|
1456
|
+
} catch (error) {
|
|
1457
|
+
console.error("Failed to fetch logs:", error);
|
|
1458
|
+
return c.json({ error: "Failed to fetch logs" }, 500);
|
|
1459
|
+
}
|
|
1460
|
+
});
|
|
1461
|
+
return app;
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1344
1464
|
// src/backend/routes/index.js
|
|
1345
|
-
function createEmailRoutes(
|
|
1346
|
-
const app = new
|
|
1347
|
-
app.route("/
|
|
1348
|
-
app.route("/
|
|
1465
|
+
function createEmailRoutes(config = {}, cacheProvider = null) {
|
|
1466
|
+
const app = new import_hono5.Hono();
|
|
1467
|
+
app.route("/templates", createTemplateRoutes(config, cacheProvider));
|
|
1468
|
+
app.route("/logs", createLogRoutes(config));
|
|
1469
|
+
app.route("/settings", createSettingsRoutes({
|
|
1470
|
+
...config,
|
|
1471
|
+
tableName: config.settingsTableName || "system_settings",
|
|
1472
|
+
keyPrefix: config.settingsKeyPrefix || "system_email."
|
|
1473
|
+
}));
|
|
1349
1474
|
return app;
|
|
1350
1475
|
}
|
|
1351
1476
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1352
1477
|
0 && (module.exports = {
|
|
1353
1478
|
createEmailRoutes,
|
|
1479
|
+
createLogRoutes,
|
|
1480
|
+
createSettingsRoutes,
|
|
1354
1481
|
createTemplateRoutes,
|
|
1355
1482
|
createTrackingRoutes
|
|
1356
1483
|
});
|