@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.
@@ -35,7 +35,7 @@ __export(backend_exports, {
35
35
  createDOCacheProvider: () => createDOCacheProvider,
36
36
  createEmailLoggerCallback: () => createEmailLoggerCallback,
37
37
  createEmailRoutes: () => createEmailRoutes,
38
- createTemplateRoutes: () => createTemplateRoutes,
38
+ createTemplateRoutes: () => createTemplateRoutes2,
39
39
  createTrackingRoutes: () => createTrackingRoutes,
40
40
  encodeTrackingLinks: () => encodeTrackingLinks,
41
41
  extractVariables: () => extractVariables,
@@ -814,6 +814,9 @@ var EmailService = class {
814
814
  // Updater function to save settings to backend
815
815
  // Signature: async (profile, tenantId, settings) => void
816
816
  settingsUpdater: config.settingsUpdater || null,
817
+ // Settings configuration
818
+ settingsTableName: config.settingsTableName || "system_settings",
819
+ settingsKeyPrefix: config.settingsKeyPrefix || "system_email.",
817
820
  // Branding configuration for email templates
818
821
  branding: {
819
822
  brandName: config.branding?.brandName || "Your App",
@@ -862,6 +865,22 @@ var EmailService = class {
862
865
  console.warn("[EmailService] settingsLoader failed:", e);
863
866
  }
864
867
  }
868
+ if (!settings && profile === "system" && this.db) {
869
+ try {
870
+ const tableName = this.config.settingsTableName;
871
+ const prefix = this.config.settingsKeyPrefix;
872
+ const { results } = await this.db.prepare(`SELECT * FROM ${tableName} WHERE key LIKE ?`).bind(`${prefix}%`).all();
873
+ if (results && results.length > 0) {
874
+ settings = {};
875
+ for (const row of results) {
876
+ const cleanKey = row.key.slice(prefix.length);
877
+ settings[cleanKey] = row.value;
878
+ }
879
+ }
880
+ } catch (e) {
881
+ console.warn("[EmailService] Failed to load settings from DB:", e.message);
882
+ }
883
+ }
865
884
  if (settings) {
866
885
  if (this.cache && this.cache.putSettings) {
867
886
  try {
@@ -1392,82 +1411,148 @@ var EmailService = class {
1392
1411
  };
1393
1412
 
1394
1413
  // src/backend/routes/index.js
1395
- var import_hono3 = require("hono");
1414
+ var import_hono5 = require("hono");
1396
1415
 
1397
- // src/backend/routes/templates.js
1416
+ // src/backend/routes/settings.js
1398
1417
  var import_hono = require("hono");
1399
- function createTemplateRoutes(env, config = {}, cacheProvider = null) {
1418
+ function createSettingsRoutes(config = {}) {
1400
1419
  const app = new import_hono.Hono();
1401
- const emailService = new EmailService(env, config, cacheProvider);
1402
- app.get("/templates", async (c) => {
1420
+ const tableName = config.tableName || "system_settings";
1421
+ const keyPrefix = config.keyPrefix || "system_email.";
1422
+ const getSettings = async (db) => {
1423
+ try {
1424
+ const { results } = await db.prepare(`SELECT * FROM ${tableName} WHERE key LIKE ?`).bind(`${keyPrefix}%`).all();
1425
+ const settings = {};
1426
+ for (const row of results) {
1427
+ const cleanKey = row.key.slice(keyPrefix.length);
1428
+ settings[cleanKey] = row.value;
1429
+ }
1430
+ return settings;
1431
+ } catch (e) {
1432
+ console.warn(`[Settings] Failed to fetch from ${tableName}:`, e.message);
1433
+ return {};
1434
+ }
1435
+ };
1436
+ app.get("/", async (c) => {
1437
+ try {
1438
+ const settings = await getSettings(c.env.DB);
1439
+ return c.json(settings);
1440
+ } catch (error) {
1441
+ console.error("Failed to fetch settings:", error);
1442
+ return c.json({ error: error.message }, 500);
1443
+ }
1444
+ });
1445
+ app.post("/", async (c) => {
1446
+ try {
1447
+ const body = await c.req.json();
1448
+ const db = c.env.DB;
1449
+ const updates = Object.entries(body).map(([k, v]) => ({
1450
+ key: `${keyPrefix}${k}`,
1451
+ value: v
1452
+ }));
1453
+ if (updates.length === 0) return c.json({ success: true });
1454
+ const stmt = db.prepare(`
1455
+ INSERT INTO ${tableName} (key, value, updated_at)
1456
+ VALUES (?, ?, strftime('%s', 'now'))
1457
+ ON CONFLICT(key) DO UPDATE SET
1458
+ value = excluded.value,
1459
+ updated_at = excluded.updated_at
1460
+ `);
1461
+ const batch = updates.map((u) => stmt.bind(u.key, u.value === void 0 || u.value === null ? "" : String(u.value)));
1462
+ await db.batch(batch);
1463
+ return c.json({ success: true });
1464
+ } catch (error) {
1465
+ console.error("Failed to save settings:", error);
1466
+ return c.json({ error: error.message }, 500);
1467
+ }
1468
+ });
1469
+ return app;
1470
+ }
1471
+
1472
+ // src/backend/routes/templates.js
1473
+ var import_hono2 = require("hono");
1474
+ function createTemplateRoutes2(config = {}) {
1475
+ const app = new import_hono2.Hono();
1476
+ app.get("/", async (c) => {
1477
+ const emailService = new EmailService(c.env, config);
1403
1478
  try {
1404
1479
  const templates = await emailService.getAllTemplates();
1405
- return c.json({ success: true, templates });
1480
+ return c.json(templates);
1406
1481
  } catch (err) {
1407
- return c.json({ success: false, error: err.message }, 500);
1482
+ return c.json({ error: err.message }, 500);
1408
1483
  }
1409
1484
  });
1410
- app.get("/templates/:id", async (c) => {
1485
+ app.get("/:id", async (c) => {
1486
+ const emailService = new EmailService(c.env, config);
1411
1487
  try {
1412
1488
  const template = await emailService.getTemplate(c.req.param("id"));
1413
- if (!template) return c.json({ success: false, error: "Template not found" }, 404);
1414
- return c.json({ success: true, template });
1489
+ if (!template) return c.json({ error: "Template not found" }, 404);
1490
+ return c.json(template);
1415
1491
  } catch (err) {
1416
- return c.json({ success: false, error: err.message }, 500);
1492
+ return c.json({ error: err.message }, 500);
1417
1493
  }
1418
1494
  });
1419
- app.post("/templates", async (c) => {
1495
+ app.post("/", async (c) => {
1496
+ const emailService = new EmailService(c.env, config);
1420
1497
  try {
1421
1498
  const data = await c.req.json();
1422
- await emailService.saveTemplate(data, "admin");
1423
- return c.json({ success: true, message: "Template saved" });
1499
+ let userId = "admin";
1500
+ const user = c.get("dbUser") || c.get("user");
1501
+ if (user && user.id) userId = user.id;
1502
+ if (!data.template_id || !data.subject_template) {
1503
+ return c.json({ error: "Missing required fields (template_id, subject_template)" }, 400);
1504
+ }
1505
+ const result = await emailService.saveTemplate(data, userId);
1506
+ return c.json({ success: true, message: "Template saved", result });
1507
+ } catch (err) {
1508
+ return c.json({ error: err.message }, 500);
1509
+ }
1510
+ });
1511
+ app.post("/send-test", async (c) => {
1512
+ const emailService = new EmailService(c.env, config);
1513
+ try {
1514
+ const { template_id, to, variables } = await c.req.json();
1515
+ let tid = template_id;
1516
+ if (!tid || !to) {
1517
+ return c.json({ error: "Missing required fields (template_id, to)" }, 400);
1518
+ }
1519
+ const user = c.get("dbUser") || c.get("user");
1520
+ const recipientUserId = user?.id || null;
1521
+ const result = await emailService.sendViaTemplate(tid, variables || {}, {
1522
+ to,
1523
+ profile: "test",
1524
+ recipientUserId
1525
+ });
1526
+ return c.json({ success: true, result });
1424
1527
  } catch (err) {
1425
- return c.json({ success: false, error: err.message }, 500);
1528
+ return c.json({ error: `Failed to send test email: ${err.message}` }, 500);
1426
1529
  }
1427
1530
  });
1428
- app.delete("/templates/:id", async (c) => {
1531
+ app.delete("/:id", async (c) => {
1532
+ const emailService = new EmailService(c.env, config);
1429
1533
  try {
1430
1534
  await emailService.deleteTemplate(c.req.param("id"));
1431
1535
  return c.json({ success: true, message: "Template deleted" });
1432
1536
  } catch (err) {
1433
- return c.json({ success: false, error: err.message }, 500);
1537
+ return c.json({ error: err.message }, 500);
1434
1538
  }
1435
1539
  });
1436
- app.post("/templates/:id/preview", async (c) => {
1540
+ app.post("/:id/preview", async (c) => {
1541
+ const emailService = new EmailService(c.env, config);
1437
1542
  try {
1438
1543
  const id = c.req.param("id");
1439
1544
  const data = await c.req.json();
1440
1545
  const result = await emailService.renderTemplate(id, data);
1441
1546
  return c.json({ success: true, preview: result });
1442
1547
  } catch (err) {
1443
- return c.json({ success: false, error: err.message }, 500);
1444
- }
1445
- });
1446
- app.post("/templates/:id/test", async (c) => {
1447
- try {
1448
- const id = c.req.param("id");
1449
- const { to, data } = await c.req.json();
1450
- const { subject, html, plainText } = await emailService.renderTemplate(id, data);
1451
- const result = await emailService.sendEmail({
1452
- to,
1453
- subject: `[TEST] ${subject}`,
1454
- html,
1455
- text: plainText
1456
- });
1457
- if (result.success) {
1458
- return c.json({ success: true, message: "Test email sent" });
1459
- } else {
1460
- return c.json({ success: false, error: result.error }, 500);
1461
- }
1462
- } catch (err) {
1463
- return c.json({ success: false, error: err.message }, 500);
1548
+ return c.json({ error: err.message }, 500);
1464
1549
  }
1465
1550
  });
1466
1551
  return app;
1467
1552
  }
1468
1553
 
1469
1554
  // src/backend/routes/tracking.js
1470
- var import_hono2 = require("hono");
1555
+ var import_hono3 = require("hono");
1471
1556
  var TRACKING_PIXEL = new Uint8Array([
1472
1557
  71,
1473
1558
  73,
@@ -1513,7 +1598,7 @@ var TRACKING_PIXEL = new Uint8Array([
1513
1598
  59
1514
1599
  ]);
1515
1600
  function createTrackingRoutes(env, config = {}) {
1516
- const app = new import_hono2.Hono();
1601
+ const app = new import_hono3.Hono();
1517
1602
  const db = env.DB;
1518
1603
  const tablePrefix = config.emailTablePrefix || config.tableNamePrefix || "system_email_";
1519
1604
  app.get("/track/open/:token", async (c) => {
@@ -1641,11 +1726,19 @@ function createTrackingRoutes(env, config = {}) {
1641
1726
  return app;
1642
1727
  }
1643
1728
 
1729
+ // src/backend/routes/logs.js
1730
+ var import_hono4 = require("hono");
1731
+
1644
1732
  // src/backend/routes/index.js
1645
- function createEmailRoutes(env, config = {}, cacheProvider = null) {
1646
- const app = new import_hono3.Hono();
1647
- app.route("/api/email", createTemplateRoutes(env, config, cacheProvider));
1648
- app.route("/email", createTrackingRoutes(env, config));
1733
+ function createEmailRoutes(config = {}, cacheProvider = null) {
1734
+ const app = new import_hono5.Hono();
1735
+ app.route("/templates", createTemplateRoutes(config, cacheProvider));
1736
+ app.route("/logs", createLogRoutes(config));
1737
+ app.route("/settings", createSettingsRoutes({
1738
+ ...config,
1739
+ tableName: config.settingsTableName || "system_settings",
1740
+ keyPrefix: config.settingsKeyPrefix || "system_email."
1741
+ }));
1649
1742
  return app;
1650
1743
  }
1651
1744