@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.d.cts CHANGED
@@ -6,3 +6,4 @@ export { createEmailRoutes, createTemplateRoutes, createTrackingRoutes } from '.
6
6
  export { encodeTrackingLinks, extractVariables, getWebsiteUrl, markdownToPlainText, resetWebsiteUrlCache, wrapInEmailTemplate } from './common/index.cjs';
7
7
  import 'react';
8
8
  import 'hono';
9
+ import 'hono/types';
package/dist/index.d.ts CHANGED
@@ -6,3 +6,4 @@ export { createEmailRoutes, createTemplateRoutes, createTrackingRoutes } from '.
6
6
  export { encodeTrackingLinks, extractVariables, getWebsiteUrl, markdownToPlainText, resetWebsiteUrlCache, wrapInEmailTemplate } from './common/index.js';
7
7
  import 'react';
8
8
  import 'hono';
9
+ import 'hono/types';
package/dist/index.js CHANGED
@@ -766,6 +766,9 @@ var EmailService = class {
766
766
  // Updater function to save settings to backend
767
767
  // Signature: async (profile, tenantId, settings) => void
768
768
  settingsUpdater: config.settingsUpdater || null,
769
+ // Settings configuration
770
+ settingsTableName: config.settingsTableName || "system_settings",
771
+ settingsKeyPrefix: config.settingsKeyPrefix || "system_email.",
769
772
  // Branding configuration for email templates
770
773
  branding: {
771
774
  brandName: config.branding?.brandName || "Your App",
@@ -814,6 +817,22 @@ var EmailService = class {
814
817
  console.warn("[EmailService] settingsLoader failed:", e);
815
818
  }
816
819
  }
820
+ if (!settings && profile === "system" && this.db) {
821
+ try {
822
+ const tableName = this.config.settingsTableName;
823
+ const prefix = this.config.settingsKeyPrefix;
824
+ const { results } = await this.db.prepare(`SELECT * FROM ${tableName} WHERE key LIKE ?`).bind(`${prefix}%`).all();
825
+ if (results && results.length > 0) {
826
+ settings = {};
827
+ for (const row of results) {
828
+ const cleanKey = row.key.slice(prefix.length);
829
+ settings[cleanKey] = row.value;
830
+ }
831
+ }
832
+ } catch (e) {
833
+ console.warn("[EmailService] Failed to load settings from DB:", e.message);
834
+ }
835
+ }
817
836
  if (settings) {
818
837
  if (this.cache && this.cache.putSettings) {
819
838
  try {
@@ -1344,82 +1363,148 @@ var EmailService = class {
1344
1363
  };
1345
1364
 
1346
1365
  // src/backend/routes/index.js
1347
- import { Hono as Hono3 } from "hono";
1366
+ import { Hono as Hono5 } from "hono";
1348
1367
 
1349
- // src/backend/routes/templates.js
1368
+ // src/backend/routes/settings.js
1350
1369
  import { Hono } from "hono";
1351
- function createTemplateRoutes(env, config = {}, cacheProvider = null) {
1370
+ function createSettingsRoutes(config = {}) {
1352
1371
  const app = new Hono();
1353
- const emailService = new EmailService(env, config, cacheProvider);
1354
- app.get("/templates", async (c) => {
1372
+ const tableName = config.tableName || "system_settings";
1373
+ const keyPrefix = config.keyPrefix || "system_email.";
1374
+ const getSettings = async (db) => {
1375
+ try {
1376
+ const { results } = await db.prepare(`SELECT * FROM ${tableName} WHERE key LIKE ?`).bind(`${keyPrefix}%`).all();
1377
+ const settings = {};
1378
+ for (const row of results) {
1379
+ const cleanKey = row.key.slice(keyPrefix.length);
1380
+ settings[cleanKey] = row.value;
1381
+ }
1382
+ return settings;
1383
+ } catch (e) {
1384
+ console.warn(`[Settings] Failed to fetch from ${tableName}:`, e.message);
1385
+ return {};
1386
+ }
1387
+ };
1388
+ app.get("/", async (c) => {
1389
+ try {
1390
+ const settings = await getSettings(c.env.DB);
1391
+ return c.json(settings);
1392
+ } catch (error) {
1393
+ console.error("Failed to fetch settings:", error);
1394
+ return c.json({ error: error.message }, 500);
1395
+ }
1396
+ });
1397
+ app.post("/", async (c) => {
1398
+ try {
1399
+ const body = await c.req.json();
1400
+ const db = c.env.DB;
1401
+ const updates = Object.entries(body).map(([k, v]) => ({
1402
+ key: `${keyPrefix}${k}`,
1403
+ value: v
1404
+ }));
1405
+ if (updates.length === 0) return c.json({ success: true });
1406
+ const stmt = db.prepare(`
1407
+ INSERT INTO ${tableName} (key, value, updated_at)
1408
+ VALUES (?, ?, strftime('%s', 'now'))
1409
+ ON CONFLICT(key) DO UPDATE SET
1410
+ value = excluded.value,
1411
+ updated_at = excluded.updated_at
1412
+ `);
1413
+ const batch = updates.map((u) => stmt.bind(u.key, u.value === void 0 || u.value === null ? "" : String(u.value)));
1414
+ await db.batch(batch);
1415
+ return c.json({ success: true });
1416
+ } catch (error) {
1417
+ console.error("Failed to save settings:", error);
1418
+ return c.json({ error: error.message }, 500);
1419
+ }
1420
+ });
1421
+ return app;
1422
+ }
1423
+
1424
+ // src/backend/routes/templates.js
1425
+ import { Hono as Hono2 } from "hono";
1426
+ function createTemplateRoutes2(config = {}) {
1427
+ const app = new Hono2();
1428
+ app.get("/", async (c) => {
1429
+ const emailService = new EmailService(c.env, config);
1355
1430
  try {
1356
1431
  const templates = await emailService.getAllTemplates();
1357
- return c.json({ success: true, templates });
1432
+ return c.json(templates);
1358
1433
  } catch (err) {
1359
- return c.json({ success: false, error: err.message }, 500);
1434
+ return c.json({ error: err.message }, 500);
1360
1435
  }
1361
1436
  });
1362
- app.get("/templates/:id", async (c) => {
1437
+ app.get("/:id", async (c) => {
1438
+ const emailService = new EmailService(c.env, config);
1363
1439
  try {
1364
1440
  const template = await emailService.getTemplate(c.req.param("id"));
1365
- if (!template) return c.json({ success: false, error: "Template not found" }, 404);
1366
- return c.json({ success: true, template });
1441
+ if (!template) return c.json({ error: "Template not found" }, 404);
1442
+ return c.json(template);
1367
1443
  } catch (err) {
1368
- return c.json({ success: false, error: err.message }, 500);
1444
+ return c.json({ error: err.message }, 500);
1369
1445
  }
1370
1446
  });
1371
- app.post("/templates", async (c) => {
1447
+ app.post("/", async (c) => {
1448
+ const emailService = new EmailService(c.env, config);
1372
1449
  try {
1373
1450
  const data = await c.req.json();
1374
- await emailService.saveTemplate(data, "admin");
1375
- return c.json({ success: true, message: "Template saved" });
1451
+ let userId = "admin";
1452
+ const user = c.get("dbUser") || c.get("user");
1453
+ if (user && user.id) userId = user.id;
1454
+ if (!data.template_id || !data.subject_template) {
1455
+ return c.json({ error: "Missing required fields (template_id, subject_template)" }, 400);
1456
+ }
1457
+ const result = await emailService.saveTemplate(data, userId);
1458
+ return c.json({ success: true, message: "Template saved", result });
1459
+ } catch (err) {
1460
+ return c.json({ error: err.message }, 500);
1461
+ }
1462
+ });
1463
+ app.post("/send-test", async (c) => {
1464
+ const emailService = new EmailService(c.env, config);
1465
+ try {
1466
+ const { template_id, to, variables } = await c.req.json();
1467
+ let tid = template_id;
1468
+ if (!tid || !to) {
1469
+ return c.json({ error: "Missing required fields (template_id, to)" }, 400);
1470
+ }
1471
+ const user = c.get("dbUser") || c.get("user");
1472
+ const recipientUserId = user?.id || null;
1473
+ const result = await emailService.sendViaTemplate(tid, variables || {}, {
1474
+ to,
1475
+ profile: "test",
1476
+ recipientUserId
1477
+ });
1478
+ return c.json({ success: true, result });
1376
1479
  } catch (err) {
1377
- return c.json({ success: false, error: err.message }, 500);
1480
+ return c.json({ error: `Failed to send test email: ${err.message}` }, 500);
1378
1481
  }
1379
1482
  });
1380
- app.delete("/templates/:id", async (c) => {
1483
+ app.delete("/:id", async (c) => {
1484
+ const emailService = new EmailService(c.env, config);
1381
1485
  try {
1382
1486
  await emailService.deleteTemplate(c.req.param("id"));
1383
1487
  return c.json({ success: true, message: "Template deleted" });
1384
1488
  } catch (err) {
1385
- return c.json({ success: false, error: err.message }, 500);
1489
+ return c.json({ error: err.message }, 500);
1386
1490
  }
1387
1491
  });
1388
- app.post("/templates/:id/preview", async (c) => {
1492
+ app.post("/:id/preview", async (c) => {
1493
+ const emailService = new EmailService(c.env, config);
1389
1494
  try {
1390
1495
  const id = c.req.param("id");
1391
1496
  const data = await c.req.json();
1392
1497
  const result = await emailService.renderTemplate(id, data);
1393
1498
  return c.json({ success: true, preview: result });
1394
1499
  } catch (err) {
1395
- return c.json({ success: false, error: err.message }, 500);
1396
- }
1397
- });
1398
- app.post("/templates/:id/test", async (c) => {
1399
- try {
1400
- const id = c.req.param("id");
1401
- const { to, data } = await c.req.json();
1402
- const { subject, html, plainText } = await emailService.renderTemplate(id, data);
1403
- const result = await emailService.sendEmail({
1404
- to,
1405
- subject: `[TEST] ${subject}`,
1406
- html,
1407
- text: plainText
1408
- });
1409
- if (result.success) {
1410
- return c.json({ success: true, message: "Test email sent" });
1411
- } else {
1412
- return c.json({ success: false, error: result.error }, 500);
1413
- }
1414
- } catch (err) {
1415
- return c.json({ success: false, error: err.message }, 500);
1500
+ return c.json({ error: err.message }, 500);
1416
1501
  }
1417
1502
  });
1418
1503
  return app;
1419
1504
  }
1420
1505
 
1421
1506
  // src/backend/routes/tracking.js
1422
- import { Hono as Hono2 } from "hono";
1507
+ import { Hono as Hono3 } from "hono";
1423
1508
  var TRACKING_PIXEL = new Uint8Array([
1424
1509
  71,
1425
1510
  73,
@@ -1465,7 +1550,7 @@ var TRACKING_PIXEL = new Uint8Array([
1465
1550
  59
1466
1551
  ]);
1467
1552
  function createTrackingRoutes(env, config = {}) {
1468
- const app = new Hono2();
1553
+ const app = new Hono3();
1469
1554
  const db = env.DB;
1470
1555
  const tablePrefix = config.emailTablePrefix || config.tableNamePrefix || "system_email_";
1471
1556
  app.get("/track/open/:token", async (c) => {
@@ -1593,11 +1678,19 @@ function createTrackingRoutes(env, config = {}) {
1593
1678
  return app;
1594
1679
  }
1595
1680
 
1681
+ // src/backend/routes/logs.js
1682
+ import { Hono as Hono4 } from "hono";
1683
+
1596
1684
  // src/backend/routes/index.js
1597
- function createEmailRoutes(env, config = {}, cacheProvider = null) {
1598
- const app = new Hono3();
1599
- app.route("/api/email", createTemplateRoutes(env, config, cacheProvider));
1600
- app.route("/email", createTrackingRoutes(env, config));
1685
+ function createEmailRoutes(config = {}, cacheProvider = null) {
1686
+ const app = new Hono5();
1687
+ app.route("/templates", createTemplateRoutes(config, cacheProvider));
1688
+ app.route("/logs", createLogRoutes(config));
1689
+ app.route("/settings", createSettingsRoutes({
1690
+ ...config,
1691
+ tableName: config.settingsTableName || "system_settings",
1692
+ keyPrefix: config.settingsKeyPrefix || "system_email."
1693
+ }));
1601
1694
  return app;
1602
1695
  }
1603
1696
 
@@ -2143,7 +2236,7 @@ export {
2143
2236
  createDOCacheProvider,
2144
2237
  createEmailLoggerCallback,
2145
2238
  createEmailRoutes,
2146
- createTemplateRoutes,
2239
+ createTemplateRoutes2 as createTemplateRoutes,
2147
2240
  createTrackingRoutes,
2148
2241
  encodeTrackingLinks,
2149
2242
  extractVariables,