@sonicjs-cms/core 2.17.2 → 2.18.1

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.
Files changed (43) hide show
  1. package/dist/{chunk-ITGOUYVN.js → chunk-4R3NOOL3.js} +2 -2
  2. package/dist/{chunk-ITGOUYVN.js.map → chunk-4R3NOOL3.js.map} +1 -1
  3. package/dist/{chunk-LVGB5UU5.cjs → chunk-C54YUA23.cjs} +2 -2
  4. package/dist/{chunk-LVGB5UU5.cjs.map → chunk-C54YUA23.cjs.map} +1 -1
  5. package/dist/{chunk-P4RAIX7B.cjs → chunk-DSUJ5YQH.cjs} +8 -8
  6. package/dist/{chunk-P4RAIX7B.cjs.map → chunk-DSUJ5YQH.cjs.map} +1 -1
  7. package/dist/{chunk-NAYUXSNR.js → chunk-EW5NOBVU.js} +9 -3
  8. package/dist/chunk-EW5NOBVU.js.map +1 -0
  9. package/dist/{chunk-K6QVIOTA.js → chunk-I2H5NGJQ.js} +4 -4
  10. package/dist/{chunk-K6QVIOTA.js.map → chunk-I2H5NGJQ.js.map} +1 -1
  11. package/dist/{chunk-I2Z72YTD.js → chunk-MGFRZO24.js} +3 -3
  12. package/dist/{chunk-I2Z72YTD.js.map → chunk-MGFRZO24.js.map} +1 -1
  13. package/dist/{chunk-Q3W6LCEN.cjs → chunk-SQ6FNXU2.cjs} +3 -3
  14. package/dist/{chunk-Q3W6LCEN.cjs.map → chunk-SQ6FNXU2.cjs.map} +1 -1
  15. package/dist/{chunk-2VY2G7OR.cjs → chunk-SXXTQETM.cjs} +245 -125
  16. package/dist/chunk-SXXTQETM.cjs.map +1 -0
  17. package/dist/{chunk-FXWF5D5V.cjs → chunk-T3Q5V33G.cjs} +9 -3
  18. package/dist/chunk-T3Q5V33G.cjs.map +1 -0
  19. package/dist/{chunk-KJSZMIBF.js → chunk-XXDFQERJ.js} +131 -12
  20. package/dist/chunk-XXDFQERJ.js.map +1 -0
  21. package/dist/index.cjs +211 -158
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.js +80 -27
  24. package/dist/index.js.map +1 -1
  25. package/dist/middleware.cjs +32 -32
  26. package/dist/middleware.js +3 -3
  27. package/dist/migrations-IYNTWDC6.cjs +13 -0
  28. package/dist/{migrations-Q7C6F2RM.cjs.map → migrations-IYNTWDC6.cjs.map} +1 -1
  29. package/dist/migrations-R337UD46.js +4 -0
  30. package/dist/{migrations-IFZLGVV3.js.map → migrations-R337UD46.js.map} +1 -1
  31. package/dist/routes.cjs +28 -28
  32. package/dist/routes.js +5 -5
  33. package/dist/services.cjs +23 -23
  34. package/dist/services.js +2 -2
  35. package/dist/utils.cjs +11 -11
  36. package/dist/utils.js +1 -1
  37. package/package.json +1 -1
  38. package/dist/chunk-2VY2G7OR.cjs.map +0 -1
  39. package/dist/chunk-FXWF5D5V.cjs.map +0 -1
  40. package/dist/chunk-KJSZMIBF.js.map +0 -1
  41. package/dist/chunk-NAYUXSNR.js.map +0 -1
  42. package/dist/migrations-IFZLGVV3.js +0 -4
  43. package/dist/migrations-Q7C6F2RM.cjs +0 -13
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
- import { renderConfirmationDialog, getConfirmationDialogScript, api_default, api_media_default, api_system_default, admin_api_default, router, adminCollectionsRoutes, adminFormsRoutes, adminSettingsRoutes, public_forms_default, router2, admin_content_default, adminMediaRoutes, userProfilesPlugin, adminPluginRoutes, adminLogsRoutes, userRoutes, auth_default, test_cleanup_default } from './chunk-KJSZMIBF.js';
2
- export { ROUTES_INFO, admin_api_default as adminApiRoutes, adminCheckboxRoutes, admin_code_examples_default as adminCodeExamplesRoutes, adminCollectionsRoutes, admin_content_default as adminContentRoutes, router as adminDashboardRoutes, adminDesignRoutes, adminLogsRoutes, adminMediaRoutes, adminPluginRoutes, adminSettingsRoutes, admin_testimonials_default as adminTestimonialsRoutes, userRoutes as adminUsersRoutes, api_content_crud_default as apiContentCrudRoutes, api_media_default as apiMediaRoutes, api_default as apiRoutes, api_system_default as apiSystemRoutes, auth_default as authRoutes, createUserProfilesPlugin, defineUserProfile, getUserProfileConfig, userProfilesPlugin } from './chunk-KJSZMIBF.js';
1
+ import { getCustomData, renderConfirmationDialog, getConfirmationDialogScript, api_default, api_media_default, api_system_default, admin_api_default, router, adminCollectionsRoutes, adminFormsRoutes, adminSettingsRoutes, public_forms_default, router2, admin_content_default, adminMediaRoutes, userProfilesPlugin, adminPluginRoutes, adminLogsRoutes, userRoutes, auth_default, test_cleanup_default } from './chunk-XXDFQERJ.js';
2
+ export { ROUTES_INFO, admin_api_default as adminApiRoutes, adminCheckboxRoutes, admin_code_examples_default as adminCodeExamplesRoutes, adminCollectionsRoutes, admin_content_default as adminContentRoutes, router as adminDashboardRoutes, adminDesignRoutes, adminLogsRoutes, adminMediaRoutes, adminPluginRoutes, adminSettingsRoutes, admin_testimonials_default as adminTestimonialsRoutes, userRoutes as adminUsersRoutes, api_content_crud_default as apiContentCrudRoutes, api_media_default as apiMediaRoutes, api_default as apiRoutes, api_system_default as apiSystemRoutes, auth_default as authRoutes, createUserProfilesPlugin, defineUserProfile, getUserProfileConfig, userProfilesPlugin } from './chunk-XXDFQERJ.js';
3
3
  import { SettingsService, setAppInstance, schema_exports } from './chunk-QFWHAFEO.js';
