@sonicjs-cms/core 2.6.0 → 2.7.0

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 (49) hide show
  1. package/dist/{chunk-63K7XXRX.cjs → chunk-AYPF6C4D.cjs} +5 -5
  2. package/dist/{chunk-63K7XXRX.cjs.map → chunk-AYPF6C4D.cjs.map} +1 -1
  3. package/dist/{chunk-7DL5SPPX.js → chunk-DNHJS6RN.js} +3 -3
  4. package/dist/{chunk-7DL5SPPX.js.map → chunk-DNHJS6RN.js.map} +1 -1
  5. package/dist/{chunk-T3YIKW2A.cjs → chunk-E2BXLXPW.cjs} +4 -4
  6. package/dist/{chunk-T3YIKW2A.cjs.map → chunk-E2BXLXPW.cjs.map} +1 -1
  7. package/dist/{chunk-BZC4FYW7.cjs → chunk-EHSZ6TAN.cjs} +9 -2
  8. package/dist/chunk-EHSZ6TAN.cjs.map +1 -0
  9. package/dist/{chunk-KA2PDJNB.js → chunk-GRN3GHUG.js} +9 -2
  10. package/dist/chunk-GRN3GHUG.js.map +1 -0
  11. package/dist/{chunk-N7TDLOUE.cjs → chunk-J7F3NPAP.cjs} +208 -182
  12. package/dist/chunk-J7F3NPAP.cjs.map +1 -0
  13. package/dist/{chunk-EVZOVYLO.js → chunk-L2IDZI7F.js} +2 -2
  14. package/dist/{chunk-EVZOVYLO.js.map → chunk-L2IDZI7F.js.map} +1 -1
  15. package/dist/{chunk-YMTTGHEK.cjs → chunk-MYB5RY7H.cjs} +3 -3
  16. package/dist/{chunk-YMTTGHEK.cjs.map → chunk-MYB5RY7H.cjs.map} +1 -1
  17. package/dist/{chunk-F6GZURXJ.js → chunk-UISZ2MBW.js} +50 -26
  18. package/dist/chunk-UISZ2MBW.js.map +1 -0
  19. package/dist/{chunk-KAOWRIFD.js → chunk-V3KVSEG6.js} +3 -3
  20. package/dist/{chunk-KAOWRIFD.js.map → chunk-V3KVSEG6.js.map} +1 -1
  21. package/dist/{chunk-EYWR6UA2.js → chunk-Y3EWJQ4D.js} +3 -3
  22. package/dist/{chunk-EYWR6UA2.js.map → chunk-Y3EWJQ4D.js.map} +1 -1
  23. package/dist/{chunk-IIRVZSP2.cjs → chunk-YRFAQ6MI.cjs} +2 -2
  24. package/dist/{chunk-IIRVZSP2.cjs.map → chunk-YRFAQ6MI.cjs.map} +1 -1
  25. package/dist/index.cjs +1940 -122
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.js +1874 -56
  28. package/dist/index.js.map +1 -1
  29. package/dist/middleware.cjs +23 -23
  30. package/dist/middleware.js +2 -2
  31. package/dist/migrations-LEMFV2ND.cjs +13 -0
  32. package/dist/{migrations-QNYAWQLB.cjs.map → migrations-LEMFV2ND.cjs.map} +1 -1
  33. package/dist/migrations-RKQES6XY.js +4 -0
  34. package/dist/{migrations-R6NQBKQV.js.map → migrations-RKQES6XY.js.map} +1 -1
  35. package/dist/routes.cjs +25 -25
  36. package/dist/routes.js +5 -5
  37. package/dist/services.cjs +2 -2
  38. package/dist/services.js +1 -1
  39. package/dist/templates.cjs +17 -17
  40. package/dist/templates.js +2 -2
  41. package/dist/utils.cjs +14 -14
  42. package/dist/utils.js +1 -1
  43. package/package.json +1 -1
  44. package/dist/chunk-BZC4FYW7.cjs.map +0 -1
  45. package/dist/chunk-F6GZURXJ.js.map +0 -1
  46. package/dist/chunk-KA2PDJNB.js.map +0 -1
  47. package/dist/chunk-N7TDLOUE.cjs.map +0 -1
  48. package/dist/migrations-QNYAWQLB.cjs +0 -13
  49. package/dist/migrations-R6NQBKQV.js +0 -4
package/dist/index.cjs CHANGED
@@ -1,15 +1,15 @@
1
1
  'use strict';
2
2
 
3
- var chunkN7TDLOUE_cjs = require('./chunk-N7TDLOUE.cjs');
3
+ var chunkJ7F3NPAP_cjs = require('./chunk-J7F3NPAP.cjs');
4
4
  var chunk7FOAMNTI_cjs = require('./chunk-7FOAMNTI.cjs');
5
- var chunkT3YIKW2A_cjs = require('./chunk-T3YIKW2A.cjs');
5
+ var chunkE2BXLXPW_cjs = require('./chunk-E2BXLXPW.cjs');
6
6
  var chunkMPT5PA6U_cjs = require('./chunk-MPT5PA6U.cjs');
7
- var chunkIIRVZSP2_cjs = require('./chunk-IIRVZSP2.cjs');
8
- var chunk63K7XXRX_cjs = require('./chunk-63K7XXRX.cjs');
9
- var chunkBZC4FYW7_cjs = require('./chunk-BZC4FYW7.cjs');
7
+ var chunkYRFAQ6MI_cjs = require('./chunk-YRFAQ6MI.cjs');
8
+ var chunkAYPF6C4D_cjs = require('./chunk-AYPF6C4D.cjs');
9
+ var chunkEHSZ6TAN_cjs = require('./chunk-EHSZ6TAN.cjs');
10
10
  var chunkY72M3MVX_cjs = require('./chunk-Y72M3MVX.cjs');
11
11
  var chunkYHW27CBV_cjs = require('./chunk-YHW27CBV.cjs');
12
- var chunkYMTTGHEK_cjs = require('./chunk-YMTTGHEK.cjs');
12
+ var chunkMYB5RY7H_cjs = require('./chunk-MYB5RY7H.cjs');
13
13
  require('./chunk-P3XDZL6Q.cjs');
14
14
  var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
15
15
  var chunkKYGRJCZM_cjs = require('./chunk-KYGRJCZM.cjs');
@@ -235,7 +235,7 @@ var DatabaseToolsService = class {
235
235
  };
236
236
 
237
237
  // src/templates/pages/admin-database-table.template.ts
238
- chunkBZC4FYW7_cjs.init_admin_layout_catalyst_template();
238
+ chunkEHSZ6TAN_cjs.init_admin_layout_catalyst_template();
239
239
  function renderDatabaseTablePage(data) {
240
240
  const totalPages = Math.ceil(data.totalRows / data.pageSize);
241
241
  const startRow = (data.currentPage - 1) * data.pageSize + 1;
@@ -484,7 +484,7 @@ function renderDatabaseTablePage(data) {
484
484
  user: data.user,
485
485
  content: pageContent
486
486
  };
487
- return chunkBZC4FYW7_cjs.renderAdminLayoutCatalyst(layoutData);
487
+ return chunkEHSZ6TAN_cjs.renderAdminLayoutCatalyst(layoutData);
488
488
  }
