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