4
4
  export { Logger, apiTokens, collections, content, contentVersions, getLogger, initLogger, insertCollectionSchema, insertContentSchema, insertLogConfigSchema, insertMediaSchema, insertPluginActivityLogSchema, insertPluginAssetSchema, insertPluginHookSchema, insertPluginRouteSchema, insertPluginSchema, insertSystemLogSchema, insertUserSchema, insertWorkflowHistorySchema, logConfig, media, pluginActivityLog, pluginAssets, pluginHooks, pluginRoutes, plugins, selectCollectionSchema, selectContentSchema, selectLogConfigSchema, selectMediaSchema, selectPluginActivityLogSchema, selectPluginAssetSchema, selectPluginHookSchema, selectPluginRouteSchema, selectPluginSchema, selectSystemLogSchema, selectUserSchema, selectWorkflowHistorySchema, systemLogs, users, workflowHistory } from './chunk-QFWHAFEO.js';
5
- import { requireAuth, getJwtExpirySecondsFromDb, AuthManager, metricsMiddleware, bootstrapMiddleware, securityHeadersMiddleware, csrfProtection, requireRole } from './chunk-K6QVIOTA.js';
6
- export { AuthManager, PermissionManager, bootstrapMiddleware, cacheHeaders, compressionMiddleware, detailedLoggingMiddleware, getActivePlugins, isPluginActive, logActivity, loggingMiddleware, optionalAuth, performanceLoggingMiddleware, requireActivePlugin, requireActivePlugins, requireAnyPermission, requireAuth, requirePermission, requireRole, securityHeadersMiddleware as securityHeaders, securityLoggingMiddleware } from './chunk-K6QVIOTA.js';
7
- import { PluginService, PLUGIN_REGISTRY } from './chunk-NAYUXSNR.js';
8
- export { PluginBootstrapService, PluginService as PluginServiceClass, backfillFormSubmissions, cleanupRemovedCollections, createContentFromSubmission, deriveCollectionSchemaFromFormio, deriveSubmissionTitle, fullCollectionSync, getAvailableCollectionNames, getManagedCollections, isCollectionManaged, loadCollectionConfig, loadCollectionConfigs, mapFormStatusToContentStatus, registerCollections, syncAllFormCollections, syncCollection, syncCollections, syncFormCollection, validateCollectionConfig } from './chunk-NAYUXSNR.js';
9
- export { MigrationService } from './chunk-ITGOUYVN.js';
5
+ import { requireAuth, getJwtExpirySecondsFromDb, AuthManager, metricsMiddleware, bootstrapMiddleware, securityHeadersMiddleware, csrfProtection, requireRole } from './chunk-I2H5NGJQ.js';
6
+ export { AuthManager, PermissionManager, bootstrapMiddleware, cacheHeaders, compressionMiddleware, detailedLoggingMiddleware, getActivePlugins, isPluginActive, logActivity, loggingMiddleware, optionalAuth, performanceLoggingMiddleware, requireActivePlugin, requireActivePlugins, requireAnyPermission, requireAuth, requirePermission, requireRole, securityHeadersMiddleware as securityHeaders, securityLoggingMiddleware } from './chunk-I2H5NGJQ.js';
7
+ import { PluginService, PLUGIN_REGISTRY } from './chunk-EW5NOBVU.js';
8
+ export { PluginBootstrapService, PluginService as PluginServiceClass, backfillFormSubmissions, cleanupRemovedCollections, createContentFromSubmission, deriveCollectionSchemaFromFormio, deriveSubmissionTitle, fullCollectionSync, getAvailableCollectionNames, getManagedCollections, isCollectionManaged, loadCollectionConfig, loadCollectionConfigs, mapFormStatusToContentStatus, registerCollections, syncAllFormCollections, syncCollection, syncCollections, syncFormCollection, validateCollectionConfig } from './chunk-EW5NOBVU.js';
9
+ export { MigrationService } from './chunk-4R3NOOL3.js';
10
10
  export { renderFilterBar } from './chunk-ON5ZMSU4.js';
