@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.
@@ -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
- createTemplateRoutes: () => createTemplateRoutes,
33
+ createLogRoutes: () => createLogRoutes2,
34
+ createSettingsRoutes: () => createSettingsRoutes,
35
+ createTemplateRoutes: () => createTemplateRoutes2,
34
36
  createTrackingRoutes: () => createTrackingRoutes
35
37
  });
36
38
  module.exports = __toCommonJS(routes_exports);
37
- var import_hono3 = require("hono");
39
+ var import_hono5 = require("hono");
38
40
 
39
- // src/backend/routes/templates.js
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 createTemplateRoutes(env, config = {}, cacheProvider = null) {
1100
- const app = new import_hono.Hono();
1101
- const emailService = new EmailService(env, config, cacheProvider);
1102
- app.get("/templates", async (c) => {
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({ success: true, templates });
1182
+ return c.json(templates);
1106
1183
  } catch (err) {
1107
- return c.json({ success: false, error: err.message }, 500);
1184
+ return c.json({ error: err.message }, 500);
1108
1185
  }
1109
1186
  });
1110
- app.get("/templates/:id", async (c) => {
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({ success: false, error: "Template not found" }, 404);
1114
- return c.json({ success: true, template });
1191
+ if (!template) return c.json({ error: "Template not found" }, 404);
1192
+ return c.json(template);
1115
1193
  } catch (err) {
1116
- return c.json({ success: false, error: err.message }, 500);
1194
+ return c.json({ error: err.message }, 500);
1117
1195
  }
1118
1196
  });
1119
- app.post("/templates", async (c) => {
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
- await emailService.saveTemplate(data, "admin");
1123
- return c.json({ success: true, message: "Template saved" });
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({ success: false, error: err.message }, 500);
1210
+ return c.json({ error: err.message }, 500);
1126
1211
  }
1127
1212
  });
1128
- app.delete("/templates/:id", async (c) => {
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({ success: false, error: err.message }, 500);
1239
+ return c.json({ error: err.message }, 500);
1134
1240
  }
1135
1241
  });
1136
- app.post("/templates/:id/preview", async (c) => {
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({ success: false, error: err.message }, 500);
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 import_hono2 = require("hono");
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 import_hono2.Hono();
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(env, config = {}, cacheProvider = null) {
1346
- const app = new import_hono3.Hono();
1347
- app.route("/api/email", createTemplateRoutes(env, config, cacheProvider));
1348
- app.route("/email", createTrackingRoutes(env, config));
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
  });