489
489
  function generatePageNumbers(currentPage, totalPages) {
490
490
  const pages = [];
@@ -559,7 +559,7 @@ function formatCellValue(value) {
559
559
  // src/plugins/core-plugins/database-tools-plugin/admin-routes.ts
560
560
  function createDatabaseToolsAdminRoutes() {
561
561
  const router2 = new hono.Hono();
562
- router2.use("*", chunkT3YIKW2A_cjs.requireAuth());
562
+ router2.use("*", chunkE2BXLXPW_cjs.requireAuth());
563
563
  router2.get("/api/stats", async (c) => {
564
564
  try {
565
565
  const user = c.get("user");
@@ -1324,10 +1324,10 @@ function createEmailPlugin() {
1324
1324
  emailRoutes.get("/settings", async (c) => {
1325
1325
  const user = c.get("user");
1326
1326
  const db = c.env.DB;
1327
- const plugin = await db.prepare(`
1327
+ const plugin2 = await db.prepare(`
1328
1328
  SELECT settings FROM plugins WHERE id = 'email'
1329
1329
  `).first();
1330
- const settings = plugin?.settings ? JSON.parse(plugin.settings) : {};
1330
+ const settings = plugin2?.settings ? JSON.parse(plugin2.settings) : {};
1331
1331
  const contentHTML = await html.html`
1332
1332
  <div class="p-8">
1333
1333
  <!-- Header -->
@@ -1560,7 +1560,7 @@ function createEmailPlugin() {
1560
1560
  role: user.role ?? "admin"
1561
1561
  } : void 0;
1562
1562
  return c.html(
1563
- chunkBZC4FYW7_cjs.renderAdminLayout({
1563
+ chunkEHSZ6TAN_cjs.renderAdminLayout({
1564
1564
  title: "Email Settings",
1565
1565
  content: contentHTML,
1566
1566
  user: templateUser,
@@ -1588,16 +1588,16 @@ function createEmailPlugin() {
1588
1588
  try {
1589
1589
  const db = c.env.DB;
1590
1590
  const body = await c.req.json();
1591
- const plugin = await db.prepare(`
1591
+ const plugin2 = await db.prepare(`
1592
1592
  SELECT settings FROM plugins WHERE id = 'email'
1593
1593
  `).first();
1594
- if (!plugin?.settings) {
1594
+ if (!plugin2?.settings) {
1595
1595
  return c.json({
1596
1596
  success: false,
1597
1597
  error: "Email settings not configured. Please save your settings first."
1598
1598
  }, 400);
1599
1599
  }
1600
- const settings = JSON.parse(plugin.settings);
1600
+ const settings = JSON.parse(plugin2.settings);
1601
1601
  if (!settings.apiKey || !settings.fromEmail || !settings.fromName) {
1602
1602
  return c.json({
1603
1603
  success: false,
@@ -2148,7 +2148,7 @@ function createOTPLoginPlugin() {
2148
2148
  error: "Account is deactivated"
2149
2149
  }, 403);
2150
2150
  }
2151
- const token = await chunkT3YIKW2A_cjs.AuthManager.generateToken(user.id, user.email, user.role);
2151
+ const token = await chunkE2BXLXPW_cjs.AuthManager.generateToken(user.id, user.email, user.role);
2152
2152
  cookie.setCookie(c, "auth_token", token, {
2153
2153
  httpOnly: true,
2154
2154
  secure: true,
@@ -2376,7 +2376,7 @@ function createOTPLoginPlugin() {
2376
2376
  role: user.role ?? "admin"
2377
2377
  } : void 0;
2378
2378
  return c.html(
2379
- chunkBZC4FYW7_cjs.adminLayoutV2({
2379
+ chunkEHSZ6TAN_cjs.adminLayoutV2({
2380
2380
  title: "OTP Login Settings",
2381
2381
  content: contentHTML,
2382
2382
  user: templateUser,
@@ -2911,11 +2911,11 @@ var AISearchService = class {
2911
2911
  */
2912
2912
  async getSettings() {
2913
2913
  try {
2914
- const plugin = await this.db.prepare(`SELECT settings FROM plugins WHERE id = ? LIMIT 1`).bind("ai-search").first();
2915
- if (!plugin || !plugin.settings) {
2914
+ const plugin2 = await this.db.prepare(`SELECT settings FROM plugins WHERE id = ? LIMIT 1`).bind("ai-search").first();
2915
+ if (!plugin2 || !plugin2.settings) {
2916
2916
  return this.getDefaultSettings();
2917
2917
  }
2918
- return JSON.parse(plugin.settings);
2918
+ return JSON.parse(plugin2.settings);
2919
2919
  } catch (error) {
2920
2920
  console.error("Error fetching AI Search settings:", error);
2921
2921
  return this.getDefaultSettings();
@@ -3973,7 +3973,7 @@ function renderSettingsPage(data) {
3973
3973
  }, 30000);
3974
3974
  </script>
3975
3975
  `;
3976
- return chunkBZC4FYW7_cjs.renderAdminLayout({
3976
+ return chunkEHSZ6TAN_cjs.renderAdminLayout({
3977
3977
  title: "AI Search Settings",
3978
3978
  pageTitle: "AI Search Settings",
3979
3979
  currentPath: "/admin/plugins/ai-search/settings",
@@ -3984,7 +3984,7 @@ function renderSettingsPage(data) {
3984
3984
 
3985
3985
  // src/plugins/core-plugins/ai-search-plugin/routes/admin.ts
3986
3986
  var adminRoutes = new hono.Hono();
3987
- adminRoutes.use("*", chunkT3YIKW2A_cjs.requireAuth());
3987
+ adminRoutes.use("*", chunkE2BXLXPW_cjs.requireAuth());
3988
3988
  adminRoutes.get("/", async (c) => {
3989
3989
  try {
3990
3990
  const user = c.get("user");
@@ -4385,12 +4385,12 @@ function createMagicLinkAuthPlugin() {
4385
4385
  SET used = 1, used_at = ?
4386
4386
  WHERE id = ?
4387
4387
  `).bind(Date.now(), magicLink.id).run();
4388
- const jwtToken = await chunkT3YIKW2A_cjs.AuthManager.generateToken(
4388
+ const jwtToken = await chunkE2BXLXPW_cjs.AuthManager.generateToken(
4389
4389
  user.id,
4390
4390
  user.email,
4391
4391
  user.role
4392
4392
  );
4393
- chunkT3YIKW2A_cjs.AuthManager.setAuthCookie(c, jwtToken);
4393
+ chunkE2BXLXPW_cjs.AuthManager.setAuthCookie(c, jwtToken);
4394
4394
  await db.prepare(`
4395
4395
  UPDATE users SET last_login_at = ? WHERE id = ?
4396
4396
  `).bind(Date.now(), user.id).run();
@@ -4535,6 +4535,1823 @@ function renderMagicLinkEmail(magicLink, expiryMinutes) {
4535
4535
  }
4536
4536
  createMagicLinkAuthPlugin();
4537
4537
 
4538
+ // src/plugins/cache/services/cache-config.ts
4539
+ var CACHE_CONFIGS = {
4540
+ // Content (high read, low write)
4541
+ content: {
4542
+ ttl: 3600,
4543
+ // 1 hour
4544
+ kvEnabled: true,
4545
+ memoryEnabled: true,
4546
+ namespace: "content",
4547
+ invalidateOn: ["content.update", "content.delete", "content.publish"],
4548
+ version: "v1"
4549
+ },
4550
+ // User data (medium read, medium write)
4551
+ user: {
4552
+ ttl: 900,
4553
+ // 15 minutes
4554
+ kvEnabled: true,
4555
+ memoryEnabled: true,
4556
+ namespace: "user",
4557
+ invalidateOn: ["user.update", "user.delete", "auth.login"],
4558
+ version: "v1"
4559
+ },
4560
+ // Configuration (high read, very low write)
4561
+ config: {
4562
+ ttl: 7200,
4563
+ // 2 hours
4564
+ kvEnabled: true,
4565
+ memoryEnabled: true,
4566
+ namespace: "config",
4567
+ invalidateOn: ["config.update", "plugin.activate", "plugin.deactivate"],
4568
+ version: "v1"
4569
+ },
4570
+ // Media metadata (high read, low write)
4571
+ media: {
4572
+ ttl: 3600,
4573
+ // 1 hour
4574
+ kvEnabled: true,
4575
+ memoryEnabled: true,
4576
+ namespace: "media",
4577
+ invalidateOn: ["media.upload", "media.delete", "media.update"],
4578
+ version: "v1"
4579
+ },
4580
+ // API responses (very high read, low write)
4581
+ api: {
4582
+ ttl: 300,
4583
+ // 5 minutes
4584
+ kvEnabled: true,
4585
+ memoryEnabled: true,
4586
+ namespace: "api",
4587
+ invalidateOn: ["content.update", "content.publish"],
4588
+ version: "v1"
4589
+ },
4590
+ // Session data (very high read, medium write)
4591
+ session: {
4592
+ ttl: 1800,
4593
+ // 30 minutes
4594
+ kvEnabled: false,
4595
+ // Only in-memory for sessions
4596
+ memoryEnabled: true,
4597
+ namespace: "session",
4598
+ invalidateOn: ["auth.logout"],
4599
+ version: "v1"
4600
+ },
4601
+ // Plugin data
4602
+ plugin: {
4603
+ ttl: 3600,
4604
+ // 1 hour
4605
+ kvEnabled: true,
4606
+ memoryEnabled: true,
4607
+ namespace: "plugin",
4608
+ invalidateOn: ["plugin.activate", "plugin.deactivate", "plugin.update"],
4609
+ version: "v1"
4610
+ },
4611
+ // Collections/schema
4612
+ collection: {
4613
+ ttl: 7200,
4614
+ // 2 hours
4615
+ kvEnabled: true,
4616
+ memoryEnabled: true,
4617
+ namespace: "collection",
4618
+ invalidateOn: ["collection.update", "collection.delete"],
4619
+ version: "v1"
4620
+ }
4621
+ };
4622
+ function getCacheConfig(namespace) {
4623
+ return CACHE_CONFIGS[namespace] || {
4624
+ ttl: 3600,
4625
+ kvEnabled: true,
4626
+ memoryEnabled: true,
4627
+ namespace,
4628
+ invalidateOn: [],
4629
+ version: "v1"
4630
+ };
4631
+ }
4632
+ function generateCacheKey(namespace, type, identifier, version) {
4633
+ const v = version || getCacheConfig(namespace).version || "v1";
4634
+ return `${namespace}:${type}:${identifier}:${v}`;
4635
+ }
4636
+ function parseCacheKey(key) {
4637
+ const parts = key.split(":");
4638
+ if (parts.length !== 4) {
4639
+ return null;
4640
+ }
4641
+ return {
4642
+ namespace: parts[0] || "",
4643
+ type: parts[1] || "",
4644
+ identifier: parts[2] || "",
4645
+ version: parts[3] || ""
4646
+ };
4647
+ }
4648
+
4649
+ // src/plugins/cache/services/cache.ts
4650
+ var MemoryCache = class {
4651
+ cache = /* @__PURE__ */ new Map();
4652
+ maxSize = 50 * 1024 * 1024;
4653
+ // 50MB
4654
+ currentSize = 0;
4655
+ /**
4656
+ * Get item from memory cache
4657
+ */
4658
+ get(key) {
4659
+ const entry = this.cache.get(key);
4660
+ if (!entry) {
4661
+ return null;
4662
+ }
4663
+ if (Date.now() > entry.expiresAt) {
4664
+ this.delete(key);
4665
+ return null;
4666
+ }
4667
+ return entry.data;
4668
+ }
4669
+ /**
4670
+ * Set item in memory cache
4671
+ */
4672
+ set(key, value, ttl, version = "v1") {
4673
+ const now = Date.now();
4674
+ const entry = {
4675
+ data: value,
4676
+ timestamp: now,
4677
+ expiresAt: now + ttl * 1e3,
4678
+ version
4679
+ };
4680
+ const entrySize = JSON.stringify(entry).length * 2;
4681
+ if (this.currentSize + entrySize > this.maxSize) {
4682
+ this.evictLRU(entrySize);
4683
+ }
4684
+ if (this.cache.has(key)) {
4685
+ this.delete(key);
4686
+ }
4687
+ this.cache.set(key, entry);
4688
+ this.currentSize += entrySize;
4689
+ }
4690
+ /**
4691
+ * Delete item from memory cache
4692
+ */
4693
+ delete(key) {
4694
+ const entry = this.cache.get(key);
4695
+ if (entry) {
4696
+ const entrySize = JSON.stringify(entry).length * 2;
4697
+ this.currentSize -= entrySize;
4698
+ return this.cache.delete(key);
4699
+ }
4700
+ return false;
4701
+ }
4702
+ /**
4703
+ * Clear all items from memory cache
4704
+ */
4705
+ clear() {
4706
+ this.cache.clear();
4707
+ this.currentSize = 0;
4708
+ }
4709
+ /**
4710
+ * Get cache statistics
4711
+ */
4712
+ getStats() {
4713
+ return {
4714
+ size: this.currentSize,
4715
+ count: this.cache.size
4716
+ };
4717
+ }
4718
+ /**
4719
+ * Evict least recently used items to make space
4720
+ */
4721
+ evictLRU(neededSpace) {
4722
+ const entries = Array.from(this.cache.entries()).sort(
4723
+ (a, b) => a[1].timestamp - b[1].timestamp
4724
+ );
4725
+ let freedSpace = 0;
4726
+ for (const [key, entry] of entries) {
4727
+ if (freedSpace >= neededSpace) break;
4728
+ const entrySize = JSON.stringify(entry).length * 2;
4729
+ this.delete(key);
4730
+ freedSpace += entrySize;
4731
+ }
4732
+ }
4733
+ /**
4734
+ * Delete items matching a pattern
4735
+ */
4736
+ invalidatePattern(pattern) {
4737
+ const regex = new RegExp(
4738
+ "^" + pattern.replace(/\*/g, ".*").replace(/\?/g, ".") + "$"
4739
+ );
4740
+ let count = 0;
4741
+ for (const key of this.cache.keys()) {
4742
+ if (regex.test(key)) {
4743
+ this.delete(key);
4744
+ count++;
4745
+ }
4746
+ }
4747
+ return count;
4748
+ }
4749
+ };
4750
+ var CacheService = class {
4751
+ memoryCache;
4752
+ config;
4753
+ stats;
4754
+ kvNamespace;
4755
+ constructor(config, kvNamespace) {
4756
+ this.memoryCache = new MemoryCache();
4757
+ this.config = config;
4758
+ this.kvNamespace = kvNamespace;
4759
+ this.stats = {
4760
+ memoryHits: 0,
4761
+ memoryMisses: 0,
4762
+ kvHits: 0,
4763
+ kvMisses: 0,
4764
+ dbHits: 0,
4765
+ totalRequests: 0,
4766
+ hitRate: 0,
4767
+ memorySize: 0,
4768
+ entryCount: 0
4769
+ };
4770
+ }
4771
+ /**
4772
+ * Get value from cache (tries memory first, then KV)
4773
+ */
4774
+ async get(key) {
4775
+ this.stats.totalRequests++;
4776
+ if (this.config.memoryEnabled) {
4777
+ const memoryValue = this.memoryCache.get(key);
4778
+ if (memoryValue !== null) {
4779
+ this.stats.memoryHits++;
4780
+ this.updateHitRate();
4781
+ return memoryValue;
4782
+ }
4783
+ this.stats.memoryMisses++;
4784
+ }
4785
+ if (this.config.kvEnabled && this.kvNamespace) {
4786
+ try {
4787
+ const kvValue = await this.kvNamespace.get(key, "json");
4788
+ if (kvValue !== null) {
4789
+ this.stats.kvHits++;
4790
+ if (this.config.memoryEnabled) {
4791
+ this.memoryCache.set(key, kvValue, this.config.ttl, this.config.version);
4792
+ }
4793
+ this.updateHitRate();
4794
+ return kvValue;
4795
+ }
4796
+ this.stats.kvMisses++;
4797
+ } catch (error) {
4798
+ console.error("KV cache read error:", error);
4799
+ this.stats.kvMisses++;
4800
+ }
4801
+ }
4802
+ this.updateHitRate();
4803
+ return null;
4804
+ }
4805
+ /**
4806
+ * Get value from cache with source information
4807
+ */
4808
+ async getWithSource(key) {
4809
+ this.stats.totalRequests++;
4810
+ if (this.config.memoryEnabled) {
4811
+ const memoryValue = this.memoryCache.get(key);
4812
+ if (memoryValue !== null) {
4813
+ this.stats.memoryHits++;
4814
+ this.updateHitRate();
4815
+ const entry = await this.getEntry(key);
4816
+ return {
4817
+ data: memoryValue,
4818
+ source: "memory",
4819
+ hit: true,
4820
+ timestamp: entry?.timestamp,
4821
+ ttl: entry?.ttl
4822
+ };
4823
+ }
4824
+ this.stats.memoryMisses++;
4825
+ }
4826
+ if (this.config.kvEnabled && this.kvNamespace) {
4827
+ try {
4828
+ const kvValue = await this.kvNamespace.get(key, "json");
4829
+ if (kvValue !== null) {
4830
+ this.stats.kvHits++;
4831
+ if (this.config.memoryEnabled) {
4832
+ this.memoryCache.set(key, kvValue, this.config.ttl, this.config.version);
4833
+ }
4834
+ this.updateHitRate();
4835
+ return {
4836
+ data: kvValue,
4837
+ source: "kv",
4838
+ hit: true
4839
+ };
4840
+ }
4841
+ this.stats.kvMisses++;
4842
+ } catch (error) {
4843
+ console.error("KV cache read error:", error);
4844
+ this.stats.kvMisses++;
4845
+ }
4846
+ }
4847
+ this.updateHitRate();
4848
+ return {
4849
+ data: null,
4850
+ source: "miss",
4851
+ hit: false
4852
+ };
4853
+ }
4854
+ /**
4855
+ * Set value in cache (stores in both memory and KV)
4856
+ */
4857
+ async set(key, value, customConfig) {
4858
+ const config = { ...this.config, ...customConfig };
4859
+ if (config.memoryEnabled) {
4860
+ this.memoryCache.set(key, value, config.ttl, config.version);
4861
+ }
4862
+ if (config.kvEnabled && this.kvNamespace) {
4863
+ try {
4864
+ await this.kvNamespace.put(key, JSON.stringify(value), {
4865
+ expirationTtl: config.ttl
4866
+ });
4867
+ } catch (error) {
4868
+ console.error("KV cache write error:", error);
4869
+ }
4870
+ }
4871
+ }
4872
+ /**
4873
+ * Delete value from cache (removes from both memory and KV)
4874
+ */
4875
+ async delete(key) {
4876
+ if (this.config.memoryEnabled) {
4877
+ this.memoryCache.delete(key);
4878
+ }
4879
+ if (this.config.kvEnabled && this.kvNamespace) {
4880
+ try {
4881
+ await this.kvNamespace.delete(key);
4882
+ } catch (error) {
4883
+ console.error("KV cache delete error:", error);
4884
+ }
4885
+ }
4886
+ }
4887
+ /**
4888
+ * Clear all cache entries for this namespace
4889
+ */
4890
+ async clear() {
4891
+ if (this.config.memoryEnabled) {
4892
+ this.memoryCache.clear();
4893
+ }
4894
+ this.stats = {
4895
+ memoryHits: 0,
4896
+ memoryMisses: 0,
4897
+ kvHits: 0,
4898
+ kvMisses: 0,
4899
+ dbHits: 0,
4900
+ totalRequests: 0,
4901
+ hitRate: 0,
4902
+ memorySize: 0,
4903
+ entryCount: 0
4904
+ };
4905
+ }
4906
+ /**
4907
+ * Invalidate cache entries matching a pattern
4908
+ */
4909
+ async invalidate(pattern) {
4910
+ let count = 0;
4911
+ if (this.config.memoryEnabled) {
4912
+ count += this.memoryCache.invalidatePattern(pattern);
4913
+ }
4914
+ if (this.config.kvEnabled && this.kvNamespace) {
4915
+ try {
4916
+ const regex = new RegExp(
4917
+ "^" + pattern.replace(/\*/g, ".*").replace(/\?/g, ".") + "$"
4918
+ );
4919
+ const prefix = this.config.namespace + ":";
4920
+ const list = await this.kvNamespace.list({ prefix });
4921
+ for (const key of list.keys) {
4922
+ if (regex.test(key.name)) {
4923
+ await this.kvNamespace.delete(key.name);
4924
+ count++;
4925
+ }
4926
+ }
4927
+ } catch (error) {
4928
+ console.error("KV cache invalidation error:", error);
4929
+ }
4930
+ }
4931
+ return count;
4932
+ }
4933
+ /**
4934
+ * Invalidate cache entries matching a pattern (alias for invalidate)
4935
+ */
4936
+ async invalidatePattern(pattern) {
4937
+ return this.invalidate(pattern);
4938
+ }
4939
+ /**
4940
+ * Get cache statistics
4941
+ */
4942
+ getStats() {
4943
+ const memStats = this.memoryCache.getStats();
4944
+ return {
4945
+ ...this.stats,
4946
+ memorySize: memStats.size,
4947
+ entryCount: memStats.count
4948
+ };
4949
+ }
4950
+ /**
4951
+ * Update hit rate calculation
4952
+ */
4953
+ updateHitRate() {
4954
+ const totalHits = this.stats.memoryHits + this.stats.kvHits + this.stats.dbHits;
4955
+ this.stats.hitRate = this.stats.totalRequests > 0 ? totalHits / this.stats.totalRequests * 100 : 0;
4956
+ }
4957
+ /**
4958
+ * Generate a cache key using the configured namespace
4959
+ */
4960
+ generateKey(type, identifier) {
4961
+ return generateCacheKey(
4962
+ this.config.namespace,
4963
+ type,
4964
+ identifier,
4965
+ this.config.version
4966
+ );
4967
+ }
4968
+ /**
4969
+ * Warm cache with multiple entries
4970
+ */
4971
+ async warmCache(entries) {
4972
+ for (const entry of entries) {
4973
+ await this.set(entry.key, entry.value);
4974
+ }
4975
+ }
4976
+ /**
4977
+ * Check if a key exists in cache
4978
+ */
4979
+ async has(key) {
4980
+ const value = await this.get(key);
4981
+ return value !== null;
4982
+ }
4983
+ /**
4984
+ * Get multiple values at once
4985
+ */
4986
+ async getMany(keys) {
4987
+ const results = /* @__PURE__ */ new Map();
4988
+ for (const key of keys) {
4989
+ const value = await this.get(key);
4990
+ if (value !== null) {
4991
+ results.set(key, value);
4992
+ }
4993
+ }
4994
+ return results;
4995
+ }
4996
+ /**
4997
+ * Set multiple values at once
4998
+ */
4999
+ async setMany(entries, customConfig) {
5000
+ for (const entry of entries) {
5001
+ await this.set(entry.key, entry.value, customConfig);
5002
+ }
5003
+ }
5004
+ /**
5005
+ * Delete multiple keys at once
5006
+ */
5007
+ async deleteMany(keys) {
5008
+ for (const key of keys) {
5009
+ await this.delete(key);
5010
+ }
5011
+ }
5012
+ /**
5013
+ * Get or set pattern - fetch from cache or compute if not found
5014
+ */
5015
+ async getOrSet(key, fetcher, customConfig) {
5016
+ const cached = await this.get(key);
5017
+ if (cached !== null) {
5018
+ return cached;
5019
+ }
5020
+ const value = await fetcher();
5021
+ await this.set(key, value, customConfig);
5022
+ return value;
5023
+ }
5024
+ /**
5025
+ * List all cache keys with metadata
5026
+ */
5027
+ async listKeys() {
5028
+ const keys = [];
5029
+ if (this.config.memoryEnabled) {
5030
+ const cache = this.memoryCache.cache;
5031
+ for (const [key, entry] of cache.entries()) {
5032
+ const size = JSON.stringify(entry).length * 2;
5033
+ const age = Date.now() - entry.timestamp;
5034
+ keys.push({
5035
+ key,
5036
+ size,
5037
+ expiresAt: entry.expiresAt,
5038
+ age
5039
+ });
5040
+ }
5041
+ }
5042
+ return keys.sort((a, b) => a.age - b.age);
5043
+ }
5044
+ /**
5045
+ * Get cache entry with full metadata
5046
+ */
5047
+ async getEntry(key) {
5048
+ if (!this.config.memoryEnabled) {
5049
+ return null;
5050
+ }
5051
+ const cache = this.memoryCache.cache;
5052
+ const entry = cache.get(key);
5053
+ if (!entry) {
5054
+ return null;
5055
+ }
5056
+ if (Date.now() > entry.expiresAt) {
5057
+ await this.delete(key);
5058
+ return null;
5059
+ }
5060
+ const size = JSON.stringify(entry).length * 2;
5061
+ const ttl = Math.max(0, entry.expiresAt - Date.now()) / 1e3;
5062
+ return {
5063
+ data: entry.data,
5064
+ timestamp: entry.timestamp,
5065
+ expiresAt: entry.expiresAt,
5066
+ ttl,
5067
+ size
5068
+ };
5069
+ }
5070
+ };
5071
+ var cacheInstances = /* @__PURE__ */ new Map();
5072
+ var globalKVNamespace;
5073
+ function getCacheService(config, kvNamespace) {
5074
+ const key = config.namespace;
5075
+ if (!cacheInstances.has(key)) {
5076
+ const kv = globalKVNamespace;
5077
+ cacheInstances.set(key, new CacheService(config, kv));
5078
+ }
5079
+ return cacheInstances.get(key);
5080
+ }
5081
+ async function clearAllCaches() {
5082
+ for (const cache of cacheInstances.values()) {
5083
+ await cache.clear();
5084
+ }
5085
+ }
5086
+ function getAllCacheStats() {
5087
+ const stats = {};
5088
+ for (const [namespace, cache] of cacheInstances.entries()) {
5089
+ stats[namespace] = cache.getStats();
5090
+ }
5091
+ return stats;
5092
+ }
5093
+
5094
+ // src/plugins/cache/services/event-bus.ts
5095
+ var EventBus = class {
5096
+ subscriptions = /* @__PURE__ */ new Map();
5097
+ eventLog = [];
5098
+ maxLogSize = 100;
5099
+ /**
5100
+ * Subscribe to an event
5101
+ */
5102
+ on(event, handler) {
5103
+ if (!this.subscriptions.has(event)) {
5104
+ this.subscriptions.set(event, []);
5105
+ }
5106
+ this.subscriptions.get(event).push(handler);
5107
+ return () => {
5108
+ const handlers = this.subscriptions.get(event);
5109
+ if (handlers) {
5110
+ const index = handlers.indexOf(handler);
5111
+ if (index > -1) {
5112
+ handlers.splice(index, 1);
5113
+ }
5114
+ }
5115
+ };
5116
+ }
5117
+ /**
5118
+ * Emit an event to all subscribers
5119
+ */
5120
+ async emit(event, data) {
5121
+ this.logEvent(event, data);
5122
+ const handlers = this.subscriptions.get(event) || [];
5123
+ await Promise.all(
5124
+ handlers.map(async (handler) => {
5125
+ try {
5126
+ await handler(data);
5127
+ } catch (error) {
5128
+ console.error(`Error in event handler for ${event}:`, error);
5129
+ }
5130
+ })
5131
+ );
5132
+ const wildcardHandlers = this.subscriptions.get("*") || [];
5133
+ await Promise.all(
5134
+ wildcardHandlers.map(async (handler) => {
5135
+ try {
5136
+ await handler({ event, data });
5137
+ } catch (error) {
5138
+ console.error(`Error in wildcard event handler for ${event}:`, error);
5139
+ }
5140
+ })
5141
+ );
5142
+ }
5143
+ /**
5144
+ * Remove all subscribers for an event
5145
+ */
5146
+ off(event) {
5147
+ this.subscriptions.delete(event);
5148
+ }
5149
+ /**
5150
+ * Get all registered events
5151
+ */
5152
+ getEvents() {
5153
+ return Array.from(this.subscriptions.keys());
5154
+ }
5155
+ /**
5156
+ * Get subscriber count for an event
5157
+ */
5158
+ getSubscriberCount(event) {
5159
+ return this.subscriptions.get(event)?.length || 0;
5160
+ }
5161
+ /**
5162
+ * Log an event for debugging
5163
+ */
5164
+ logEvent(event, data) {
5165
+ this.eventLog.push({
5166
+ event,
5167
+ timestamp: Date.now(),
5168
+ data
5169
+ });
5170
+ if (this.eventLog.length > this.maxLogSize) {
5171
+ this.eventLog.shift();
5172
+ }
5173
+ }
5174
+ /**
5175
+ * Get recent event log
5176
+ */
5177
+ getEventLog(limit = 50) {
5178
+ return this.eventLog.slice(-limit);
5179
+ }
5180
+ /**
5181
+ * Clear event log
5182
+ */
5183
+ clearEventLog() {
5184
+ this.eventLog = [];
5185
+ }
5186
+ /**
5187
+ * Get statistics
5188
+ */
5189
+ getStats() {
5190
+ const eventCounts = {};
5191
+ for (const log of this.eventLog) {
5192
+ eventCounts[log.event] = (eventCounts[log.event] || 0) + 1;
5193
+ }
5194
+ return {
5195
+ totalEvents: this.eventLog.length,
5196
+ totalSubscriptions: this.subscriptions.size,
5197
+ eventCounts
5198
+ };
5199
+ }
5200
+ };
5201
+ var globalEventBus = null;
5202
+ function getEventBus() {
5203
+ if (!globalEventBus) {
5204
+ globalEventBus = new EventBus();
5205
+ }
5206
+ return globalEventBus;
5207
+ }
5208
+ function onEvent(event, handler) {
5209
+ const bus = getEventBus();
5210
+ return bus.on(event, handler);
5211
+ }
5212
+
5213
+ // src/plugins/cache/services/cache-invalidation.ts
5214
+ function setupCacheInvalidation() {
5215
+ getEventBus();
5216
+ setupContentInvalidation();
5217
+ setupUserInvalidation();
5218
+ setupConfigInvalidation();
5219
+ setupMediaInvalidation();
5220
+ setupAPIInvalidation();
5221
+ setupCollectionInvalidation();
5222
+ console.log("Cache invalidation listeners registered");
5223
+ }
5224
+ function setupContentInvalidation() {
5225
+ const config = CACHE_CONFIGS.content;
5226
+ if (!config) return;
5227
+ const contentCache = getCacheService(config);
5228
+ onEvent("content.create", async (_data) => {
5229
+ await contentCache.invalidate("content:*");
5230
+ console.log("Cache invalidated: content.create");
5231
+ });
5232
+ onEvent("content.update", async (data) => {
5233
+ if (data?.id) {
5234
+ await contentCache.delete(contentCache.generateKey("item", data.id));
5235
+ }
5236
+ await contentCache.invalidate("content:list:*");
5237
+ console.log("Cache invalidated: content.update", data?.id);
5238
+ });
5239
+ onEvent("content.delete", async (data) => {
5240
+ if (data?.id) {
5241
+ await contentCache.delete(contentCache.generateKey("item", data.id));
5242
+ }
5243
+ await contentCache.invalidate("content:*");
5244
+ console.log("Cache invalidated: content.delete", data?.id);
5245
+ });
5246
+ onEvent("content.publish", async (_data) => {
5247
+ await contentCache.invalidate("content:*");
5248
+ console.log("Cache invalidated: content.publish");
5249
+ });
5250
+ }
5251
+ function setupUserInvalidation() {
5252
+ const config = CACHE_CONFIGS.user;
5253
+ if (!config) return;
5254
+ const userCache = getCacheService(config);
5255
+ onEvent("user.update", async (data) => {
5256
+ if (data?.id) {
5257
+ await userCache.delete(userCache.generateKey("id", data.id));
5258
+ }
5259
+ if (data?.email) {
5260
+ await userCache.delete(userCache.generateKey("email", data.email));
5261
+ }
5262
+ console.log("Cache invalidated: user.update", data?.id);
5263
+ });
5264
+ onEvent("user.delete", async (data) => {
5265
+ if (data?.id) {
5266
+ await userCache.delete(userCache.generateKey("id", data.id));
5267
+ }
5268
+ if (data?.email) {
5269
+ await userCache.delete(userCache.generateKey("email", data.email));
5270
+ }
5271
+ console.log("Cache invalidated: user.delete", data?.id);
5272
+ });
5273
+ onEvent("auth.login", async (data) => {
5274
+ if (data?.userId) {
5275
+ await userCache.delete(userCache.generateKey("id", data.userId));
5276
+ }
5277
+ console.log("Cache invalidated: auth.login", data?.userId);
5278
+ });
5279
+ onEvent("auth.logout", async (data) => {
5280
+ const sessionConfig = CACHE_CONFIGS.session;
5281
+ if (sessionConfig) {
5282
+ const sessionCache = getCacheService(sessionConfig);
5283
+ if (data?.sessionId) {
5284
+ await sessionCache.delete(sessionCache.generateKey("session", data.sessionId));
5285
+ }
5286
+ }
5287
+ console.log("Cache invalidated: auth.logout");
5288
+ });
5289
+ }
5290
+ function setupConfigInvalidation() {
5291
+ const configConfig = CACHE_CONFIGS.config;
5292
+ if (!configConfig) return;
5293
+ const configCache = getCacheService(configConfig);
5294
+ onEvent("config.update", async (_data) => {
5295
+ await configCache.invalidate("config:*");
5296
+ console.log("Cache invalidated: config.update");
5297
+ });
5298
+ onEvent("plugin.activate", async (data) => {
5299
+ await configCache.invalidate("config:*");
5300
+ const pluginConfig = CACHE_CONFIGS.plugin;
5301
+ if (pluginConfig) {
5302
+ const pluginCache = getCacheService(pluginConfig);
5303
+ await pluginCache.invalidate("plugin:*");
5304
+ }
5305
+ console.log("Cache invalidated: plugin.activate", data?.pluginId);
5306
+ });
5307
+ onEvent("plugin.deactivate", async (data) => {
5308
+ await configCache.invalidate("config:*");
5309
+ const pluginConfig = CACHE_CONFIGS.plugin;
5310
+ if (pluginConfig) {
5311
+ const pluginCache = getCacheService(pluginConfig);
5312
+ await pluginCache.invalidate("plugin:*");
5313
+ }
5314
+ console.log("Cache invalidated: plugin.deactivate", data?.pluginId);
5315
+ });
5316
+ onEvent("plugin.update", async (data) => {
5317
+ const pluginConfig = CACHE_CONFIGS.plugin;
5318
+ if (!pluginConfig) return;
5319
+ const pluginCache = getCacheService(pluginConfig);
5320
+ await pluginCache.invalidate("plugin:*");
5321
+ console.log("Cache invalidated: plugin.update", data?.pluginId);
5322
+ });
5323
+ }
5324
+ function setupMediaInvalidation() {
5325
+ const config = CACHE_CONFIGS.media;
5326
+ if (!config) return;
5327
+ const mediaCache = getCacheService(config);
5328
+ onEvent("media.upload", async (_data) => {
5329
+ await mediaCache.invalidate("media:*");
5330
+ console.log("Cache invalidated: media.upload");
5331
+ });
5332
+ onEvent("media.delete", async (data) => {
5333
+ if (data?.id) {
5334
+ await mediaCache.delete(mediaCache.generateKey("item", data.id));
5335
+ }
5336
+ await mediaCache.invalidate("media:list:*");
5337
+ console.log("Cache invalidated: media.delete", data?.id);
5338
+ });
5339
+ onEvent("media.update", async (data) => {
5340
+ if (data?.id) {
5341
+ await mediaCache.delete(mediaCache.generateKey("item", data.id));
5342
+ }
5343
+ await mediaCache.invalidate("media:list:*");
5344
+ console.log("Cache invalidated: media.update", data?.id);
5345
+ });
5346
+ }
5347
+ function setupAPIInvalidation() {
5348
+ const config = CACHE_CONFIGS.api;
5349
+ if (!config) return;
5350
+ const apiCache = getCacheService(config);
5351
+ onEvent("content.update", async (_data) => {
5352
+ await apiCache.invalidate("api:*");
5353
+ console.log("Cache invalidated: api (content.update)");
5354
+ });
5355
+ onEvent("content.publish", async (_data) => {
5356
+ await apiCache.invalidate("api:*");
5357
+ console.log("Cache invalidated: api (content.publish)");
5358
+ });
5359
+ onEvent("content.create", async (_data) => {
5360
+ await apiCache.invalidate("api:*");
5361
+ console.log("Cache invalidated: api (content.create)");
5362
+ });
5363
+ onEvent("content.delete", async (_data) => {
5364
+ await apiCache.invalidate("api:*");
5365
+ console.log("Cache invalidated: api (content.delete)");
5366
+ });
5367
+ onEvent("collection.update", async (_data) => {
5368
+ await apiCache.invalidate("api:*");
5369
+ console.log("Cache invalidated: api (collection.update)");
5370
+ });
5371
+ }
5372
+ function setupCollectionInvalidation() {
5373
+ const config = CACHE_CONFIGS.collection;
5374
+ if (!config) return;
5375
+ const collectionCache = getCacheService(config);
5376
+ onEvent("collection.create", async (_data) => {
5377
+ await collectionCache.invalidate("collection:*");
5378
+ console.log("Cache invalidated: collection.create");
5379
+ });
5380
+ onEvent("collection.update", async (data) => {
5381
+ if (data?.id) {
5382
+ await collectionCache.delete(collectionCache.generateKey("item", data.id));
5383
+ }
5384
+ await collectionCache.invalidate("collection:*");
5385
+ console.log("Cache invalidated: collection.update", data?.id);
5386
+ });
5387
+ onEvent("collection.delete", async (data) => {
5388
+ await collectionCache.invalidate("collection:*");
5389
+ console.log("Cache invalidated: collection.delete", data?.id);
5390
+ });
5391
+ }
5392
+ function getCacheInvalidationStats() {
5393
+ const eventBus = getEventBus();
5394
+ return eventBus.getStats();
5395
+ }
5396
+ function getRecentInvalidations(limit = 50) {
5397
+ const eventBus = getEventBus();
5398
+ return eventBus.getEventLog(limit);
5399
+ }
5400
+
5401
+ // src/plugins/cache/services/cache-warming.ts
5402
+ async function warmCommonCaches(db) {
5403
+ let totalWarmed = 0;
5404
+ let totalErrors = 0;
5405
+ const details = [];
5406
+ try {
5407
+ const collectionCount = await warmCollections(db);
5408
+ totalWarmed += collectionCount;
5409
+ details.push({ namespace: "collection", count: collectionCount });
5410
+ const contentCount = await warmRecentContent(db);
5411
+ totalWarmed += contentCount;
5412
+ details.push({ namespace: "content", count: contentCount });
5413
+ const mediaCount = await warmRecentMedia(db);
5414
+ totalWarmed += mediaCount;
5415
+ details.push({ namespace: "media", count: mediaCount });
5416
+ } catch (error) {
5417
+ console.error("Error warming caches:", error);
5418
+ totalErrors++;
5419
+ }
5420
+ return {
5421
+ warmed: totalWarmed,
5422
+ errors: totalErrors,
5423
+ details
5424
+ };
5425
+ }
5426
+ async function warmCollections(db) {
5427
+ const config = CACHE_CONFIGS.collection;
5428
+ if (!config) return 0;
5429
+ const collectionCache = getCacheService(config);
5430
+ let count = 0;
5431
+ try {
5432
+ const stmt = db.prepare("SELECT * FROM collections WHERE is_active = 1");
5433
+ const { results } = await stmt.all();
5434
+ for (const collection of results) {
5435
+ const key = collectionCache.generateKey("item", collection.id);
5436
+ await collectionCache.set(key, collection);
5437
+ count++;
5438
+ }
5439
+ const listKey = collectionCache.generateKey("list", "all");
5440
+ await collectionCache.set(listKey, results);
5441
+ count++;
5442
+ } catch (error) {
5443
+ console.error("Error warming collections cache:", error);
5444
+ }
5445
+ return count;
5446
+ }
5447
+ async function warmRecentContent(db, limit = 50) {
5448
+ const config = CACHE_CONFIGS.content;
5449
+ if (!config) return 0;
5450
+ const contentCache = getCacheService(config);
5451
+ let count = 0;
5452
+ try {
5453
+ const stmt = db.prepare(`SELECT * FROM content ORDER BY created_at DESC LIMIT ${limit}`);
5454
+ const { results } = await stmt.all();
5455
+ for (const content2 of results) {
5456
+ const key = contentCache.generateKey("item", content2.id);
5457
+ await contentCache.set(key, content2);
5458
+ count++;
5459
+ }
5460
+ const listKey = contentCache.generateKey("list", "recent");
5461
+ await contentCache.set(listKey, results);
5462
+ count++;
5463
+ } catch (error) {
5464
+ console.error("Error warming content cache:", error);
5465
+ }
5466
+ return count;
5467
+ }
5468
+ async function warmRecentMedia(db, limit = 50) {
5469
+ const config = CACHE_CONFIGS.media;
5470
+ if (!config) return 0;
5471
+ const mediaCache = getCacheService(config);
5472
+ let count = 0;
5473
+ try {
5474
+ const stmt = db.prepare(`SELECT * FROM media WHERE deleted_at IS NULL ORDER BY uploaded_at DESC LIMIT ${limit}`);
5475
+ const { results } = await stmt.all();
5476
+ for (const media2 of results) {
5477
+ const key = mediaCache.generateKey("item", media2.id);
5478
+ await mediaCache.set(key, media2);
5479
+ count++;
5480
+ }
5481
+ const listKey = mediaCache.generateKey("list", "recent");
5482
+ await mediaCache.set(listKey, results);
5483
+ count++;
5484
+ } catch (error) {
5485
+ console.error("Error warming media cache:", error);
5486
+ }
5487
+ return count;
5488
+ }
5489
+ async function warmNamespace(namespace, entries) {
5490
+ const config = CACHE_CONFIGS[namespace];
5491
+ if (!config) {
5492
+ throw new Error(`Unknown namespace: ${namespace}`);
5493
+ }
5494
+ const cache = getCacheService(config);
5495
+ await cache.setMany(entries);
5496
+ return entries.length;
5497
+ }
5498
+
5499
+ // src/templates/pages/admin-cache.template.ts
5500
+ chunkEHSZ6TAN_cjs.init_admin_layout_catalyst_template();
5501
+ function renderCacheDashboard(data) {
5502
+ const pageContent = `
5503
+ <div class="space-y-6">
5504
+ <!-- Header -->
5505
+ <div class="flex items-center justify-between">
5506
+ <div>
5507
+ <h1 class="text-2xl font-semibold text-zinc-950 dark:text-white">Cache System</h1>
5508
+ <p class="mt-1 text-sm text-zinc-600 dark:text-zinc-400">
5509
+ Monitor and manage cache performance across all namespaces
5510
+ </p>
5511
+ </div>
5512
+ <div class="flex gap-3">
5513
+ <button
5514
+ onclick="refreshStats()"
5515
+ class="inline-flex items-center gap-2 rounded-lg bg-white dark:bg-zinc-900 px-4 py-2 text-sm font-medium text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-800"
5516
+ >
5517
+ <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5518
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/>
5519
+ </svg>
5520
+ Refresh
5521
+ </button>
5522
+ <button
5523
+ onclick="clearAllCaches()"
5524
+ class="inline-flex items-center gap-2 rounded-lg bg-red-600 dark:bg-red-500 px-4 py-2 text-sm font-medium text-white hover:bg-red-700 dark:hover:bg-red-600"
5525
+ >
5526
+ <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5527
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
5528
+ </svg>
5529
+ Clear All
5530
+ </button>
5531
+ </div>
5532
+ </div>
5533
+
5534
+ <!-- Overall Stats Cards -->
5535
+ <div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
5536
+ ${renderStatCard("Total Requests", data.totals.requests.toLocaleString(), "lime", `
5537
+ <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5538
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"/>
5539
+ </svg>
5540
+ `)}
5541
+
5542
+ ${renderStatCard("Hit Rate", data.totals.hitRate + "%", "blue", `
5543
+ <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5544
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
5545
+ </svg>
5546
+ `, parseFloat(data.totals.hitRate) > 70 ? "lime" : parseFloat(data.totals.hitRate) > 40 ? "amber" : "red")}
5547
+
5548
+ ${renderStatCard("Memory Usage", formatBytes(data.totals.memorySize), "purple", `
5549
+ <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5550
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z"/>
5551
+ </svg>
5552
+ `)}
5553
+
5554
+ ${renderStatCard("Cached Entries", data.totals.entryCount.toLocaleString(), "sky", `
5555
+ <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5556
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01"/>
5557
+ </svg>
5558
+ `)}
5559
+ </div>
5560
+
5561
+ <!-- Namespace Statistics -->
5562
+ <div class="overflow-hidden rounded-xl bg-white dark:bg-zinc-900 ring-1 ring-zinc-950/5 dark:ring-white/10">
5563
+ <div class="px-6 py-4 border-b border-zinc-950/5 dark:border-white/10">
5564
+ <h2 class="text-lg font-semibold text-zinc-950 dark:text-white">Cache Namespaces</h2>
5565
+ </div>
5566
+ <div class="overflow-x-auto">
5567
+ <table class="min-w-full divide-y divide-zinc-950/5 dark:divide-white/10">
5568
+ <thead class="bg-zinc-50 dark:bg-zinc-800/50">
5569
+ <tr>
5570
+ <th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
5571
+ Namespace
5572
+ </th>
5573
+ <th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
5574
+ Requests
5575
+ </th>
5576
+ <th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
5577
+ Hit Rate
5578
+ </th>
5579
+ <th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
5580
+ Memory Hits
5581
+ </th>
5582
+ <th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
5583
+ KV Hits
5584
+ </th>
5585
+ <th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
5586
+ Entries
5587
+ </th>
5588
+ <th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
5589
+ Size
5590
+ </th>
5591
+ <th class="px-6 py-3 text-right text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
5592
+ Actions
5593
+ </th>
5594
+ </tr>
5595
+ </thead>
5596
+ <tbody class="divide-y divide-zinc-950/5 dark:divide-white/10">
5597
+ ${data.namespaces.map((namespace) => {
5598
+ const stat = data.stats[namespace];
5599
+ if (!stat) return "";
5600
+ return renderNamespaceRow(namespace, stat);
5601
+ }).join("")}
5602
+ </tbody>
5603
+ </table>
5604
+ </div>
5605
+ </div>
5606
+
5607
+ <!-- Performance Chart Placeholder -->
5608
+ <div class="overflow-hidden rounded-xl bg-white dark:bg-zinc-900 ring-1 ring-zinc-950/5 dark:ring-white/10">
5609
+ <div class="px-6 py-4 border-b border-zinc-950/5 dark:border-white/10">
5610
+ <h2 class="text-lg font-semibold text-zinc-950 dark:text-white">Performance Overview</h2>
5611
+ </div>
5612
+ <div class="p-6">
5613
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
5614
+ ${renderPerformanceMetric("Memory Cache", data.totals.hits, data.totals.misses)}
5615
+ ${renderHealthStatus(parseFloat(data.totals.hitRate))}
5616
+ </div>
5617
+ </div>
5618
+ </div>
5619
+ </div>
5620
+
5621
+ <script>
5622
+ async function refreshStats() {
5623
+ window.location.reload()
5624
+ }
5625
+
5626
+ async function clearAllCaches() {
5627
+ showConfirmDialog('clear-all-cache-confirm')
5628
+ }
5629
+
5630
+ async function performClearAllCaches() {
5631
+ try {
5632
+ const response = await fetch('/admin/cache/clear', {
5633
+ method: 'POST'
5634
+ })
5635
+
5636
+ const result = await response.json()
5637
+ if (result.success) {
5638
+ alert('All caches cleared successfully')
5639
+ window.location.reload()
5640
+ } else {
5641
+ alert('Error clearing caches: ' + result.error)
5642
+ }
5643
+ } catch (error) {
5644
+ alert('Error clearing caches: ' + error.message)
5645
+ }
5646
+ }
5647
+
5648
+ let namespaceToDelete = null
5649
+
5650
+ async function clearNamespaceCache(namespace) {
5651
+ namespaceToDelete = namespace
5652
+ showConfirmDialog('clear-namespace-cache-confirm')
5653
+ }
5654
+
5655
+ async function performClearNamespaceCache() {
5656
+ if (!namespaceToDelete) return
5657
+
5658
+ try {
5659
+ const response = await fetch(\`/admin/cache/clear/\${namespaceToDelete}\`, {
5660
+ method: 'POST'
5661
+ })
5662
+
5663
+ const result = await response.json()
5664
+ if (result.success) {
5665
+ alert('Cache cleared successfully')
5666
+ window.location.reload()
5667
+ } else {
5668
+ alert('Error clearing cache: ' + result.error)
5669
+ }
5670
+ } catch (error) {
5671
+ alert('Error clearing cache: ' + error.message)
5672
+ } finally {
5673
+ namespaceToDelete = null
5674
+ }
5675
+ }
5676
+ </script>
5677
+
5678
+ <!-- Confirmation Dialogs -->
5679
+ ${chunkJ7F3NPAP_cjs.renderConfirmationDialog({
5680
+ id: "clear-all-cache-confirm",
5681
+ title: "Clear All Cache",
5682
+ message: "Are you sure you want to clear all cache entries? This cannot be undone.",
5683
+ confirmText: "Clear All",
5684
+ cancelText: "Cancel",
5685
+ iconColor: "yellow",
5686
+ confirmClass: "bg-yellow-500 hover:bg-yellow-400",
5687
+ onConfirm: "performClearAllCaches()"
5688
+ })}
5689
+
5690
+ ${chunkJ7F3NPAP_cjs.renderConfirmationDialog({
5691
+ id: "clear-namespace-cache-confirm",
5692
+ title: "Clear Namespace Cache",
5693
+ message: "Clear cache for this namespace?",
5694
+ confirmText: "Clear",
5695
+ cancelText: "Cancel",
5696
+ iconColor: "yellow",
5697
+ confirmClass: "bg-yellow-500 hover:bg-yellow-400",
5698
+ onConfirm: "performClearNamespaceCache()"
5699
+ })}
5700
+
5701
+ ${chunkJ7F3NPAP_cjs.getConfirmationDialogScript()}
5702
+ `;
5703
+ const layoutData = {
5704
+ title: "Cache System",
5705
+ pageTitle: "Cache System",
5706
+ currentPath: "/admin/cache",
5707
+ user: data.user,
5708
+ version: data.version,
5709
+ content: pageContent
5710
+ };
5711
+ return chunkEHSZ6TAN_cjs.renderAdminLayoutCatalyst(layoutData);
5712
+ }
5713
+ function renderStatCard(label, value, color, icon, colorOverride) {
5714
+ const finalColor = colorOverride || color;
5715
+ const colorClasses = {
5716
+ lime: "bg-lime-50 dark:bg-lime-500/10 text-lime-600 dark:text-lime-400 ring-lime-600/20 dark:ring-lime-500/20",
5717
+ blue: "bg-blue-50 dark:bg-blue-500/10 text-blue-600 dark:text-blue-400 ring-blue-600/20 dark:ring-blue-500/20",
5718
+ purple: "bg-purple-50 dark:bg-purple-500/10 text-purple-600 dark:text-purple-400 ring-purple-600/20 dark:ring-purple-500/20",
5719
+ sky: "bg-sky-50 dark:bg-sky-500/10 text-sky-600 dark:text-sky-400 ring-sky-600/20 dark:ring-sky-500/20",
5720
+ amber: "bg-amber-50 dark:bg-amber-500/10 text-amber-600 dark:text-amber-400 ring-amber-600/20 dark:ring-amber-500/20",
5721
+ red: "bg-red-50 dark:bg-red-500/10 text-red-600 dark:text-red-400 ring-red-600/20 dark:ring-red-500/20"
5722
+ };
5723
+ return `
5724
+ <div class="overflow-hidden rounded-xl bg-white dark:bg-zinc-900 ring-1 ring-zinc-950/5 dark:ring-white/10">
5725
+ <div class="p-6">
5726
+ <div class="flex items-center justify-between">
5727
+ <div class="flex items-center gap-3">
5728
+ <div class="rounded-lg p-2 ring-1 ring-inset ${colorClasses[finalColor]}">
5729
+ ${icon}
5730
+ </div>
5731
+ <div>
5732
+ <p class="text-sm text-zinc-600 dark:text-zinc-400">${label}</p>
5733
+ <p class="mt-1 text-2xl font-semibold text-zinc-950 dark:text-white">${value}</p>
5734
+ </div>
5735
+ </div>
5736
+ </div>
5737
+ </div>
5738
+ </div>
5739
+ `;
5740
+ }
5741
+ function renderNamespaceRow(namespace, stat) {
5742
+ const hitRate = stat.hitRate.toFixed(1);
5743
+ const hitRateColor = stat.hitRate > 70 ? "text-lime-600 dark:text-lime-400" : stat.hitRate > 40 ? "text-amber-600 dark:text-amber-400" : "text-red-600 dark:text-red-400";
5744
+ return `
5745
+ <tr class="hover:bg-zinc-50 dark:hover:bg-zinc-800/50">
5746
+ <td class="px-6 py-4 whitespace-nowrap">
5747
+ <span class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium bg-zinc-100 dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 ring-1 ring-inset ring-zinc-200 dark:ring-zinc-700">
5748
+ ${namespace}
5749
+ </span>
5750
+ </td>
5751
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-900 dark:text-zinc-100">
5752
+ ${stat.totalRequests.toLocaleString()}
5753
+ </td>
5754
+ <td class="px-6 py-4 whitespace-nowrap">
5755
+ <span class="text-sm font-medium ${hitRateColor}">
5756
+ ${hitRate}%
5757
+ </span>
5758
+ </td>
5759
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-600 dark:text-zinc-400">
5760
+ ${stat.memoryHits.toLocaleString()}
5761
+ </td>
5762
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-600 dark:text-zinc-400">
5763
+ ${stat.kvHits.toLocaleString()}
5764
+ </td>
5765
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-600 dark:text-zinc-400">
5766
+ ${stat.entryCount.toLocaleString()}
5767
+ </td>
5768
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-600 dark:text-zinc-400">
5769
+ ${formatBytes(stat.memorySize)}
5770
+ </td>
5771
+ <td class="px-6 py-4 whitespace-nowrap text-right text-sm">
5772
+ <button
5773
+ onclick="clearNamespaceCache('${namespace}')"
5774
+ class="text-red-600 dark:text-red-400 hover:text-red-700 dark:hover:text-red-300"
5775
+ >
5776
+ Clear
5777
+ </button>
5778
+ </td>
5779
+ </tr>
5780
+ `;
5781
+ }
5782
+ function renderPerformanceMetric(label, hits, misses) {
5783
+ const total = hits + misses;
5784
+ const hitPercentage = total > 0 ? hits / total * 100 : 0;
5785
+ return `
5786
+ <div>
5787
+ <h3 class="text-sm font-medium text-zinc-900 dark:text-zinc-100 mb-3">${label}</h3>
5788
+ <div class="space-y-2">
5789
+ <div class="flex items-center justify-between text-sm">
5790
+ <span class="text-zinc-600 dark:text-zinc-400">Hits</span>
5791
+ <span class="font-medium text-zinc-900 dark:text-zinc-100">${hits.toLocaleString()}</span>
5792
+ </div>
5793
+ <div class="flex items-center justify-between text-sm">
5794
+ <span class="text-zinc-600 dark:text-zinc-400">Misses</span>
5795
+ <span class="font-medium text-zinc-900 dark:text-zinc-100">${misses.toLocaleString()}</span>
5796
+ </div>
5797
+ <div class="mt-3">
5798
+ <div class="flex items-center justify-between text-sm mb-1">
5799
+ <span class="text-zinc-600 dark:text-zinc-400">Hit Rate</span>
5800
+ <span class="font-medium text-zinc-900 dark:text-zinc-100">${hitPercentage.toFixed(1)}%</span>
5801
+ </div>
5802
+ <div class="h-2 bg-zinc-200 dark:bg-zinc-700 rounded-full overflow-hidden">
5803
+ <div class="h-full bg-lime-500 dark:bg-lime-400" style="width: ${hitPercentage}%"></div>
5804
+ </div>
5805
+ </div>
5806
+ </div>
5807
+ </div>
5808
+ `;
5809
+ }
5810
+ function renderHealthStatus(hitRate) {
5811
+ const status = hitRate > 70 ? "healthy" : hitRate > 40 ? "warning" : "critical";
5812
+ const statusConfig = {
5813
+ healthy: {
5814
+ label: "Healthy",
5815
+ color: "lime",
5816
+ icon: `<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5817
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
5818
+ </svg>`
5819
+ },
5820
+ warning: {
5821
+ label: "Needs Attention",
5822
+ color: "amber",
5823
+ icon: `<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5824
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
5825
+ </svg>`
5826
+ },
5827
+ critical: {
5828
+ label: "Critical",
5829
+ color: "red",
5830
+ icon: `<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5831
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
5832
+ </svg>`
5833
+ }
5834
+ };
5835
+ const config = statusConfig[status];
5836
+ const colorClasses = {
5837
+ lime: "bg-lime-50 dark:bg-lime-500/10 text-lime-600 dark:text-lime-400 ring-lime-600/20 dark:ring-lime-500/20",
5838
+ amber: "bg-amber-50 dark:bg-amber-500/10 text-amber-600 dark:text-amber-400 ring-amber-600/20 dark:ring-amber-500/20",
5839
+ red: "bg-red-50 dark:bg-red-500/10 text-red-600 dark:text-red-400 ring-red-600/20 dark:ring-red-500/20"
5840
+ };
5841
+ return `
5842
+ <div>
5843
+ <h3 class="text-sm font-medium text-zinc-900 dark:text-zinc-100 mb-3">System Health</h3>
5844
+ <div class="flex items-center gap-3 p-4 rounded-lg ring-1 ring-inset ${colorClasses[config.color]}">
5845
+ ${config.icon}
5846
+ <div>
5847
+ <p class="text-sm font-medium">${config.label}</p>
5848
+ <p class="text-xs mt-0.5 opacity-80">
5849
+ ${status === "healthy" ? "Cache is performing well" : status === "warning" ? "Consider increasing cache TTL or capacity" : "Cache hit rate is too low"}
5850
+ </p>
5851
+ </div>
5852
+ </div>
5853
+ </div>
5854
+ `;
5855
+ }
5856
+ function formatBytes(bytes) {
5857
+ if (bytes === 0) return "0 B";
5858
+ const k = 1024;
5859
+ const sizes = ["B", "KB", "MB", "GB"];
5860
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
5861
+ return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`;
5862
+ }
5863
+
5864
+ // src/plugins/cache/routes.ts
5865
+ var app = new hono.Hono();
5866
+ app.get("/", async (c) => {
5867
+ const stats = getAllCacheStats();
5868
+ const user = c.get("user");
5869
+ let totalHits = 0;
5870
+ let totalMisses = 0;
5871
+ let totalSize = 0;
5872
+ let totalEntries = 0;
5873
+ Object.values(stats).forEach((stat) => {
5874
+ totalHits += stat.memoryHits + stat.kvHits;
5875
+ totalMisses += stat.memoryMisses + stat.kvMisses;
5876
+ totalSize += stat.memorySize;
5877
+ totalEntries += stat.entryCount;
5878
+ });
5879
+ const totalRequests = totalHits + totalMisses;
5880
+ const overallHitRate = totalRequests > 0 ? totalHits / totalRequests * 100 : 0;
5881
+ const dashboardData = {
5882
+ stats,
5883
+ totals: {
5884
+ hits: totalHits,
5885
+ misses: totalMisses,
5886
+ requests: totalRequests,
5887
+ hitRate: overallHitRate.toFixed(2),
5888
+ memorySize: totalSize,
5889
+ entryCount: totalEntries
5890
+ },
5891
+ namespaces: Object.keys(stats),
5892
+ user: user ? {
5893
+ name: user.email,
5894
+ email: user.email,
5895
+ role: user.role
5896
+ } : void 0,
5897
+ version: c.get("appVersion")
5898
+ };
5899
+ return c.html(renderCacheDashboard(dashboardData));
5900
+ });
5901
+ app.get("/stats", async (c) => {
5902
+ const stats = getAllCacheStats();
5903
+ return c.json({
5904
+ success: true,
5905
+ data: stats,
5906
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
5907
+ });
5908
+ });
5909
+ app.get("/stats/:namespace", async (c) => {
5910
+ const namespace = c.req.param("namespace");
5911
+ const config = CACHE_CONFIGS[namespace];
5912
+ if (!config) {
5913
+ return c.json({
5914
+ success: false,
5915
+ error: `Unknown namespace: ${namespace}`
5916
+ }, 404);
5917
+ }
5918
+ const cache = getCacheService(config);
5919
+ const stats = cache.getStats();
5920
+ return c.json({
5921
+ success: true,
5922
+ data: {
5923
+ namespace,
5924
+ config,
5925
+ stats
5926
+ },
5927
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
5928
+ });
5929
+ });
5930
+ app.post("/clear", async (c) => {
5931
+ await clearAllCaches();
5932
+ return c.json({
5933
+ success: true,
5934
+ message: "All cache entries cleared",
5935
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
5936
+ });
5937
+ });
5938
+ app.post("/clear/:namespace", async (c) => {
5939
+ const namespace = c.req.param("namespace");
5940
+ const config = CACHE_CONFIGS[namespace];
5941
+ if (!config) {
5942
+ return c.json({
5943
+ success: false,
5944
+ error: `Unknown namespace: ${namespace}`
5945
+ }, 404);
5946
+ }
5947
+ const cache = getCacheService(config);
5948
+ await cache.clear();
5949
+ return c.json({
5950
+ success: true,
5951
+ message: `Cache cleared for namespace: ${namespace}`,
5952
+ namespace,
5953
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
5954
+ });
5955
+ });
5956
+ app.post("/invalidate", async (c) => {
5957
+ const body = await c.req.json();
5958
+ const { pattern, namespace } = body;
5959
+ if (!pattern) {
5960
+ return c.json({
5961
+ success: false,
5962
+ error: "Pattern is required"
5963
+ }, 400);
5964
+ }
5965
+ let totalInvalidated = 0;
5966
+ if (namespace) {
5967
+ const config = CACHE_CONFIGS[namespace];
5968
+ if (!config) {
5969
+ return c.json({
5970
+ success: false,
5971
+ error: `Unknown namespace: ${namespace}`
5972
+ }, 404);
5973
+ }
5974
+ const cache = getCacheService(config);
5975
+ totalInvalidated = await cache.invalidate(pattern);
5976
+ } else {
5977
+ for (const config of Object.values(CACHE_CONFIGS)) {
5978
+ const cache = getCacheService(config);
5979
+ totalInvalidated += await cache.invalidate(pattern);
5980
+ }
5981
+ }
5982
+ return c.json({
5983
+ success: true,
5984
+ invalidated: totalInvalidated,
5985
+ pattern,
5986
+ namespace: namespace || "all",
5987
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
5988
+ });
5989
+ });
5990
+ app.get("/health", async (c) => {
5991
+ const stats = getAllCacheStats();
5992
+ const namespaces = Object.entries(stats);
5993
+ const healthChecks = namespaces.map(([name, stat]) => {
5994
+ const hitRate = stat.hitRate;
5995
+ const memoryUsage = stat.memorySize / (50 * 1024 * 1024);
5996
+ return {
5997
+ namespace: name,
5998
+ status: hitRate > 70 ? "healthy" : hitRate > 40 ? "warning" : "unhealthy",
5999
+ hitRate,
6000
+ memoryUsage: (memoryUsage * 100).toFixed(2) + "%",
6001
+ entryCount: stat.entryCount
6002
+ };
6003
+ });
6004
+ const overallStatus = healthChecks.every((h) => h.status === "healthy") ? "healthy" : healthChecks.some((h) => h.status === "unhealthy") ? "unhealthy" : "warning";
6005
+ return c.json({
6006
+ success: true,
6007
+ data: {
6008
+ status: overallStatus,
6009
+ namespaces: healthChecks,
6010
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
6011
+ }
6012
+ });
6013
+ });
6014
+ app.get("/browser", async (c) => {
6015
+ const namespace = c.req.query("namespace") || "all";
6016
+ const search = c.req.query("search") || "";
6017
+ const sortBy = c.req.query("sort") || "age";
6018
+ const limit = parseInt(c.req.query("limit") || "100");
6019
+ const entries = [];
6020
+ const namespaces = namespace === "all" ? Object.keys(CACHE_CONFIGS) : [namespace];
6021
+ for (const ns of namespaces) {
6022
+ const config = CACHE_CONFIGS[ns];
6023
+ if (!config) continue;
6024
+ const cache = getCacheService(config);
6025
+ const keys = await cache.listKeys();
6026
+ for (const keyInfo of keys) {
6027
+ if (search && !keyInfo.key.toLowerCase().includes(search.toLowerCase())) {
6028
+ continue;
6029
+ }
6030
+ const parsed = parseCacheKey(keyInfo.key);
6031
+ const ttl = Math.max(0, keyInfo.expiresAt - Date.now()) / 1e3;
6032
+ entries.push({
6033
+ namespace: ns,
6034
+ key: keyInfo.key,
6035
+ size: keyInfo.size,
6036
+ age: keyInfo.age,
6037
+ ttl,
6038
+ expiresAt: keyInfo.expiresAt,
6039
+ parsed
6040
+ });
6041
+ }
6042
+ }
6043
+ if (sortBy === "size") {
6044
+ entries.sort((a, b) => b.size - a.size);
6045
+ } else if (sortBy === "age") {
6046
+ entries.sort((a, b) => a.age - b.age);
6047
+ } else if (sortBy === "key") {
6048
+ entries.sort((a, b) => a.key.localeCompare(b.key));
6049
+ }
6050
+ const limitedEntries = entries.slice(0, limit);
6051
+ return c.json({
6052
+ success: true,
6053
+ data: {
6054
+ entries: limitedEntries,
6055
+ total: entries.length,
6056
+ showing: limitedEntries.length,
6057
+ namespace,
6058
+ search,
6059
+ sortBy
6060
+ },
6061
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
6062
+ });
6063
+ });
6064
+ app.get("/browser/:namespace/:key", async (c) => {
6065
+ const namespace = c.req.param("namespace");
6066
+ const key = decodeURIComponent(c.req.param("key"));
6067
+ const config = CACHE_CONFIGS[namespace];
6068
+ if (!config) {
6069
+ return c.json({
6070
+ success: false,
6071
+ error: `Unknown namespace: ${namespace}`
6072
+ }, 404);
6073
+ }
6074
+ const cache = getCacheService(config);
6075
+ const entry = await cache.getEntry(key);
6076
+ if (!entry) {
6077
+ return c.json({
6078
+ success: false,
6079
+ error: "Cache entry not found or expired"
6080
+ }, 404);
6081
+ }
6082
+ const parsed = parseCacheKey(key);
6083
+ return c.json({
6084
+ success: true,
6085
+ data: {
6086
+ key,
6087
+ namespace,
6088
+ parsed,
6089
+ ...entry,
6090
+ createdAt: new Date(entry.timestamp).toISOString(),
6091
+ expiresAt: new Date(entry.expiresAt).toISOString()
6092
+ },
6093
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
6094
+ });
6095
+ });
6096
+ app.get("/analytics", async (c) => {
6097
+ const stats = getAllCacheStats();
6098
+ const invalidationStats = getCacheInvalidationStats();
6099
+ const recentInvalidations = getRecentInvalidations(20);
6100
+ let totalHits = 0;
6101
+ let totalMisses = 0;
6102
+ let totalSize = 0;
6103
+ let totalEntries = 0;
6104
+ const namespacesAnalytics = [];
6105
+ for (const [namespace, stat] of Object.entries(stats)) {
6106
+ totalHits += stat.memoryHits + stat.kvHits;
6107
+ totalMisses += stat.memoryMisses + stat.kvMisses;
6108
+ totalSize += stat.memorySize;
6109
+ totalEntries += stat.entryCount;
6110
+ const totalRequests2 = stat.memoryHits + stat.kvHits + stat.memoryMisses + stat.kvMisses;
6111
+ const hitRate = totalRequests2 > 0 ? (stat.memoryHits + stat.kvHits) / totalRequests2 * 100 : 0;
6112
+ const avgEntrySize = stat.entryCount > 0 ? stat.memorySize / stat.entryCount : 0;
6113
+ namespacesAnalytics.push({
6114
+ namespace,
6115
+ hitRate: hitRate.toFixed(2),
6116
+ totalRequests: totalRequests2,
6117
+ memoryHitRate: totalRequests2 > 0 ? (stat.memoryHits / totalRequests2 * 100).toFixed(2) : "0",
6118
+ kvHitRate: totalRequests2 > 0 ? (stat.kvHits / totalRequests2 * 100).toFixed(2) : "0",
6119
+ avgEntrySize: Math.round(avgEntrySize),
6120
+ totalSize: stat.memorySize,
6121
+ entryCount: stat.entryCount,
6122
+ efficiency: totalRequests2 > 0 ? ((stat.memoryHits + stat.kvHits) / (stat.memoryHits + stat.kvHits + stat.dbHits + 1)).toFixed(2) : "0"
6123
+ });
6124
+ }
6125
+ namespacesAnalytics.sort((a, b) => parseFloat(b.hitRate) - parseFloat(a.hitRate));
6126
+ const totalRequests = totalHits + totalMisses;
6127
+ const overallHitRate = totalRequests > 0 ? totalHits / totalRequests * 100 : 0;
6128
+ const dbQueriesAvoided = totalHits;
6129
+ const timeSaved = dbQueriesAvoided * 48;
6130
+ const estimatedCostSavings = dbQueriesAvoided / 1e6 * 0.5;
6131
+ return c.json({
6132
+ success: true,
6133
+ data: {
6134
+ overview: {
6135
+ totalHits,
6136
+ totalMisses,
6137
+ totalRequests,
6138
+ overallHitRate: overallHitRate.toFixed(2),
6139
+ totalSize,
6140
+ totalEntries,
6141
+ avgEntrySize: totalEntries > 0 ? Math.round(totalSize / totalEntries) : 0
6142
+ },
6143
+ performance: {
6144
+ dbQueriesAvoided,
6145
+ timeSavedMs: timeSaved,
6146
+ timeSavedMinutes: (timeSaved / 1e3 / 60).toFixed(2),
6147
+ estimatedCostSavings: estimatedCostSavings.toFixed(4)
6148
+ },
6149
+ namespaces: namespacesAnalytics,
6150
+ invalidation: {
6151
+ ...invalidationStats,
6152
+ recent: recentInvalidations
6153
+ }
6154
+ },
6155
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
6156
+ });
6157
+ });
6158
+ app.get("/analytics/trends", async (c) => {
6159
+ const stats = getAllCacheStats();
6160
+ const dataPoint = {
6161
+ timestamp: Date.now(),
6162
+ stats: Object.entries(stats).map(([namespace, stat]) => ({
6163
+ namespace,
6164
+ hitRate: stat.hitRate,
6165
+ entryCount: stat.entryCount,
6166
+ memorySize: stat.memorySize,
6167
+ totalRequests: stat.totalRequests
6168
+ }))
6169
+ };
6170
+ return c.json({
6171
+ success: true,
6172
+ data: {
6173
+ trends: [dataPoint],
6174
+ note: "Historical trends require persistent storage. This returns current snapshot only."
6175
+ },
6176
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
6177
+ });
6178
+ });
6179
+ app.get("/analytics/top-keys", async (c) => {
6180
+ c.req.query("namespace") || "all";
6181
+ parseInt(c.req.query("limit") || "10");
6182
+ return c.json({
6183
+ success: true,
6184
+ data: {
6185
+ topKeys: [],
6186
+ note: "Top keys tracking requires per-key hit counting. Feature not yet implemented."
6187
+ },
6188
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
6189
+ });
6190
+ });
6191
+ app.post("/warm", async (c) => {
6192
+ try {
6193
+ const db = c.env.DB;
6194
+ const result = await warmCommonCaches(db);
6195
+ return c.json({
6196
+ success: true,
6197
+ message: "Cache warming completed",
6198
+ ...result,
6199
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
6200
+ });
6201
+ } catch (error) {
6202
+ console.error("Cache warming error:", error);
6203
+ return c.json({
6204
+ success: false,
6205
+ error: "Cache warming failed",
6206
+ details: error instanceof Error ? error.message : "Unknown error"
6207
+ }, 500);
6208
+ }
6209
+ });
6210
+ app.post("/warm/:namespace", async (c) => {
6211
+ try {
6212
+ const namespace = c.req.param("namespace");
6213
+ const body = await c.req.json();
6214
+ const { entries } = body;
6215
+ if (!entries || !Array.isArray(entries)) {
6216
+ return c.json({
6217
+ success: false,
6218
+ error: "Entries array is required"
6219
+ }, 400);
6220
+ }
6221
+ const count = await warmNamespace(namespace, entries);
6222
+ return c.json({
6223
+ success: true,
6224
+ message: `Warmed ${count} entries in namespace: ${namespace}`,
6225
+ namespace,
6226
+ count,
6227
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
6228
+ });
6229
+ } catch (error) {
6230
+ console.error("Namespace warming error:", error);
6231
+ return c.json({
6232
+ success: false,
6233
+ error: "Namespace warming failed",
6234
+ details: error instanceof Error ? error.message : "Unknown error"
6235
+ }, 500);
6236
+ }
6237
+ });
6238
+ var routes_default = app;
6239
+
6240
+ // src/plugins/cache/index.ts
6241
+ var CachePlugin = class {
6242
+ _context = null;
6243
+ /**
6244
+ * Get plugin routes
6245
+ */
6246
+ getRoutes() {
6247
+ return routes_default;
6248
+ }
6249
+ /**
6250
+ * Activate the cache plugin
6251
+ */
6252
+ async activate(context) {
6253
+ this._context = context;
6254
+ const settings = context.config || {};
6255
+ console.log("\u2705 Cache plugin activated", {
6256
+ memoryEnabled: settings.memoryEnabled ?? true,
6257
+ kvEnabled: settings.kvEnabled ?? false,
6258
+ defaultTTL: settings.defaultTTL ?? 3600
6259
+ });
6260
+ for (const [_namespace, config] of Object.entries(CACHE_CONFIGS)) {
6261
+ getCacheService({
6262
+ ...config,
6263
+ memoryEnabled: settings.memoryEnabled ?? config.memoryEnabled,
6264
+ kvEnabled: settings.kvEnabled ?? config.kvEnabled,
6265
+ ttl: settings.defaultTTL ?? config.ttl
6266
+ });
6267
+ }
6268
+ setupCacheInvalidation();
6269
+ }
6270
+ /**
6271
+ * Deactivate the cache plugin
6272
+ */
6273
+ async deactivate() {
6274
+ console.log("\u274C Cache plugin deactivated - clearing all caches");
6275
+ await clearAllCaches();
6276
+ this._context = null;
6277
+ }
6278
+ /**
6279
+ * Configure the cache plugin
6280
+ */
6281
+ async configure(settings) {
6282
+ console.log("\u2699\uFE0F Cache plugin configured", settings);
6283
+ for (const [_namespace, config] of Object.entries(CACHE_CONFIGS)) {
6284
+ getCacheService({
6285
+ ...config,
6286
+ memoryEnabled: settings.memoryEnabled ?? config.memoryEnabled,
6287
+ kvEnabled: settings.kvEnabled ?? config.kvEnabled,
6288
+ ttl: settings.defaultTTL ?? config.ttl
6289
+ });
6290
+ }
6291
+ }
6292
+ /**
6293
+ * Get cache statistics
6294
+ */
6295
+ async getStats(c) {
6296
+ const stats = getAllCacheStats();
6297
+ return c.json({
6298
+ success: true,
6299
+ data: stats,
6300
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
6301
+ });
6302
+ }
6303
+ /**
6304
+ * Clear all cache entries
6305
+ */
6306
+ async clearCache(c) {
6307
+ await clearAllCaches();
6308
+ return c.json({
6309
+ success: true,
6310
+ message: "All cache entries cleared",
6311
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
6312
+ });
6313
+ }
6314
+ /**
6315
+ * Invalidate cache entries matching pattern
6316
+ */
6317
+ async invalidatePattern(c) {
6318
+ const body = await c.req.json();
6319
+ const { pattern, namespace: _namespace } = body;
6320
+ if (!pattern) {
6321
+ return c.json({
6322
+ success: false,
6323
+ error: "Pattern is required"
6324
+ }, 400);
6325
+ }
6326
+ let totalInvalidated = 0;
6327
+ if (_namespace) {
6328
+ const cache = getCacheService(CACHE_CONFIGS[_namespace] || {
6329
+ ttl: 3600,
6330
+ kvEnabled: false,
6331
+ memoryEnabled: true,
6332
+ namespace: _namespace,
6333
+ invalidateOn: [],
6334
+ version: "v1"
6335
+ });
6336
+ totalInvalidated = await cache.invalidate(pattern);
6337
+ } else {
6338
+ for (const config of Object.values(CACHE_CONFIGS)) {
6339
+ const cache = getCacheService(config);
6340
+ totalInvalidated += await cache.invalidate(pattern);
6341
+ }
6342
+ }
6343
+ return c.json({
6344
+ success: true,
6345
+ invalidated: totalInvalidated,
6346
+ pattern,
6347
+ namespace: _namespace || "all",
6348
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
6349
+ });
6350
+ }
6351
+ };
6352
+ var plugin = new CachePlugin();
6353
+ var cache_default = plugin;
6354
+
4538
6355
  // src/assets/favicon.ts
4539
6356
  var faviconSvg = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
4540
6357
  <svg
@@ -4566,69 +6383,70 @@ var faviconSvg = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
4566
6383
 
4567
6384
  // src/app.ts
4568
6385
  function createSonicJSApp(config = {}) {
4569
- const app = new hono.Hono();
4570
- const appVersion = config.version || chunkYMTTGHEK_cjs.getCoreVersion();
6386
+ const app2 = new hono.Hono();
6387
+ const appVersion = config.version || chunkMYB5RY7H_cjs.getCoreVersion();
4571
6388
  const appName = config.name || "SonicJS AI";
4572
- app.use("*", async (c, next) => {
6389
+ app2.use("*", async (c, next) => {
4573
6390
  c.set("appVersion", appVersion);
4574
6391
  await next();
4575
6392
  });
4576
- app.use("*", chunkT3YIKW2A_cjs.metricsMiddleware());
4577
- app.use("*", chunkT3YIKW2A_cjs.bootstrapMiddleware(config));
6393
+ app2.use("*", chunkE2BXLXPW_cjs.metricsMiddleware());
6394
+ app2.use("*", chunkE2BXLXPW_cjs.bootstrapMiddleware(config));
4578
6395
  if (config.middleware?.beforeAuth) {
4579
6396
  for (const middleware of config.middleware.beforeAuth) {
4580
- app.use("*", middleware);
6397
+ app2.use("*", middleware);
4581
6398
  }
4582
6399
  }
4583
- app.use("*", async (_c, next) => {
6400
+ app2.use("*", async (_c, next) => {
4584
6401
  await next();
4585
6402
  });
4586
- app.use("*", async (_c, next) => {
6403
+ app2.use("*", async (_c, next) => {
4587
6404
  await next();
4588
6405
  });
4589
6406
  if (config.middleware?.afterAuth) {
4590
6407
  for (const middleware of config.middleware.afterAuth) {
4591
- app.use("*", middleware);
4592
- }
4593
- }
4594
- app.route("/api", chunkN7TDLOUE_cjs.api_default);
4595
- app.route("/api/media", chunkN7TDLOUE_cjs.api_media_default);
4596
- app.route("/api/system", chunkN7TDLOUE_cjs.api_system_default);
4597
- app.route("/admin/api", chunkN7TDLOUE_cjs.admin_api_default);
4598
- app.route("/admin/dashboard", chunkN7TDLOUE_cjs.router);
4599
- app.route("/admin/collections", chunkN7TDLOUE_cjs.adminCollectionsRoutes);
4600
- app.route("/admin/settings", chunkN7TDLOUE_cjs.adminSettingsRoutes);
4601
- app.route("/admin/database-tools", createDatabaseToolsAdminRoutes());
4602
- app.route("/admin/seed-data", createSeedDataAdminRoutes());
4603
- app.route("/admin/content", chunkN7TDLOUE_cjs.admin_content_default);
4604
- app.route("/admin/media", chunkN7TDLOUE_cjs.adminMediaRoutes);
6408
+ app2.use("*", middleware);
6409
+ }
6410
+ }
6411
+ app2.route("/api", chunkJ7F3NPAP_cjs.api_default);
6412
+ app2.route("/api/media", chunkJ7F3NPAP_cjs.api_media_default);
6413
+ app2.route("/api/system", chunkJ7F3NPAP_cjs.api_system_default);
6414
+ app2.route("/admin/api", chunkJ7F3NPAP_cjs.admin_api_default);
6415
+ app2.route("/admin/dashboard", chunkJ7F3NPAP_cjs.router);
6416
+ app2.route("/admin/collections", chunkJ7F3NPAP_cjs.adminCollectionsRoutes);
6417
+ app2.route("/admin/settings", chunkJ7F3NPAP_cjs.adminSettingsRoutes);
6418
+ app2.route("/admin/database-tools", createDatabaseToolsAdminRoutes());
6419
+ app2.route("/admin/seed-data", createSeedDataAdminRoutes());
6420
+ app2.route("/admin/content", chunkJ7F3NPAP_cjs.admin_content_default);
6421
+ app2.route("/admin/media", chunkJ7F3NPAP_cjs.adminMediaRoutes);
4605
6422
  if (aiSearchPlugin.routes && aiSearchPlugin.routes.length > 0) {
4606
6423
  for (const route of aiSearchPlugin.routes) {
4607
- app.route(route.path, route.handler);
6424
+ app2.route(route.path, route.handler);
4608
6425
  }
4609
6426
  }
4610
- app.route("/admin/plugins", chunkN7TDLOUE_cjs.adminPluginRoutes);
4611
- app.route("/admin/logs", chunkN7TDLOUE_cjs.adminLogsRoutes);
4612
- app.route("/admin", chunkN7TDLOUE_cjs.userRoutes);
4613
- app.route("/auth", chunkN7TDLOUE_cjs.auth_default);
4614
- app.route("/", chunkN7TDLOUE_cjs.test_cleanup_default);
6427
+ app2.route("/admin/cache", cache_default.getRoutes());
6428
+ app2.route("/admin/plugins", chunkJ7F3NPAP_cjs.adminPluginRoutes);
6429
+ app2.route("/admin/logs", chunkJ7F3NPAP_cjs.adminLogsRoutes);
6430
+ app2.route("/admin", chunkJ7F3NPAP_cjs.userRoutes);
6431
+ app2.route("/auth", chunkJ7F3NPAP_cjs.auth_default);
6432
+ app2.route("/", chunkJ7F3NPAP_cjs.test_cleanup_default);
4615
6433
  if (emailPlugin.routes && emailPlugin.routes.length > 0) {
4616
6434
  for (const route of emailPlugin.routes) {
4617
- app.route(route.path, route.handler);
6435
+ app2.route(route.path, route.handler);
4618
6436
  }
4619
6437
  }
4620
6438
  if (otpLoginPlugin.routes && otpLoginPlugin.routes.length > 0) {
4621
6439
  for (const route of otpLoginPlugin.routes) {
4622
- app.route(route.path, route.handler);
6440
+ app2.route(route.path, route.handler);
4623
6441
  }
4624
6442
  }
4625
6443
  const magicLinkPlugin = createMagicLinkAuthPlugin();
4626
6444
  if (magicLinkPlugin.routes && magicLinkPlugin.routes.length > 0) {
4627
6445
  for (const route of magicLinkPlugin.routes) {
4628
- app.route(route.path, route.handler);
6446
+ app2.route(route.path, route.handler);
4629
6447
  }
4630
6448
  }
4631
- app.get("/favicon.svg", (c) => {
6449
+ app2.get("/favicon.svg", (c) => {
4632
6450
  return new Response(faviconSvg, {
4633
6451
  headers: {
4634
6452
  "Content-Type": "image/svg+xml",
@@ -4636,7 +6454,7 @@ function createSonicJSApp(config = {}) {
4636
6454
  }
4637
6455
  });
4638
6456
  });
4639
- app.get("/files/*", async (c) => {
6457
+ app2.get("/files/*", async (c) => {
4640
6458
  try {
4641
6459
  const url = new URL(c.req.url);
4642
6460
  const pathname = url.pathname;
@@ -4665,13 +6483,13 @@ function createSonicJSApp(config = {}) {
4665
6483
  });
4666
6484
  if (config.routes) {
4667
6485
  for (const route of config.routes) {
4668
- app.route(route.path, route.handler);
6486
+ app2.route(route.path, route.handler);
4669
6487
  }
4670
6488
  }
4671
- app.get("/", (c) => {
6489
+ app2.get("/", (c) => {
4672
6490
  return c.redirect("/auth/login");
4673
6491
  });
4674
- app.get("/health", (c) => {
6492
+ app2.get("/health", (c) => {
4675
6493
  return c.json({
4676
6494
  name: appName,
4677
6495
  version: appVersion,
@@ -4679,14 +6497,14 @@ function createSonicJSApp(config = {}) {
4679
6497
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
4680
6498
  });
4681
6499
  });
4682
- app.notFound((c) => {
6500
+ app2.notFound((c) => {
4683
6501
  return c.json({ error: "Not Found", status: 404 }, 404);
4684
6502
  });
4685
- app.onError((err, c) => {
6503
+ app2.onError((err, c) => {
4686
6504
  console.error(err);
4687
6505
  return c.json({ error: "Internal Server Error", status: 500 }, 500);
4688
6506
  });
4689
- return app;
6507
+ return app2;
4690
6508
  }
4691
6509
  function setupCoreMiddleware(_app) {
4692
6510
  console.warn("setupCoreMiddleware is deprecated. Use createSonicJSApp() instead.");
@@ -4699,83 +6517,83 @@ function createDb(d1$1) {
4699
6517
  }
4700
6518
 
4701
6519
  // src/index.ts
4702
- var VERSION = chunkYMTTGHEK_cjs.package_default.version;
6520
+ var VERSION = chunkMYB5RY7H_cjs.package_default.version;
4703
6521
 
4704
6522
  Object.defineProperty(exports, "ROUTES_INFO", {
4705
6523
  enumerable: true,
4706
- get: function () { return chunkN7TDLOUE_cjs.ROUTES_INFO; }
6524
+ get: function () { return chunkJ7F3NPAP_cjs.ROUTES_INFO; }
4707
6525
  });
4708
6526
  Object.defineProperty(exports, "adminApiRoutes", {
4709
6527
  enumerable: true,
4710
- get: function () { return chunkN7TDLOUE_cjs.admin_api_default; }
6528
+ get: function () { return chunkJ7F3NPAP_cjs.admin_api_default; }
4711
6529
  });
4712
6530
  Object.defineProperty(exports, "adminCheckboxRoutes", {
4713
6531
  enumerable: true,
4714
- get: function () { return chunkN7TDLOUE_cjs.adminCheckboxRoutes; }
6532
+ get: function () { return chunkJ7F3NPAP_cjs.adminCheckboxRoutes; }
4715
6533
  });
4716
6534
  Object.defineProperty(exports, "adminCodeExamplesRoutes", {
4717
6535
  enumerable: true,
4718
- get: function () { return chunkN7TDLOUE_cjs.admin_code_examples_default; }
6536
+ get: function () { return chunkJ7F3NPAP_cjs.admin_code_examples_default; }
4719
6537
  });
4720
6538
  Object.defineProperty(exports, "adminCollectionsRoutes", {
4721
6539
  enumerable: true,
4722
- get: function () { return chunkN7TDLOUE_cjs.adminCollectionsRoutes; }
6540
+ get: function () { return chunkJ7F3NPAP_cjs.adminCollectionsRoutes; }
4723
6541
  });
4724
6542
  Object.defineProperty(exports, "adminContentRoutes", {
4725
6543
  enumerable: true,
4726
- get: function () { return chunkN7TDLOUE_cjs.admin_content_default; }
6544
+ get: function () { return chunkJ7F3NPAP_cjs.admin_content_default; }
4727
6545
  });
4728
6546
  Object.defineProperty(exports, "adminDashboardRoutes", {
4729
6547
  enumerable: true,
4730
- get: function () { return chunkN7TDLOUE_cjs.router; }
6548
+ get: function () { return chunkJ7F3NPAP_cjs.router; }
4731
6549
  });
4732
6550
  Object.defineProperty(exports, "adminDesignRoutes", {
4733
6551
  enumerable: true,
4734
- get: function () { return chunkN7TDLOUE_cjs.adminDesignRoutes; }
6552
+ get: function () { return chunkJ7F3NPAP_cjs.adminDesignRoutes; }
4735
6553
  });
4736
6554
  Object.defineProperty(exports, "adminLogsRoutes", {
4737
6555
  enumerable: true,
4738
- get: function () { return chunkN7TDLOUE_cjs.adminLogsRoutes; }
6556
+ get: function () { return chunkJ7F3NPAP_cjs.adminLogsRoutes; }
4739
6557
  });
4740
6558
  Object.defineProperty(exports, "adminMediaRoutes", {
4741
6559
  enumerable: true,
4742
- get: function () { return chunkN7TDLOUE_cjs.adminMediaRoutes; }
6560
+ get: function () { return chunkJ7F3NPAP_cjs.adminMediaRoutes; }
4743
6561
  });
4744
6562
  Object.defineProperty(exports, "adminPluginRoutes", {
4745
6563
  enumerable: true,
4746
- get: function () { return chunkN7TDLOUE_cjs.adminPluginRoutes; }
6564
+ get: function () { return chunkJ7F3NPAP_cjs.adminPluginRoutes; }
4747
6565
  });
4748
6566
  Object.defineProperty(exports, "adminSettingsRoutes", {
4749
6567
  enumerable: true,
4750
- get: function () { return chunkN7TDLOUE_cjs.adminSettingsRoutes; }
6568
+ get: function () { return chunkJ7F3NPAP_cjs.adminSettingsRoutes; }
4751
6569
  });
4752
6570
  Object.defineProperty(exports, "adminTestimonialsRoutes", {
4753
6571
  enumerable: true,
4754
- get: function () { return chunkN7TDLOUE_cjs.admin_testimonials_default; }
6572
+ get: function () { return chunkJ7F3NPAP_cjs.admin_testimonials_default; }
4755
6573
  });
4756
6574
  Object.defineProperty(exports, "adminUsersRoutes", {
4757
6575
  enumerable: true,
4758
- get: function () { return chunkN7TDLOUE_cjs.userRoutes; }
6576
+ get: function () { return chunkJ7F3NPAP_cjs.userRoutes; }
4759
6577
  });
4760
6578
  Object.defineProperty(exports, "apiContentCrudRoutes", {
4761
6579
  enumerable: true,
4762
- get: function () { return chunkN7TDLOUE_cjs.api_content_crud_default; }
6580
+ get: function () { return chunkJ7F3NPAP_cjs.api_content_crud_default; }
4763
6581
  });
4764
6582
  Object.defineProperty(exports, "apiMediaRoutes", {
4765
6583
  enumerable: true,
4766
- get: function () { return chunkN7TDLOUE_cjs.api_media_default; }
6584
+ get: function () { return chunkJ7F3NPAP_cjs.api_media_default; }
4767
6585
  });
4768
6586
  Object.defineProperty(exports, "apiRoutes", {
4769
6587
  enumerable: true,
4770
- get: function () { return chunkN7TDLOUE_cjs.api_default; }
6588
+ get: function () { return chunkJ7F3NPAP_cjs.api_default; }
4771
6589
  });
4772
6590
  Object.defineProperty(exports, "apiSystemRoutes", {
4773
6591
  enumerable: true,
4774
- get: function () { return chunkN7TDLOUE_cjs.api_system_default; }
6592
+ get: function () { return chunkJ7F3NPAP_cjs.api_system_default; }
4775
6593
  });
4776
6594
  Object.defineProperty(exports, "authRoutes", {
4777
6595
  enumerable: true,
4778
- get: function () { return chunkN7TDLOUE_cjs.auth_default; }
6596
+ get: function () { return chunkJ7F3NPAP_cjs.auth_default; }
4779
6597
  });
4780
6598
  Object.defineProperty(exports, "Logger", {
4781
6599
  enumerable: true,
@@ -4943,83 +6761,83 @@ Object.defineProperty(exports, "workflowHistory", {
4943
6761
  });
4944
6762
  Object.defineProperty(exports, "AuthManager", {
4945
6763
  enumerable: true,
4946
- get: function () { return chunkT3YIKW2A_cjs.AuthManager; }
6764
+ get: function () { return chunkE2BXLXPW_cjs.AuthManager; }
4947
6765
  });
4948
6766
  Object.defineProperty(exports, "PermissionManager", {
4949
6767
  enumerable: true,
4950
- get: function () { return chunkT3YIKW2A_cjs.PermissionManager; }
6768
+ get: function () { return chunkE2BXLXPW_cjs.PermissionManager; }
4951
6769
  });
4952
6770
  Object.defineProperty(exports, "bootstrapMiddleware", {
4953
6771
  enumerable: true,
4954
- get: function () { return chunkT3YIKW2A_cjs.bootstrapMiddleware; }
6772
+ get: function () { return chunkE2BXLXPW_cjs.bootstrapMiddleware; }
4955
6773
  });
4956
6774
  Object.defineProperty(exports, "cacheHeaders", {
4957
6775
  enumerable: true,
4958
- get: function () { return chunkT3YIKW2A_cjs.cacheHeaders; }
6776
+ get: function () { return chunkE2BXLXPW_cjs.cacheHeaders; }
4959
6777
  });
4960
6778
  Object.defineProperty(exports, "compressionMiddleware", {
4961
6779
  enumerable: true,
4962
- get: function () { return chunkT3YIKW2A_cjs.compressionMiddleware; }
6780
+ get: function () { return chunkE2BXLXPW_cjs.compressionMiddleware; }
4963
6781
  });
4964
6782
  Object.defineProperty(exports, "detailedLoggingMiddleware", {
4965
6783
  enumerable: true,
4966
- get: function () { return chunkT3YIKW2A_cjs.detailedLoggingMiddleware; }
6784
+ get: function () { return chunkE2BXLXPW_cjs.detailedLoggingMiddleware; }
4967
6785
  });
4968
6786
  Object.defineProperty(exports, "getActivePlugins", {
4969
6787
  enumerable: true,
4970
- get: function () { return chunkT3YIKW2A_cjs.getActivePlugins; }
6788
+ get: function () { return chunkE2BXLXPW_cjs.getActivePlugins; }
4971
6789
  });
4972
6790
  Object.defineProperty(exports, "isPluginActive", {
4973
6791
  enumerable: true,
4974
- get: function () { return chunkT3YIKW2A_cjs.isPluginActive; }
6792
+ get: function () { return chunkE2BXLXPW_cjs.isPluginActive; }
4975
6793
  });
4976
6794
  Object.defineProperty(exports, "logActivity", {
4977
6795
  enumerable: true,
4978
- get: function () { return chunkT3YIKW2A_cjs.logActivity; }
6796
+ get: function () { return chunkE2BXLXPW_cjs.logActivity; }
4979
6797
  });
4980
6798
  Object.defineProperty(exports, "loggingMiddleware", {
4981
6799
  enumerable: true,
4982
- get: function () { return chunkT3YIKW2A_cjs.loggingMiddleware; }
6800
+ get: function () { return chunkE2BXLXPW_cjs.loggingMiddleware; }
4983
6801
  });
4984
6802
  Object.defineProperty(exports, "optionalAuth", {
4985
6803
  enumerable: true,
4986
- get: function () { return chunkT3YIKW2A_cjs.optionalAuth; }
6804
+ get: function () { return chunkE2BXLXPW_cjs.optionalAuth; }
4987
6805
  });
4988
6806
  Object.defineProperty(exports, "performanceLoggingMiddleware", {
4989
6807
  enumerable: true,
4990
- get: function () { return chunkT3YIKW2A_cjs.performanceLoggingMiddleware; }
6808
+ get: function () { return chunkE2BXLXPW_cjs.performanceLoggingMiddleware; }
4991
6809
  });
4992
6810
  Object.defineProperty(exports, "requireActivePlugin", {
4993
6811
  enumerable: true,
4994
- get: function () { return chunkT3YIKW2A_cjs.requireActivePlugin; }
6812
+ get: function () { return chunkE2BXLXPW_cjs.requireActivePlugin; }
4995
6813
  });
4996
6814
  Object.defineProperty(exports, "requireActivePlugins", {
4997
6815
  enumerable: true,
4998
- get: function () { return chunkT3YIKW2A_cjs.requireActivePlugins; }
6816
+ get: function () { return chunkE2BXLXPW_cjs.requireActivePlugins; }
4999
6817
  });
5000
6818
  Object.defineProperty(exports, "requireAnyPermission", {
5001
6819
  enumerable: true,
5002
- get: function () { return chunkT3YIKW2A_cjs.requireAnyPermission; }
6820
+ get: function () { return chunkE2BXLXPW_cjs.requireAnyPermission; }
5003
6821
  });
5004
6822
  Object.defineProperty(exports, "requireAuth", {
5005
6823
  enumerable: true,
5006
- get: function () { return chunkT3YIKW2A_cjs.requireAuth; }
6824
+ get: function () { return chunkE2BXLXPW_cjs.requireAuth; }
5007
6825
  });
5008
6826
  Object.defineProperty(exports, "requirePermission", {
5009
6827
  enumerable: true,
5010
- get: function () { return chunkT3YIKW2A_cjs.requirePermission; }
6828
+ get: function () { return chunkE2BXLXPW_cjs.requirePermission; }
5011
6829
  });
5012
6830
  Object.defineProperty(exports, "requireRole", {
5013
6831
  enumerable: true,
5014
- get: function () { return chunkT3YIKW2A_cjs.requireRole; }
6832
+ get: function () { return chunkE2BXLXPW_cjs.requireRole; }
5015
6833
  });
5016
6834
  Object.defineProperty(exports, "securityHeaders", {
5017
6835
  enumerable: true,
5018
- get: function () { return chunkT3YIKW2A_cjs.securityHeaders; }
6836
+ get: function () { return chunkE2BXLXPW_cjs.securityHeaders; }
5019
6837
  });
5020
6838
  Object.defineProperty(exports, "securityLoggingMiddleware", {
5021
6839
  enumerable: true,
5022
- get: function () { return chunkT3YIKW2A_cjs.securityLoggingMiddleware; }
6840
+ get: function () { return chunkE2BXLXPW_cjs.securityLoggingMiddleware; }
5023
6841
  });
5024
6842
  Object.defineProperty(exports, "PluginBootstrapService", {
5025
6843
  enumerable: true,
@@ -5075,39 +6893,39 @@ Object.defineProperty(exports, "validateCollectionConfig", {
5075
6893
  });
5076
6894
  Object.defineProperty(exports, "MigrationService", {
5077
6895
  enumerable: true,
5078
- get: function () { return chunkIIRVZSP2_cjs.MigrationService; }
6896
+ get: function () { return chunkYRFAQ6MI_cjs.MigrationService; }
5079
6897
  });
5080
6898
  Object.defineProperty(exports, "renderFilterBar", {
5081
6899
  enumerable: true,
5082
- get: function () { return chunk63K7XXRX_cjs.renderFilterBar; }
6900
+ get: function () { return chunkAYPF6C4D_cjs.renderFilterBar; }
5083
6901
  });
5084
6902
  Object.defineProperty(exports, "getConfirmationDialogScript", {
5085
6903
  enumerable: true,
5086
- get: function () { return chunkBZC4FYW7_cjs.getConfirmationDialogScript; }
6904
+ get: function () { return chunkEHSZ6TAN_cjs.getConfirmationDialogScript; }
5087
6905
  });
5088
6906
  Object.defineProperty(exports, "renderAlert", {
5089
6907
  enumerable: true,
5090
- get: function () { return chunkBZC4FYW7_cjs.renderAlert; }
6908
+ get: function () { return chunkEHSZ6TAN_cjs.renderAlert; }
5091
6909
  });
5092
6910
  Object.defineProperty(exports, "renderConfirmationDialog", {
5093
6911
  enumerable: true,
5094
- get: function () { return chunkBZC4FYW7_cjs.renderConfirmationDialog; }
6912
+ get: function () { return chunkEHSZ6TAN_cjs.renderConfirmationDialog; }
5095
6913
  });
5096
6914
  Object.defineProperty(exports, "renderForm", {
5097
6915
  enumerable: true,
5098
- get: function () { return chunkBZC4FYW7_cjs.renderForm; }
6916
+ get: function () { return chunkEHSZ6TAN_cjs.renderForm; }
5099
6917
  });
5100
6918
  Object.defineProperty(exports, "renderFormField", {
5101
6919
  enumerable: true,
5102
- get: function () { return chunkBZC4FYW7_cjs.renderFormField; }
6920
+ get: function () { return chunkEHSZ6TAN_cjs.renderFormField; }
5103
6921
  });
5104
6922
  Object.defineProperty(exports, "renderPagination", {
5105
6923
  enumerable: true,
5106
- get: function () { return chunkBZC4FYW7_cjs.renderPagination; }
6924
+ get: function () { return chunkEHSZ6TAN_cjs.renderPagination; }
5107
6925
  });
5108
6926
  Object.defineProperty(exports, "renderTable", {
5109
6927
  enumerable: true,
5110
- get: function () { return chunkBZC4FYW7_cjs.renderTable; }
6928
+ get: function () { return chunkEHSZ6TAN_cjs.renderTable; }
5111
6929
  });
5112
6930
  Object.defineProperty(exports, "HookSystemImpl", {
5113
6931
  enumerable: true,
@@ -5143,43 +6961,43 @@ Object.defineProperty(exports, "PluginHelpers", {
5143
6961
  });
5144
6962
  Object.defineProperty(exports, "QueryFilterBuilder", {
5145
6963
  enumerable: true,
5146
- get: function () { return chunkYMTTGHEK_cjs.QueryFilterBuilder; }
6964
+ get: function () { return chunkMYB5RY7H_cjs.QueryFilterBuilder; }
5147
6965
  });
5148
6966
  Object.defineProperty(exports, "SONICJS_VERSION", {
5149
6967
  enumerable: true,
5150
- get: function () { return chunkYMTTGHEK_cjs.SONICJS_VERSION; }
6968
+ get: function () { return chunkMYB5RY7H_cjs.SONICJS_VERSION; }
5151
6969
  });
5152
6970
  Object.defineProperty(exports, "TemplateRenderer", {
5153
6971
  enumerable: true,
5154
- get: function () { return chunkYMTTGHEK_cjs.TemplateRenderer; }
6972
+ get: function () { return chunkMYB5RY7H_cjs.TemplateRenderer; }
5155
6973
  });
5156
6974
  Object.defineProperty(exports, "buildQuery", {
5157
6975
  enumerable: true,
5158
- get: function () { return chunkYMTTGHEK_cjs.buildQuery; }
6976
+ get: function () { return chunkMYB5RY7H_cjs.buildQuery; }
5159
6977
  });
5160
6978
  Object.defineProperty(exports, "escapeHtml", {
5161
6979
  enumerable: true,
5162
- get: function () { return chunkYMTTGHEK_cjs.escapeHtml; }
6980
+ get: function () { return chunkMYB5RY7H_cjs.escapeHtml; }
5163
6981
  });
5164
6982
  Object.defineProperty(exports, "getCoreVersion", {
5165
6983
  enumerable: true,
5166
- get: function () { return chunkYMTTGHEK_cjs.getCoreVersion; }
6984
+ get: function () { return chunkMYB5RY7H_cjs.getCoreVersion; }
5167
6985
  });
5168
6986
  Object.defineProperty(exports, "renderTemplate", {
5169
6987
  enumerable: true,
5170
- get: function () { return chunkYMTTGHEK_cjs.renderTemplate; }
6988
+ get: function () { return chunkMYB5RY7H_cjs.renderTemplate; }
5171
6989
  });
5172
6990
  Object.defineProperty(exports, "sanitizeInput", {
5173
6991
  enumerable: true,
5174
- get: function () { return chunkYMTTGHEK_cjs.sanitizeInput; }
6992
+ get: function () { return chunkMYB5RY7H_cjs.sanitizeInput; }
5175
6993
  });
5176
6994
  Object.defineProperty(exports, "sanitizeObject", {
5177
6995
  enumerable: true,
5178
- get: function () { return chunkYMTTGHEK_cjs.sanitizeObject; }
6996
+ get: function () { return chunkMYB5RY7H_cjs.sanitizeObject; }
5179
6997
  });
5180
6998
  Object.defineProperty(exports, "templateRenderer", {
5181
6999
  enumerable: true,
5182
- get: function () { return chunkYMTTGHEK_cjs.templateRenderer; }
7000
+ get: function () { return chunkMYB5RY7H_cjs.templateRenderer; }
5183
7001
  });
5184
7002
  Object.defineProperty(exports, "metricsTracker", {
5185
7003
  enumerable: true,