11
11
  import { renderAdminLayout } from './chunk-XWIA3HVX.js';
12
12
  export { getConfirmationDialogScript, renderAlert, renderConfirmationDialog, renderForm, renderFormField, renderPagination, renderTable } from './chunk-XWIA3HVX.js';
@@ -14,8 +14,8 @@ import { init_admin_layout_catalyst_template, renderAdminLayoutCatalyst } from '
14
14
  export { HookSystemImpl, HookUtils, PluginManager as PluginManagerClass, PluginRegistryImpl, PluginValidator as PluginValidatorClass, ScopedHookSystem as ScopedHookSystemClass } from './chunk-TFNTM3OA.js';
15
15
  import { PluginBuilder, PluginHelpers } from './chunk-EXNEW5US.js';
16
16
  export { PluginBuilder, PluginHelpers } from './chunk-EXNEW5US.js';
17
- import { package_default, getCoreVersion } from './chunk-I2Z72YTD.js';
18
- export { QueryFilterBuilder, SONICJS_VERSION, TemplateRenderer, buildQuery, getCoreVersion, renderTemplate, templateRenderer } from './chunk-I2Z72YTD.js';
17
+ import { package_default, getCoreVersion } from './chunk-MGFRZO24.js';
18
+ export { QueryFilterBuilder, SONICJS_VERSION, TemplateRenderer, buildQuery, getCoreVersion, renderTemplate, templateRenderer } from './chunk-MGFRZO24.js';
19
19
  import './chunk-X7ZAEI5S.js';
20
20
  export { metricsTracker } from './chunk-FICTAGD4.js';
21
21
  export { escapeHtml, sanitizeInput, sanitizeObject } from './chunk-TQABQWOP.js';
@@ -1613,7 +1613,27 @@ var OTPService = class {
1613
1613
  };
1614
1614
 
1615
1615
  // src/plugins/core-plugins/otp-login-plugin/email-templates.ts
1616
+ function sanitizeColor(value) {
1617
+ if (!value) return "";
1618
+ if (/^#[0-9a-fA-F]{3,8}$/.test(value)) return value;
1619
+ if (/^[a-zA-Z]+$/.test(value)) return value;
1620
+ if (/^(rgb|rgba|hsl|hsla)\([0-9.,\s%]+\)$/.test(value)) return value;
1621
+ return "";
1622
+ }
1623
+ function escapeHtml3(value) {
1624
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
1625
+ }
1616
1626
  function renderOTPEmailHTML(data) {
1627
+ const logoUrl = data.logoUrl ? escapeHtml3(data.logoUrl) : "";
1628
+ const loginUrl = data.loginUrl ? escapeHtml3(data.loginUrl) : "";
1629
+ const appName = escapeHtml3(data.appName);
1630
+ const loginButtonText = escapeHtml3(
1631
+ data.loginButtonText && data.loginButtonText.trim() || `Sign in to ${data.appName}`
1632
+ );
1633
+ const logoWidth = Math.max(20, Math.min(600, Number(data.logoWidth) || 150));
1634
+ const logoBorderWidth = Math.max(0, Math.min(20, Number(data.logoBorderWidth) || 0));
1635
+ const logoBorderColor = sanitizeColor(data.logoBorderColor);
1636
+ const logoBorderStyle = logoBorderWidth > 0 && logoBorderColor ? `border: ${logoBorderWidth}px solid ${logoBorderColor}; border-radius: 8px;` : "";
1617
1637
  return `<!DOCTYPE html>
1618
1638
  <html>
1619
1639
  <head>
@@ -1625,15 +1645,15 @@ function renderOTPEmailHTML(data) {
1625
1645
 
1626
1646
  <div style="background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
1627
1647
 
1628
- ${data.logoUrl ? `
1648
+ ${logoUrl ? `
1629
1649
  <div style="text-align: center; padding: 30px 20px 20px;">
1630
- <img src="${data.logoUrl}" alt="Logo" style="max-width: 150px; height: auto;">
1650
+ <img src="${logoUrl}" alt="${appName}" style="max-width: ${logoWidth}px; width: 100%; height: auto; ${logoBorderStyle}">
1631
1651
  </div>
1632
1652
  ` : ""}
1633
1653
 
1634
1654
  <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 40px 30px; text-align: center;">
1635
1655
  <h1 style="margin: 0 0 10px 0; font-size: 32px; font-weight: 600;">Your Login Code</h1>
1636
- <p style="margin: 0; opacity: 0.95; font-size: 16px;">Enter this code to sign in to ${data.appName}</p>
1656
+ <p style="margin: 0; opacity: 0.95; font-size: 16px;">Enter this code to sign in to ${appName}</p>
1637
1657
  </div>
1638
1658
 
1639
1659
  <div style="padding: 40px 30px;">
@@ -1643,6 +1663,14 @@ function renderOTPEmailHTML(data) {
1643
1663
  </div>
1644
1664
  </div>
1645
1665
 
1666
+ ${loginUrl ? `
1667
+ <div style="text-align: center; margin: 0 0 30px 0;">
1668
+ <a href="${loginUrl}" style="display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; text-decoration: none; padding: 14px 32px; border-radius: 8px; font-weight: 600; font-size: 16px;">
1669
+ ${loginButtonText}
1670
+ </a>
1671
+ </div>
1672
+ ` : ""}
1673
+
1646
1674
  <div style="background: #fff3cd; border-left: 4px solid #ffc107; padding: 16px 20px; margin: 0 0 30px 0; border-radius: 6px;">
1647
1675
  <p style="margin: 0; font-size: 14px; color: #856404;">
1648
1676
  <strong>\u26A0\uFE0F This code expires in ${data.expiryMinutes} minutes</strong>
@@ -1664,7 +1692,7 @@ function renderOTPEmailHTML(data) {
1664
1692
  \u{1F512} Security Notice
1665
1693
  </p>
1666
1694
  <p style="margin: 0; font-size: 13px; color: #004080; line-height: 1.6;">
1667
- Never share this code with anyone. ${data.appName} will never ask you for this code via phone, email, or social media.
1695
+ Never share this code with anyone. ${appName} will never ask you for this code via phone, email, or social media.
1668
1696
  </p>
1669
1697
  </div>
1670
1698
  </div>
@@ -1676,22 +1704,23 @@ function renderOTPEmailHTML(data) {
1676
1704
  </p>
1677
1705
 
1678
1706
  <div style="text-align: center; color: #999; font-size: 12px; line-height: 1.6;">
1679
- <p style="margin: 5px 0;">This email was sent to ${data.email}</p>
1680
- ${data.ipAddress ? `<p style="margin: 5px 0;">IP Address: ${data.ipAddress}</p>` : ""}
1681
- <p style="margin: 5px 0;">Time: ${data.timestamp}</p>
1707
+ <p style="margin: 5px 0;">This email was sent to ${escapeHtml3(data.email)}</p>
1708
+ ${data.ipAddress ? `<p style="margin: 5px 0;">IP Address: ${escapeHtml3(data.ipAddress)}</p>` : ""}
1709
+ <p style="margin: 5px 0;">Time: ${escapeHtml3(data.timestamp)}</p>
1682
1710
  </div>
1683
1711
  </div>
1684
1712
 
1685
1713
  </div>
1686
1714
 
1687
1715
  <div style="text-align: center; padding: 20px; color: #999; font-size: 12px;">
1688
- <p style="margin: 0;">&copy; ${(/* @__PURE__ */ new Date()).getFullYear()} ${data.appName}. All rights reserved.</p>
1716
+ <p style="margin: 0;">&copy; ${(/* @__PURE__ */ new Date()).getFullYear()} ${appName}. All rights reserved.</p>
1689
1717
  </div>
1690
1718
 
1691
1719
  </body>
1692
1720
  </html>`;
1693
1721
  }
1694
1722
  function renderOTPEmailText(data) {
1723
+ const ctaLabel = data.loginButtonText && data.loginButtonText.trim() || `Sign in to ${data.appName}`;
1695
1724
  return `Your Login Code for ${data.appName}
1696
1725
 
1697
1726
  Your one-time verification code is:
@@ -1699,6 +1728,9 @@ Your one-time verification code is:
1699
1728
  ${data.code}
1700
1729
 
1701
1730
  This code expires in ${data.expiryMinutes} minutes.
1731
+ ${data.loginUrl ? `
1732
+ ${ctaLabel}: ${data.loginUrl}
1733
+ ` : ""}
1702
1734
 
1703
1735
  Quick Tips:
1704
1736
  \u2022 Enter the code exactly as shown (${data.codeLength} digits)
@@ -1739,7 +1771,13 @@ var DEFAULT_SETTINGS = {
1739
1771
  codeExpiryMinutes: 10,
1740
1772
  maxAttempts: 3,
1741
1773
  rateLimitPerHour: 5,
1742
- allowNewUserRegistration: false
1774
+ allowNewUserRegistration: false,
1775
+ logoUrl: "",
1776
+ logoWidth: 150,
1777
+ logoBorderWidth: 0,
1778
+ logoBorderColor: "#ffffff",
1779
+ loginUrl: "",
1780
+ loginButtonText: ""
1743
1781
  };
1744
1782
  function createOTPLoginPlugin() {
1745
1783
  const builder = PluginBuilder.create({
@@ -1829,7 +1867,12 @@ function createOTPLoginPlugin() {
1829
1867
  ipAddress,
1830
1868
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1831
1869
  appName: siteName,
1832
- logoUrl: settings.logoUrl || ""
1870
+ logoUrl: settings.logoUrl || "",
1871
+ logoWidth: settings.logoWidth,
1872
+ logoBorderWidth: settings.logoBorderWidth,
1873
+ logoBorderColor: settings.logoBorderColor || "",
1874
+ loginUrl: settings.loginUrl || "",
1875
+ loginButtonText: settings.loginButtonText || ""
1833
1876
  });
1834
1877
  const emailPlugin2 = await db.prepare(`
1835
1878
  SELECT settings FROM plugins WHERE id = 'email'
@@ -1918,7 +1961,7 @@ function createOTPLoginPlugin() {
1918
1961
  }, 401);
1919
1962
  }
1920
1963
  let user = await db.prepare(`
1921
- SELECT id, email, role, is_active
1964
+ SELECT id, email, username, first_name, last_name, role, is_active, created_at
1922
1965
  FROM users
1923
1966
  WHERE email = ?
1924
1967
  `).bind(normalizedEmail).first();
@@ -1932,7 +1975,16 @@ function createOTPLoginPlugin() {
1932
1975
  password_hash, role, is_active, email_verified, created_at, updated_at
1933
1976
  ) VALUES (?, ?, ?, '', '', NULL, 'viewer', 1, 1, ?, ?)
1934
1977
  `).bind(userId, normalizedEmail, username, now, now).run();
1935
- user = { id: userId, email: normalizedEmail, role: "viewer", is_active: 1 };
1978
+ user = {
1979
+ id: userId,
1980
+ email: normalizedEmail,
1981
+ username,
1982
+ first_name: "",
1983
+ last_name: "",
1984
+ role: "viewer",
1985
+ is_active: 1,
1986
+ created_at: now
1987
+ };
1936
1988
  }
1937
1989
  if (!user) {
1938
1990
  return c.json({
@@ -1952,12 +2004,13 @@ function createOTPLoginPlugin() {
1952
2004
  sameSite: "Strict",
1953
2005
  maxAge: tokenTtl
1954
2006
  });
2007
+ const customData = await getCustomData(db, user.id);
2008
+ const { is_active, ...publicUser } = user;
1955
2009
  return c.json({
1956
2010
  success: true,
1957
2011
  user: {
1958
- id: user.id,
1959
- email: user.email,
1960
- role: user.role
2012
+ ...publicUser,
2013
+ ...customData
1961
2014
  },
1962
2015
  token,
1963
2016
  message: "Authentication successful"
@@ -7868,7 +7921,7 @@ adminRoutes4.get("/", async (c) => {
7868
7921
  <div class="divide-y divide-zinc-950/5 dark:divide-white/10">
7869
7922
  ${topPages.length > 0 ? topPages.map((p) => `
7870
7923
  <div class="flex items-center justify-between px-6 py-3">
7871
- <span class="text-sm text-zinc-700 dark:text-zinc-300 font-mono truncate">${escapeHtml3(p.path)}</span>
7924
+ <span class="text-sm text-zinc-700 dark:text-zinc-300 font-mono truncate">${escapeHtml4(p.path)}</span>
7872
7925
  <span class="text-sm font-medium text-zinc-500 dark:text-zinc-400">${p.views}</span>
7873
7926
  </div>
7874
7927
  `).join("") : `
@@ -7897,7 +7950,7 @@ adminRoutes4.get("/", async (c) => {
7897
7950
  <tbody class="divide-y divide-zinc-950/5 dark:divide-white/10">
7898
7951
  ${recentActivity.length > 0 ? recentActivity.map((a) => `
7899
7952
  <tr>
7900
- <td class="px-6 py-2 font-mono text-zinc-700 dark:text-zinc-300 truncate max-w-xs">${escapeHtml3(a.url || "")}</td>
7953
+ <td class="px-6 py-2 font-mono text-zinc-700 dark:text-zinc-300 truncate max-w-xs">${escapeHtml4(a.url || "")}</td>
7901
7954
  <td class="px-6 py-2"><span class="inline-flex items-center rounded px-1.5 py-0.5 text-xs font-medium ${a.method === "GET" ? "bg-green-50 text-green-700 dark:bg-green-900/30 dark:text-green-400" : "bg-blue-50 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400"}">${a.method || ""}</span></td>
7902
7955
  <td class="px-6 py-2"><span class="inline-flex items-center rounded px-1.5 py-0.5 text-xs font-medium ${(a.status_code || 0) >= 400 ? "bg-red-50 text-red-700 dark:bg-red-900/30 dark:text-red-400" : "bg-green-50 text-green-700 dark:bg-green-900/30 dark:text-green-400"}">${a.status_code || ""}</span></td>
7903
7956
  <td class="px-6 py-2 text-zinc-500 dark:text-zinc-400">${a.duration || 0}ms</td>
@@ -7927,7 +7980,7 @@ adminRoutes4.get("/", async (c) => {
7927
7980
  dynamicMenuItems: c.get("pluginMenuItems")
7928
7981
  }));
7929
7982
  });
7930
- function escapeHtml3(str) {
7983
+ function escapeHtml4(str) {
7931
7984
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
7932
7985
  }
7933
7986