@fjell/cache 4.7.60 → 4.7.62

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 (80) hide show
  1. package/dist/Aggregator.d.ts +1 -1
  2. package/dist/Aggregator.d.ts.map +1 -1
  3. package/dist/Cache.d.ts +1 -2
  4. package/dist/Cache.d.ts.map +1 -1
  5. package/dist/CacheContext.d.ts +1 -2
  6. package/dist/CacheContext.d.ts.map +1 -1
  7. package/dist/CacheMap.d.ts +1 -1
  8. package/dist/CacheMap.d.ts.map +1 -1
  9. package/dist/CacheStats.d.ts +6 -0
  10. package/dist/CacheStats.d.ts.map +1 -1
  11. package/dist/Instance.d.ts +1 -2
  12. package/dist/Instance.d.ts.map +1 -1
  13. package/dist/InstanceFactory.d.ts +1 -1
  14. package/dist/InstanceFactory.d.ts.map +1 -1
  15. package/dist/Operations.d.ts +4 -3
  16. package/dist/Operations.d.ts.map +1 -1
  17. package/dist/Options.d.ts +1 -1
  18. package/dist/Options.d.ts.map +1 -1
  19. package/dist/browser/AsyncIndexDBCacheMap.d.ts +1 -1
  20. package/dist/browser/AsyncIndexDBCacheMap.d.ts.map +1 -1
  21. package/dist/browser/IndexDBCacheMap.d.ts +1 -1
  22. package/dist/browser/IndexDBCacheMap.d.ts.map +1 -1
  23. package/dist/browser/LocalStorageCacheMap.d.ts +1 -1
  24. package/dist/browser/LocalStorageCacheMap.d.ts.map +1 -1
  25. package/dist/browser/SessionStorageCacheMap.d.ts +1 -1
  26. package/dist/browser/SessionStorageCacheMap.d.ts.map +1 -1
  27. package/dist/cache/TwoLayerFactory.d.ts +1 -1
  28. package/dist/cache/TwoLayerFactory.d.ts.map +1 -1
  29. package/dist/cache/layers/TwoLayerCacheMap.d.ts +1 -1
  30. package/dist/cache/layers/TwoLayerCacheMap.d.ts.map +1 -1
  31. package/dist/events/CacheEventEmitter.d.ts +1 -1
  32. package/dist/events/CacheEventEmitter.d.ts.map +1 -1
  33. package/dist/events/CacheEventFactory.d.ts +1 -1
  34. package/dist/events/CacheEventFactory.d.ts.map +1 -1
  35. package/dist/events/CacheEventTypes.d.ts +1 -1
  36. package/dist/events/CacheEventTypes.d.ts.map +1 -1
  37. package/dist/eviction/EvictionStrategyValidation.d.ts.map +1 -1
  38. package/dist/index.js +849 -229
  39. package/dist/memory/EnhancedMemoryCacheMap.d.ts +1 -1
  40. package/dist/memory/EnhancedMemoryCacheMap.d.ts.map +1 -1
  41. package/dist/memory/MemoryCacheMap.d.ts +1 -1
  42. package/dist/memory/MemoryCacheMap.d.ts.map +1 -1
  43. package/dist/normalization.d.ts +1 -1
  44. package/dist/normalization.d.ts.map +1 -1
  45. package/dist/ops/action.d.ts +1 -1
  46. package/dist/ops/action.d.ts.map +1 -1
  47. package/dist/ops/all.d.ts +1 -1
  48. package/dist/ops/all.d.ts.map +1 -1
  49. package/dist/ops/allAction.d.ts +1 -1
  50. package/dist/ops/allAction.d.ts.map +1 -1
  51. package/dist/ops/allFacet.d.ts +1 -1
  52. package/dist/ops/allFacet.d.ts.map +1 -1
  53. package/dist/ops/create.d.ts +1 -1
  54. package/dist/ops/create.d.ts.map +1 -1
  55. package/dist/ops/facet.d.ts +1 -1
  56. package/dist/ops/facet.d.ts.map +1 -1
  57. package/dist/ops/find.d.ts +1 -1
  58. package/dist/ops/find.d.ts.map +1 -1
  59. package/dist/ops/findOne.d.ts +1 -1
  60. package/dist/ops/findOne.d.ts.map +1 -1
  61. package/dist/ops/get.d.ts +1 -1
  62. package/dist/ops/get.d.ts.map +1 -1
  63. package/dist/ops/one.d.ts +1 -1
  64. package/dist/ops/one.d.ts.map +1 -1
  65. package/dist/ops/remove.d.ts +1 -1
  66. package/dist/ops/remove.d.ts.map +1 -1
  67. package/dist/ops/reset.d.ts +1 -1
  68. package/dist/ops/reset.d.ts.map +1 -1
  69. package/dist/ops/retrieve.d.ts +1 -1
  70. package/dist/ops/retrieve.d.ts.map +1 -1
  71. package/dist/ops/set.d.ts +1 -1
  72. package/dist/ops/set.d.ts.map +1 -1
  73. package/dist/ops/update.d.ts +1 -1
  74. package/dist/ops/update.d.ts.map +1 -1
  75. package/dist/ttl/TTLCalculator.d.ts.map +1 -1
  76. package/dist/ttl/TTLConfig.d.ts.map +1 -1
  77. package/dist/ttl/TTLManager.d.ts.map +1 -1
  78. package/dist/utils/cacheInvalidation.d.ts +1 -1
  79. package/dist/utils/cacheInvalidation.d.ts.map +1 -1
  80. package/package.json +9 -7
package/dist/index.js CHANGED
@@ -1,15 +1,5 @@
1
1
  // src/Operations.ts
2
- import {
3
- createAllFacetWrapper as createAllFacetWrapper2,
4
- createAllWrapper as createAllWrapper2,
5
- createCreateWrapper as createCreateWrapper2,
6
- createGetWrapper as createGetWrapper2,
7
- createOneWrapper as createOneWrapper2,
8
- createRemoveWrapper as createRemoveWrapper2,
9
- createUpdateWrapper as createUpdateWrapper2,
10
- isOperationComKey as isComKey7,
11
- isOperationPriKey as isPriKey
12
- } from "@fjell/core";
2
+ import { createAllFacetWrapper as createAllFacetWrapper2, createAllWrapper as createAllWrapper2, createCreateWrapper as createCreateWrapper2, createGetWrapper as createGetWrapper2, createOneWrapper as createOneWrapper2, createRemoveWrapper as createRemoveWrapper2, createUpdateWrapper as createUpdateWrapper2, isComKey as isComKey8, isPriKey } from "@fjell/core";
13
3
 
14
4
  // src/logger.ts
15
5
  import Logging from "@fjell/logging";
@@ -606,7 +596,20 @@ var createQueryHash = (pkType, query, locations) => {
606
596
  };
607
597
  const hash = deterministicStringify(hashInput);
608
598
  if (!hash || typeof hash !== "string" || hash.trim() === "") {
609
- throw new Error(`Invalid query hash generated: hash is empty or invalid. Input: ${JSON.stringify({ pkType, query, locations })}`);
599
+ const errorContext = {
600
+ component: "cache",
601
+ subcomponent: "normalization",
602
+ operation: "createQueryHash",
603
+ pkType,
604
+ query: JSON.stringify(query),
605
+ locations: JSON.stringify(locations),
606
+ hashResult: hash,
607
+ suggestion: "This indicates a bug in query normalization. Check query and location structures."
608
+ };
609
+ console.error("Invalid query hash generated:", JSON.stringify(errorContext, null, 2));
610
+ throw new Error(
611
+ `Invalid query hash generated: hash is empty or invalid. Input: ${JSON.stringify({ pkType, query, locations })}. This indicates a bug in query normalization logic.`
612
+ );
610
613
  }
611
614
  return hash;
612
615
  };
@@ -866,10 +869,27 @@ async function executeAllLogic(query, locations, context, allOptions) {
866
869
  logger4.debug("Cache bypass enabled, fetching directly from API", { query, locations });
867
870
  try {
868
871
  const ret = await api.all(query, locations, allOptions);
869
- logger4.debug("API response received (not cached due to bypass)", { query, locations, itemCount: ret.items.length });
872
+ logger4.debug("API response received (not cached due to bypass)", {
873
+ operation: "all",
874
+ mode: "bypass",
875
+ query,
876
+ locations,
877
+ itemCount: ret.items.length,
878
+ metadata: ret.metadata
879
+ });
870
880
  return ret;
871
881
  } catch (error) {
872
- logger4.error("API request failed", { query, locations, error });
882
+ logger4.error("API request failed in bypass mode", {
883
+ operation: "all",
884
+ mode: "bypass",
885
+ query,
886
+ locations,
887
+ errorType: error.constructor?.name || typeof error,
888
+ errorMessage: error.message,
889
+ errorCode: error.code || error.errorInfo?.code,
890
+ suggestion: "Verify API endpoint is accessible, query syntax is correct, and locations are valid",
891
+ error
892
+ });
873
893
  throw error;
874
894
  }
875
895
  }
@@ -955,8 +975,15 @@ async function executeAllLogic(query, locations, context, allOptions) {
955
975
  }
956
976
  } catch (error) {
957
977
  logger4.debug("QUERY_CACHE: Error querying cache directly, proceeding to API", {
978
+ operation: "all",
979
+ phase: "cache-query",
958
980
  queryHash,
959
- error: error instanceof Error ? error.message : String(error)
981
+ query: JSON.stringify(query),
982
+ locations: JSON.stringify(locations),
983
+ errorType: error.constructor?.name || typeof error,
984
+ errorMessage: error instanceof Error ? error.message : String(error),
985
+ cacheType: cacheMap.implementationType,
986
+ note: "This is expected behavior - falling back to API when cache query fails"
960
987
  });
961
988
  }
962
989
  } else {
@@ -1031,9 +1058,19 @@ async function executeAllLogic(query, locations, context, allOptions) {
1031
1058
  await cacheMap.setQueryResult(queryHash, []);
1032
1059
  logger4.debug("QUERY_CACHE: Cached empty query result for not found", { queryHash });
1033
1060
  } else {
1034
- logger4.debug("QUERY_CACHE: API error occurred", {
1061
+ logger4.error("QUERY_CACHE: API error occurred during all() operation", {
1062
+ operation: "all",
1063
+ phase: "api-fetch",
1035
1064
  queryHash,
1036
- error: e instanceof Error ? e.message : String(e)
1065
+ query: JSON.stringify(query),
1066
+ locations: JSON.stringify(locations),
1067
+ errorType: e instanceof Error ? e.constructor.name : typeof e,
1068
+ errorMessage: e instanceof Error ? e.message : String(e),
1069
+ errorCode: e.code || e.errorInfo?.code,
1070
+ cacheType: cacheMap.implementationType,
1071
+ inFlightRequestsCount: inFlightRequests.size,
1072
+ suggestion: "Check API connectivity, query syntax, location keys, and network connectivity",
1073
+ error: e
1037
1074
  });
1038
1075
  throw e;
1039
1076
  }
@@ -1405,27 +1442,63 @@ var create = async (v, locations = [], context) => {
1405
1442
  return [context, result];
1406
1443
  };
1407
1444
  async function executeCreateLogic(v, locations, context) {
1445
+ const startTime = Date.now();
1408
1446
  const { api, cacheMap, pkType, eventEmitter, ttlManager, evictionManager } = context;
1409
- const created = await api.create(v, locations.length > 0 ? { locations } : void 0);
1410
- cacheMap.set(created.key, created);
1411
- const keyStr = JSON.stringify(created.key);
1412
- ttlManager.onItemAdded(keyStr, cacheMap);
1413
- const evictedKeys = await evictionManager.onItemAdded(keyStr, created, cacheMap);
1414
- for (const evictedKey of evictedKeys) {
1415
- const parsedKey = JSON.parse(evictedKey);
1416
- await cacheMap.delete(parsedKey);
1447
+ try {
1448
+ logger6.debug("CACHE_OP: create() started", {
1449
+ operation: "create",
1450
+ itemType: pkType,
1451
+ hasLocations: locations.length > 0,
1452
+ locationCount: locations.length,
1453
+ itemData: JSON.stringify(v)
1454
+ });
1455
+ const created = await api.create(v, locations.length > 0 ? { locations } : void 0);
1456
+ const apiDuration = Date.now() - startTime;
1457
+ cacheMap.set(created.key, created);
1458
+ const keyStr = JSON.stringify(created.key);
1459
+ ttlManager.onItemAdded(keyStr, cacheMap);
1460
+ const evictedKeys = await evictionManager.onItemAdded(keyStr, created, cacheMap);
1461
+ for (const evictedKey of evictedKeys) {
1462
+ const parsedKey = JSON.parse(evictedKey);
1463
+ await cacheMap.delete(parsedKey);
1464
+ }
1465
+ await cacheMap.clearQueryResults();
1466
+ const itemEvent = CacheEventFactory.itemCreated(created.key, created, "api");
1467
+ eventEmitter.emit(itemEvent);
1468
+ const queryInvalidatedEvent = CacheEventFactory.createQueryInvalidatedEvent(
1469
+ [],
1470
+ // We don't track which specific queries were invalidated
1471
+ "item_changed",
1472
+ { source: "operation", context: { operation: "create" } }
1473
+ );
1474
+ eventEmitter.emit(queryInvalidatedEvent);
1475
+ const totalDuration = Date.now() - startTime;
1476
+ logger6.debug("CACHE_OP: create() completed successfully", {
1477
+ operation: "create",
1478
+ itemType: pkType,
1479
+ key: keyStr,
1480
+ evictedCount: evictedKeys.length,
1481
+ apiDuration,
1482
+ totalDuration
1483
+ });
1484
+ return created;
1485
+ } catch (e) {
1486
+ const duration = Date.now() - startTime;
1487
+ logger6.error("CACHE_OP: create() operation failed", {
1488
+ operation: "create",
1489
+ itemType: pkType,
1490
+ itemData: JSON.stringify(v),
1491
+ locations: JSON.stringify(locations),
1492
+ duration,
1493
+ errorType: e.constructor?.name || typeof e,
1494
+ errorMessage: e.message,
1495
+ errorCode: e.code || e.errorInfo?.code,
1496
+ cacheType: cacheMap.implementationType,
1497
+ suggestion: "Check validation errors, duplicate constraints, required fields, and API connectivity",
1498
+ stack: e.stack
1499
+ });
1500
+ throw e;
1417
1501
  }
1418
- await cacheMap.clearQueryResults();
1419
- const itemEvent = CacheEventFactory.itemCreated(created.key, created, "api");
1420
- eventEmitter.emit(itemEvent);
1421
- const queryInvalidatedEvent = CacheEventFactory.createQueryInvalidatedEvent(
1422
- [],
1423
- // We don't track which specific queries were invalidated
1424
- "item_changed",
1425
- { source: "operation", context: { operation: "create" } }
1426
- );
1427
- eventEmitter.emit(queryInvalidatedEvent);
1428
- return created;
1429
1502
  }
1430
1503
 
1431
1504
  // src/ops/get.ts
@@ -1474,9 +1547,19 @@ async function executeGetLogic(key, context) {
1474
1547
  cacheType: cacheMap.implementationType
1475
1548
  });
1476
1549
  statsManager.incrementRequests();
1550
+ if (key === null) {
1551
+ throw new Error("Key cannot be null");
1552
+ }
1477
1553
  if (!isValidItemKey(key)) {
1478
- logger7.error("CACHE_OP: Invalid key for get", { key: keyStr });
1479
- throw new Error("Key for Get is not a valid ItemKey");
1554
+ logger7.error("CACHE_OP: Invalid key for get operation", {
1555
+ key: keyStr,
1556
+ keyType: typeof key,
1557
+ reason: "Key validation failed - must be a valid PriKey or ComKey",
1558
+ suggestion: "Ensure the key has the correct structure: PriKey { kt, pk } or ComKey { kt, sk, lk }",
1559
+ itemType: pkType,
1560
+ coordinate: JSON.stringify(context.coordinate)
1561
+ });
1562
+ throw new Error(`Invalid key for get operation: ${keyStr}. Expected valid PriKey or ComKey structure.`);
1480
1563
  }
1481
1564
  if (context.options?.bypassCache) {
1482
1565
  logger7.debug("CACHE_OP: Cache bypass enabled, fetching directly from API", { key: keyStr });
@@ -1501,8 +1584,15 @@ async function executeGetLogic(key, context) {
1501
1584
  }
1502
1585
  } catch (error) {
1503
1586
  logger7.error("CACHE_OP: API request failed in bypass mode", {
1587
+ operation: "get",
1588
+ mode: "bypass",
1504
1589
  key: keyStr,
1590
+ itemType: pkType,
1505
1591
  duration: Date.now() - startTime,
1592
+ errorType: error.constructor?.name || typeof error,
1593
+ errorMessage: error.message,
1594
+ errorCode: error.code || error.errorInfo?.code,
1595
+ suggestion: "Verify API endpoint is accessible and key exists. Cache bypass mode does not retry.",
1506
1596
  error
1507
1597
  });
1508
1598
  throw error;
@@ -1671,10 +1761,19 @@ async function executeGetLogic(key, context) {
1671
1761
  } catch (e) {
1672
1762
  inFlightRequests2.delete(requestKeyStr);
1673
1763
  const duration = Date.now() - startTime;
1674
- logger7.error("CACHE_OP: Error in get() operation", {
1764
+ logger7.error("CACHE_OP: get() operation failed", {
1765
+ operation: "get",
1675
1766
  key: keyStr,
1767
+ itemType: pkType,
1676
1768
  duration,
1677
- message: e.message,
1769
+ errorType: e.constructor?.name || typeof e,
1770
+ errorMessage: e.message,
1771
+ errorCode: e.code || e.errorInfo?.code,
1772
+ cacheType: cacheMap.implementationType,
1773
+ ttlEnabled: ttlManager.isTTLEnabled(),
1774
+ bypassMode: context.options?.bypassCache || false,
1775
+ inFlightRequestsCount: inFlightRequests2.size,
1776
+ suggestion: "Check API connectivity, key validity, and cache configuration",
1678
1777
  stack: e.stack
1679
1778
  });
1680
1779
  throw e;
@@ -1698,6 +1797,9 @@ var retrieve = async (key, context) => {
1698
1797
  bypassEnabled: !!context.options?.bypassCache
1699
1798
  });
1700
1799
  statsManager.incrementRequests();
1800
+ if (key === null) {
1801
+ throw new Error("Key cannot be null");
1802
+ }
1701
1803
  if (!isValidItemKey2(key)) {
1702
1804
  logger8.error("CACHE_OP: Invalid key for retrieve", { key: keyStr });
1703
1805
  throw new Error("Key for Retrieve is not a valid ItemKey");
@@ -1798,13 +1900,30 @@ var remove = async (key, context) => {
1798
1900
  };
1799
1901
  async function executeRemoveLogic(key, context) {
1800
1902
  const { api, cacheMap } = context;
1903
+ const keyStr = JSON.stringify(key);
1904
+ if (key === null) {
1905
+ throw new Error("Key cannot be null");
1906
+ }
1801
1907
  if (!isValidItemKey3(key)) {
1802
- logger9.error("Key for Remove is not a valid ItemKey: %j", key);
1803
- throw new Error("Key for Remove is not a valid ItemKey");
1908
+ logger9.error("CACHE_OP: Invalid key for remove operation", {
1909
+ operation: "remove",
1910
+ key: keyStr,
1911
+ keyType: typeof key,
1912
+ reason: "Key validation failed - must be a valid PriKey or ComKey",
1913
+ suggestion: "Ensure the key has the correct structure: PriKey { kt, pk } or ComKey { kt, sk, lk }"
1914
+ });
1915
+ throw new Error(`Invalid key for remove operation: ${keyStr}. Expected valid PriKey or ComKey structure.`);
1804
1916
  }
1917
+ const startTime = Date.now();
1805
1918
  try {
1919
+ logger9.debug("CACHE_OP: remove() started", {
1920
+ operation: "remove",
1921
+ key: keyStr,
1922
+ cacheType: cacheMap.implementationType
1923
+ });
1806
1924
  const previousItem = await cacheMap.get(key);
1807
1925
  await api.remove(key);
1926
+ const apiDuration = Date.now() - startTime;
1808
1927
  cacheMap.delete(key);
1809
1928
  await cacheMap.clearQueryResults();
1810
1929
  if (previousItem) {
@@ -1817,9 +1936,27 @@ async function executeRemoveLogic(key, context) {
1817
1936
  { source: "operation", context: { operation: "remove" } }
1818
1937
  );
1819
1938
  context.eventEmitter.emit(queryInvalidatedEvent);
1820
- logger9.debug("Successfully removed item from API and cache", { key });
1939
+ const totalDuration = Date.now() - startTime;
1940
+ logger9.debug("CACHE_OP: remove() completed successfully", {
1941
+ operation: "remove",
1942
+ key: keyStr,
1943
+ hadCachedItem: !!previousItem,
1944
+ apiDuration,
1945
+ totalDuration
1946
+ });
1821
1947
  } catch (e) {
1822
- logger9.error("Error deleting item", { error: e });
1948
+ const duration = Date.now() - startTime;
1949
+ logger9.error("CACHE_OP: remove() operation failed", {
1950
+ operation: "remove",
1951
+ key: keyStr,
1952
+ duration,
1953
+ errorType: e.constructor?.name || typeof e,
1954
+ errorMessage: e.message,
1955
+ errorCode: e.code || e.errorInfo?.code,
1956
+ cacheType: cacheMap.implementationType,
1957
+ suggestion: "Check item exists, delete permissions, referential integrity constraints, and API connectivity",
1958
+ stack: e.stack
1959
+ });
1823
1960
  throw e;
1824
1961
  }
1825
1962
  }
@@ -1844,34 +1981,56 @@ var update = async (key, v, context) => {
1844
1981
  };
1845
1982
  async function executeUpdateLogic(key, v, context) {
1846
1983
  const { api, cacheMap, pkType } = context;
1984
+ if (key === null) {
1985
+ throw new Error("Key cannot be null");
1986
+ }
1847
1987
  if (!isValidItemKey4(key)) {
1848
- logger10.error("Key for Update is not a valid ItemKey: %j", key);
1849
- throw new Error("Key for Update is not a valid ItemKey");
1988
+ logger10.error("CACHE_OP: Invalid key for update operation", {
1989
+ operation: "update",
1990
+ key: JSON.stringify(key),
1991
+ keyType: typeof key,
1992
+ itemType: pkType,
1993
+ reason: "Key validation failed - must be a valid PriKey or ComKey",
1994
+ suggestion: "Ensure the key has the correct structure: PriKey { kt, pk } or ComKey { kt, sk, lk }"
1995
+ });
1996
+ throw new Error(`Invalid key for update operation: ${JSON.stringify(key)}. Expected valid PriKey or ComKey structure.`);
1850
1997
  }
1851
1998
  logger10.debug("Invalidating item key before update", { key });
1852
1999
  cacheMap.invalidateItemKeys([key]);
1853
2000
  await cacheMap.clearQueryResults();
2001
+ const startTime = Date.now();
2002
+ const keyStr = JSON.stringify(key);
1854
2003
  try {
2004
+ logger10.debug("CACHE_OP: update() started", {
2005
+ operation: "update",
2006
+ key: keyStr,
2007
+ itemType: pkType,
2008
+ updateData: JSON.stringify(v)
2009
+ });
1855
2010
  const previousItem = await cacheMap.get(key);
1856
2011
  const updated = await api.update(key, v);
1857
- logger10.debug("Caching update result", { updatedKey: updated.key });
2012
+ const apiDuration = Date.now() - startTime;
2013
+ logger10.debug("CACHE_OP: Caching update result", {
2014
+ operation: "update",
2015
+ updatedKey: JSON.stringify(updated.key)
2016
+ });
1858
2017
  await cacheMap.set(updated.key, updated);
1859
2018
  const cachedItem = await cacheMap.get(updated.key);
1860
- const keyStr = JSON.stringify(updated.key);
1861
- const metadata = await cacheMap.getMetadata(keyStr);
2019
+ const updatedKeyStr = JSON.stringify(updated.key);
2020
+ const metadata = await cacheMap.getMetadata(updatedKeyStr);
1862
2021
  if (!metadata) {
1863
2022
  const now = Date.now();
1864
2023
  const baseMetadata = {
1865
- key: keyStr,
2024
+ key: updatedKeyStr,
1866
2025
  addedAt: now,
1867
2026
  lastAccessedAt: now,
1868
2027
  accessCount: 1,
1869
2028
  estimatedSize: estimateValueSize(updated)
1870
2029
  };
1871
- await cacheMap.setMetadata(keyStr, baseMetadata);
2030
+ await cacheMap.setMetadata(updatedKeyStr, baseMetadata);
1872
2031
  }
1873
- await context.ttlManager.onItemAdded(keyStr, cacheMap);
1874
- const evictedKeys = await context.evictionManager.onItemAdded(keyStr, updated, cacheMap);
2032
+ await context.ttlManager.onItemAdded(updatedKeyStr, cacheMap);
2033
+ const evictedKeys = await context.evictionManager.onItemAdded(updatedKeyStr, updated, cacheMap);
1875
2034
  for (const evictedKey of evictedKeys) {
1876
2035
  const parsedKey = JSON.parse(evictedKey);
1877
2036
  await cacheMap.delete(parsedKey);
@@ -1885,9 +2044,31 @@ async function executeUpdateLogic(key, v, context) {
1885
2044
  { source: "operation", context: { operation: "update" } }
1886
2045
  );
1887
2046
  context.eventEmitter.emit(queryInvalidatedEvent);
2047
+ const totalDuration = Date.now() - startTime;
2048
+ logger10.debug("CACHE_OP: update() completed successfully", {
2049
+ operation: "update",
2050
+ key: updatedKeyStr,
2051
+ itemType: pkType,
2052
+ evictedCount: evictedKeys.length,
2053
+ apiDuration,
2054
+ totalDuration
2055
+ });
1888
2056
  return updated;
1889
2057
  } catch (e) {
1890
- logger10.error("Error updating item", { error: e });
2058
+ const duration = Date.now() - startTime;
2059
+ logger10.error("CACHE_OP: update() operation failed", {
2060
+ operation: "update",
2061
+ key: keyStr,
2062
+ itemType: pkType,
2063
+ updateData: JSON.stringify(v),
2064
+ duration,
2065
+ errorType: e.constructor?.name || typeof e,
2066
+ errorMessage: e.message,
2067
+ errorCode: e.code || e.errorInfo?.code,
2068
+ cacheType: cacheMap.implementationType,
2069
+ suggestion: "Check item exists, validation rules, update permissions, and API connectivity",
2070
+ stack: e.stack
2071
+ });
1891
2072
  throw e;
1892
2073
  }
1893
2074
  }
@@ -1899,7 +2080,7 @@ import {
1899
2080
  } from "@fjell/core";
1900
2081
 
1901
2082
  // src/utils/cacheInvalidation.ts
1902
- import { toKeyTypeArray } from "@fjell/core";
2083
+ import { isComKey, toKeyTypeArray } from "@fjell/core";
1903
2084
  var logger11 = logger_default.get("cache", "utils", "cacheInvalidation");
1904
2085
  var extractKeysAndKeyTypesFromActionResult = (affectedItems) => {
1905
2086
  const keys = [];
@@ -1923,7 +2104,7 @@ var invalidateCachesByKeysAndKeyTypes = async (registry, keys, keyTypeArrays) =>
1923
2104
  });
1924
2105
  const keysByKeyTypes = /* @__PURE__ */ new Map();
1925
2106
  for (const key of keys) {
1926
- const keyTypes = "loc" in key ? [key.kt, ...key.loc.map((locKey) => locKey.kt)] : [key.kt];
2107
+ const keyTypes = isComKey(key) ? [key.kt, ...key.loc.map((locKey) => locKey.kt)] : [key.kt];
1927
2108
  const keyTypesKey = keyTypes.join("|");
1928
2109
  if (!keysByKeyTypes.has(keyTypesKey)) {
1929
2110
  keysByKeyTypes.set(keyTypesKey, []);
@@ -1999,6 +2180,9 @@ var action = async (key, action2, body = {}, context) => {
1999
2180
  };
2000
2181
  async function executeActionLogic(key, action2, body, context) {
2001
2182
  const { api, cacheMap, pkType, registry } = context;
2183
+ if (key === null) {
2184
+ throw new Error("Key cannot be null");
2185
+ }
2002
2186
  if (!isValidItemKey5(key)) {
2003
2187
  logger12.error("Key for Action is not a valid ItemKey: %j", key);
2004
2188
  throw new Error("Key for Action is not a valid ItemKey");
@@ -2585,14 +2769,19 @@ var normalizeKey = (key) => {
2585
2769
  return key;
2586
2770
  };
2587
2771
  var set = async (key, v, context) => {
2772
+ if (key === null) {
2773
+ throw new Error("Key cannot be null");
2774
+ }
2775
+ if (typeof key === "undefined") {
2776
+ throw new Error("Key for Set is not a valid ItemKey");
2777
+ }
2588
2778
  const startTime = Date.now();
2589
2779
  const { cacheMap, pkType, ttlManager, evictionManager, eventEmitter } = context;
2590
2780
  const keyStr = JSON.stringify(key);
2781
+ if (v === null || typeof v === "undefined") {
2782
+ throw new Error("Item cannot be null");
2783
+ }
2591
2784
  logger18.default("set", { key, v });
2592
- logger18.debug("CACHE_OP: set() started", {
2593
- key: keyStr,
2594
- cacheType: cacheMap.implementationType
2595
- });
2596
2785
  if (!isValidItemKey6(key)) {
2597
2786
  logger18.error("CACHE_OP: Invalid key for set", { key: keyStr });
2598
2787
  throw new Error("Key for Set is not a valid ItemKey");
@@ -2677,7 +2866,7 @@ var set = async (key, v, context) => {
2677
2866
 
2678
2867
  // src/memory/MemoryCacheMap.ts
2679
2868
  import {
2680
- isComKey,
2869
+ isComKey as isComKey2,
2681
2870
  isQueryMatch
2682
2871
  } from "@fjell/core";
2683
2872
  var logger19 = logger_default.get("MemoryCacheMap");
@@ -2781,7 +2970,7 @@ var MemoryCacheMap = class _MemoryCacheMap extends CacheMap {
2781
2970
  logger19.debug("allIn", { locations, count: allValues.length });
2782
2971
  return allValues.filter((item) => {
2783
2972
  const key = item.key;
2784
- if (key && isComKey(key)) {
2973
+ if (key && isComKey2(key)) {
2785
2974
  const comKey = key;
2786
2975
  return isLocKeyArrayEqual(locations, comKey.loc);
2787
2976
  }
@@ -2897,7 +3086,7 @@ var MemoryCacheMap = class _MemoryCacheMap extends CacheMap {
2897
3086
  let keysToInvalidate = [];
2898
3087
  if (locations.length === 0) {
2899
3088
  const allKeys = await this.keys();
2900
- const primaryKeys = allKeys.filter((key) => !isComKey(key));
3089
+ const primaryKeys = allKeys.filter((key) => !isComKey2(key));
2901
3090
  keysToInvalidate = primaryKeys;
2902
3091
  } else {
2903
3092
  const itemsInLocation = await this.allIn(locations);
@@ -2945,7 +3134,7 @@ var MemoryCacheMap = class _MemoryCacheMap extends CacheMap {
2945
3134
 
2946
3135
  // src/memory/EnhancedMemoryCacheMap.ts
2947
3136
  import {
2948
- isComKey as isComKey2,
3137
+ isComKey as isComKey3,
2949
3138
  isQueryMatch as isQueryMatch2
2950
3139
  } from "@fjell/core";
2951
3140
  var logger20 = logger_default.get("EnhancedMemoryCacheMap");
@@ -3089,7 +3278,7 @@ var EnhancedMemoryCacheMap = class _EnhancedMemoryCacheMap extends CacheMap {
3089
3278
  logger20.debug("allIn", { locations, count: allValues.length });
3090
3279
  return allValues.filter((item) => {
3091
3280
  const key = item.key;
3092
- if (key && isComKey2(key)) {
3281
+ if (key && isComKey3(key)) {
3093
3282
  return isLocKeyArrayEqual(locations, key.loc);
3094
3283
  }
3095
3284
  return false;
@@ -3249,7 +3438,7 @@ var EnhancedMemoryCacheMap = class _EnhancedMemoryCacheMap extends CacheMap {
3249
3438
  let keysToInvalidate = [];
3250
3439
  if (locations.length === 0) {
3251
3440
  const allKeys = await this.keys();
3252
- const primaryKeys = allKeys.filter((key) => !isComKey2(key));
3441
+ const primaryKeys = allKeys.filter((key) => !isComKey3(key));
3253
3442
  keysToInvalidate = primaryKeys;
3254
3443
  } else {
3255
3444
  const itemsInLocation = await this.allIn(locations);
@@ -3363,7 +3552,7 @@ var EnhancedMemoryCacheMap = class _EnhancedMemoryCacheMap extends CacheMap {
3363
3552
 
3364
3553
  // src/browser/LocalStorageCacheMap.ts
3365
3554
  import {
3366
- isComKey as isComKey3,
3555
+ isComKey as isComKey4,
3367
3556
  isQueryMatch as isQueryMatch3
3368
3557
  } from "@fjell/core";
3369
3558
  var logger21 = logger_default.get("LocalStorageCacheMap");
@@ -3524,7 +3713,17 @@ var LocalStorageCacheMap = class _LocalStorageCacheMap extends CacheMap {
3524
3713
  const useAggressiveCleanup = attempt > 0;
3525
3714
  this.tryCleanupOldEntries(useAggressiveCleanup);
3526
3715
  if (isLastAttempt) {
3527
- throw new Error("Failed to store item in localStorage: storage quota exceeded even after multiple cleanup attempts");
3716
+ logger21.error("LocalStorage quota exceeded after all cleanup attempts", {
3717
+ component: "cache",
3718
+ subcomponent: "LocalStorageCacheMap",
3719
+ operation: "set",
3720
+ key: JSON.stringify(key),
3721
+ retryAttempts: attempt + 1,
3722
+ suggestion: "Reduce cache size limits, clear more data, or use IndexedDB for larger storage needs"
3723
+ });
3724
+ throw new Error(
3725
+ "Failed to store item in localStorage: storage quota exceeded even after multiple cleanup attempts. Suggestion: Reduce maxItems in memoryConfig, clear old data, or switch to IndexedDB for larger storage."
3726
+ );
3528
3727
  }
3529
3728
  continue;
3530
3729
  }
@@ -3577,13 +3776,13 @@ var LocalStorageCacheMap = class _LocalStorageCacheMap extends CacheMap {
3577
3776
  const locKeys = locations;
3578
3777
  const resolvedKeys = await allKeys;
3579
3778
  logger21.debug("allIn", { locKeys, keys: resolvedKeys.length });
3580
- const filteredKeys = resolvedKeys.filter((key) => key && isComKey3(key)).filter((key) => {
3581
- const ComKey16 = key;
3779
+ const filteredKeys = resolvedKeys.filter((key) => key && isComKey4(key)).filter((key) => {
3780
+ const ComKey = key;
3582
3781
  logger21.debug("Comparing Location Keys", {
3583
3782
  locKeys,
3584
- ComKey: ComKey16
3783
+ ComKey
3585
3784
  });
3586
- return isLocKeyArrayEqual(locKeys, ComKey16.loc);
3785
+ return isLocKeyArrayEqual(locKeys, ComKey.loc);
3587
3786
  });
3588
3787
  const items = [];
3589
3788
  for (const key of filteredKeys) {
@@ -3665,8 +3864,18 @@ var LocalStorageCacheMap = class _LocalStorageCacheMap extends CacheMap {
3665
3864
  async setQueryResult(queryHash, itemKeys, metadata) {
3666
3865
  logger21.trace("setQueryResult", { queryHash, itemKeys, hasMetadata: !!metadata });
3667
3866
  if (!queryHash || typeof queryHash !== "string" || queryHash.trim() === "") {
3668
- logger21.error("Invalid queryHash provided to setQueryResult", { queryHash, itemKeys });
3669
- throw new Error(`Invalid queryHash: ${JSON.stringify(queryHash)}`);
3867
+ logger21.error("Invalid queryHash provided to setQueryResult", {
3868
+ component: "cache",
3869
+ subcomponent: "LocalStorageCacheMap",
3870
+ operation: "setQueryResult",
3871
+ queryHash,
3872
+ queryHashType: typeof queryHash,
3873
+ itemKeys,
3874
+ suggestion: "Ensure queryHash is a non-empty string generated from query normalization"
3875
+ });
3876
+ throw new Error(
3877
+ `Invalid queryHash provided to setQueryResult: ${JSON.stringify(queryHash)}. Expected non-empty string, got ${typeof queryHash}. This usually indicates a bug in query hash generation.`
3878
+ );
3670
3879
  }
3671
3880
  const queryKey = `${this.keyPrefix}:query:${queryHash}`;
3672
3881
  const entry = {
@@ -3820,7 +4029,7 @@ var LocalStorageCacheMap = class _LocalStorageCacheMap extends CacheMap {
3820
4029
  let keysToInvalidate = [];
3821
4030
  if (locations.length === 0) {
3822
4031
  const allKeys = await this.keys();
3823
- const primaryKeys = allKeys.filter((key) => !isComKey3(key));
4032
+ const primaryKeys = allKeys.filter((key) => !isComKey4(key));
3824
4033
  keysToInvalidate = primaryKeys;
3825
4034
  } else {
3826
4035
  const itemsInLocation = await this.allIn(locations);
@@ -3985,7 +4194,7 @@ var LocalStorageCacheMap = class _LocalStorageCacheMap extends CacheMap {
3985
4194
 
3986
4195
  // src/browser/SessionStorageCacheMap.ts
3987
4196
  import {
3988
- isComKey as isComKey4,
4197
+ isComKey as isComKey5,
3989
4198
  isQueryMatch as isQueryMatch4
3990
4199
  } from "@fjell/core";
3991
4200
  import safeStringify2 from "fast-safe-stringify";
@@ -4081,8 +4290,19 @@ var SessionStorageCacheMap = class _SessionStorageCacheMap extends CacheMap {
4081
4290
  const jsonString = safeStringify2(toStore);
4082
4291
  sessionStorage.setItem(storageKey, jsonString);
4083
4292
  } catch (error) {
4084
- logger22.error("Error storing to sessionStorage", { errorMessage: error?.message });
4085
- throw new Error(`Failed to store item in sessionStorage: ${error}`);
4293
+ const isQuotaError = error?.name === "QuotaExceededError" || error?.message?.includes("quota") || error?.code === 22;
4294
+ logger22.error("Error storing to sessionStorage", {
4295
+ component: "cache",
4296
+ subcomponent: "SessionStorageCacheMap",
4297
+ operation: "set",
4298
+ key: JSON.stringify(key),
4299
+ errorType: error?.name,
4300
+ errorMessage: error?.message,
4301
+ isQuotaError,
4302
+ suggestion: isQuotaError ? "SessionStorage quota exceeded. Clear old data, reduce cache size, or use IndexedDB instead." : "Check browser sessionStorage support and data serializability."
4303
+ });
4304
+ const errorMsg = isQuotaError ? "SessionStorage quota exceeded. Try clearing old cache data or reducing cache size." : `Failed to store item in sessionStorage: ${error?.message || error}`;
4305
+ throw new Error(errorMsg);
4086
4306
  }
4087
4307
  }
4088
4308
  async includesKey(key) {
@@ -4131,13 +4351,13 @@ var SessionStorageCacheMap = class _SessionStorageCacheMap extends CacheMap {
4131
4351
  const locKeys = locations;
4132
4352
  const resolvedKeys = await allKeys;
4133
4353
  logger22.debug("allIn", { locKeys, keys: resolvedKeys.length });
4134
- const filteredKeys = resolvedKeys.filter((key) => key && isComKey4(key)).filter((key) => {
4135
- const ComKey16 = key;
4354
+ const filteredKeys = resolvedKeys.filter((key) => key && isComKey5(key)).filter((key) => {
4355
+ const ComKey = key;
4136
4356
  logger22.debug("Comparing Location Keys", {
4137
4357
  locKeys,
4138
- ComKey: ComKey16
4358
+ ComKey
4139
4359
  });
4140
- return isLocKeyArrayEqual(locKeys, ComKey16.loc);
4360
+ return isLocKeyArrayEqual(locKeys, ComKey.loc);
4141
4361
  });
4142
4362
  const items = [];
4143
4363
  for (const key of filteredKeys) {
@@ -4460,7 +4680,7 @@ var SessionStorageCacheMap = class _SessionStorageCacheMap extends CacheMap {
4460
4680
  let keysToInvalidate = [];
4461
4681
  if (locations.length === 0) {
4462
4682
  const allKeys = await this.keys();
4463
- const primaryKeys = allKeys.filter((key) => !isComKey4(key));
4683
+ const primaryKeys = allKeys.filter((key) => !isComKey5(key));
4464
4684
  keysToInvalidate = primaryKeys;
4465
4685
  } else {
4466
4686
  const itemsInLocation = await this.allIn(locations);
@@ -4512,13 +4732,13 @@ var SessionStorageCacheMap = class _SessionStorageCacheMap extends CacheMap {
4512
4732
 
4513
4733
  // src/browser/IndexDBCacheMap.ts
4514
4734
  import {
4515
- isComKey as isComKey6,
4735
+ isComKey as isComKey7,
4516
4736
  isQueryMatch as isQueryMatch6
4517
4737
  } from "@fjell/core";
4518
4738
 
4519
4739
  // src/browser/AsyncIndexDBCacheMap.ts
4520
4740
  import {
4521
- isComKey as isComKey5,
4741
+ isComKey as isComKey6,
4522
4742
  isQueryMatch as isQueryMatch5
4523
4743
  } from "@fjell/core";
4524
4744
  import safeStringify3 from "fast-safe-stringify";
@@ -4667,8 +4887,18 @@ var AsyncIndexDBCacheMap = class _AsyncIndexDBCacheMap {
4667
4887
  try {
4668
4888
  storageKey = this.getStorageKey(key);
4669
4889
  } catch (keyError) {
4670
- logger23.debug("Storage key generation failed during set, throwing error", { key, error: keyError });
4671
- throw new Error(`Failed to generate storage key: ${keyError}`);
4890
+ logger23.error("Storage key generation failed", {
4891
+ component: "cache",
4892
+ subcomponent: "AsyncIndexDBCacheMap",
4893
+ operation: "set",
4894
+ key: JSON.stringify(key),
4895
+ errorType: keyError?.constructor?.name,
4896
+ errorMessage: keyError?.message,
4897
+ suggestion: "Check key structure and normalization logic"
4898
+ });
4899
+ throw new Error(
4900
+ `Failed to generate storage key for IndexedDB: ${keyError?.message || keyError}. Key: ${JSON.stringify(key)}. This indicates a key normalization issue.`
4901
+ );
4672
4902
  }
4673
4903
  const storedItem = {
4674
4904
  originalKey: key,
@@ -4692,8 +4922,19 @@ var AsyncIndexDBCacheMap = class _AsyncIndexDBCacheMap {
4692
4922
  }
4693
4923
  });
4694
4924
  } catch (error) {
4695
- logger23.error("Error in IndexedDB set operation", { key, value, error });
4696
- throw new Error(`Failed to store item in IndexedDB: ${error}`);
4925
+ const isQuotaError = error?.name === "QuotaExceededError" || error?.message?.includes("quota");
4926
+ logger23.error("Error in IndexedDB set operation", {
4927
+ component: "cache",
4928
+ subcomponent: "AsyncIndexDBCacheMap",
4929
+ operation: "set",
4930
+ key: JSON.stringify(key),
4931
+ errorType: error?.name,
4932
+ errorMessage: error?.message,
4933
+ isQuotaError,
4934
+ suggestion: isQuotaError ? "IndexedDB quota exceeded. Clear old data, reduce cache size, or request more storage quota." : "Check IndexedDB support, permissions, and data serializability."
4935
+ });
4936
+ const errorMsg = isQuotaError ? "IndexedDB quota exceeded. Try clearing old cache data or reducing cache size." : `Failed to store item in IndexedDB: ${error?.message || error}`;
4937
+ throw new Error(errorMsg);
4697
4938
  }
4698
4939
  }
4699
4940
  /**
@@ -4793,13 +5034,13 @@ var AsyncIndexDBCacheMap = class _AsyncIndexDBCacheMap {
4793
5034
  } else {
4794
5035
  const locKeys = locations;
4795
5036
  logger23.debug("allIn", { locKeys, keys: allKeys.length });
4796
- const filteredKeys = allKeys.filter((key) => key && isComKey5(key)).filter((key) => {
4797
- const ComKey16 = key;
5037
+ const filteredKeys = allKeys.filter((key) => key && isComKey6(key)).filter((key) => {
5038
+ const ComKey = key;
4798
5039
  logger23.debug("Comparing Location Keys", {
4799
5040
  locKeys,
4800
- ComKey: ComKey16
5041
+ ComKey
4801
5042
  });
4802
- return isLocKeyArrayEqual(locKeys, ComKey16.loc);
5043
+ return isLocKeyArrayEqual(locKeys, ComKey.loc);
4803
5044
  });
4804
5045
  const promises = filteredKeys.map((key) => this.get(key));
4805
5046
  const results = await Promise.all(promises);
@@ -5412,7 +5653,7 @@ var IndexDBCacheMap = class _IndexDBCacheMap extends CacheMap {
5412
5653
  const key = entry.originalKey;
5413
5654
  if (locations.length === 0) {
5414
5655
  result.push(entry.value);
5415
- } else if (isComKey6(key)) {
5656
+ } else if (isComKey7(key)) {
5416
5657
  if (isLocKeyArrayEqual(key.loc, locations)) {
5417
5658
  result.push(entry.value);
5418
5659
  }
@@ -5514,7 +5755,7 @@ var IndexDBCacheMap = class _IndexDBCacheMap extends CacheMap {
5514
5755
  const itemsToDelete = [];
5515
5756
  for (const entry of Object.values(this.memoryMap)) {
5516
5757
  const key = entry.originalKey;
5517
- if (isComKey6(key) && isLocKeyArrayEqual(key.loc, locations)) {
5758
+ if (isComKey7(key) && isLocKeyArrayEqual(key.loc, locations)) {
5518
5759
  itemsToDelete.push(key);
5519
5760
  }
5520
5761
  }
@@ -5573,6 +5814,7 @@ var IndexDBCacheMap = class _IndexDBCacheMap extends CacheMap {
5573
5814
  };
5574
5815
 
5575
5816
  // src/Options.ts
5817
+ var logger25 = logger_default.get("Options");
5576
5818
  var DEFAULT_CACHE_OPTIONS = {
5577
5819
  cacheType: "memory",
5578
5820
  enableDebugLogging: false,
@@ -5676,12 +5918,29 @@ var createCacheMap = (kta, options) => {
5676
5918
  break;
5677
5919
  case "custom":
5678
5920
  if (!options.customCacheMapFactory) {
5679
- throw new Error('Custom cache map factory is required when cacheType is "custom"');
5921
+ logger25.error("Custom cache map factory missing", {
5922
+ component: "cache",
5923
+ operation: "createCacheMap",
5924
+ cacheType: "custom",
5925
+ suggestion: 'Provide customCacheMapFactory function in cache options when using cacheType: "custom"'
5926
+ });
5927
+ throw new Error(
5928
+ 'Custom cache map factory is required when cacheType is "custom". Provide customCacheMapFactory in cache options.'
5929
+ );
5680
5930
  }
5681
5931
  underlyingCache = options.customCacheMapFactory(kta);
5682
5932
  break;
5683
5933
  default:
5684
- throw new Error(`Unsupported cache type: ${options.cacheType}`);
5934
+ logger25.error("Unsupported cache type", {
5935
+ component: "cache",
5936
+ operation: "createCacheMap",
5937
+ cacheType: options.cacheType,
5938
+ validTypes: ["memory", "localStorage", "sessionStorage", "indexedDB", "asyncIndexedDB", "custom"],
5939
+ suggestion: "Use one of: memory, localStorage, sessionStorage, indexedDB, asyncIndexedDB, or custom"
5940
+ });
5941
+ throw new Error(
5942
+ `Unsupported cache type: ${options.cacheType}. Valid types: memory, localStorage, sessionStorage, indexedDB, asyncIndexedDB, custom.`
5943
+ );
5685
5944
  }
5686
5945
  if (options.twoLayer && Object.keys(options.twoLayer).length > 0) {
5687
5946
  return new TwoLayerCacheMap(underlyingCache, options.twoLayer);
@@ -5762,19 +6021,29 @@ Did you mean: ${suggestions.join(", ")}?`;
5762
6021
  throw new Error(errorMessage);
5763
6022
  }
5764
6023
  if (options.cacheType === "custom" && !options.customCacheMapFactory) {
5765
- throw new Error('customCacheMapFactory is required when cacheType is "custom"');
6024
+ throw new Error(
6025
+ 'customCacheMapFactory is required when cacheType is "custom". Provide a factory function that creates your custom CacheMap implementation.'
6026
+ );
5766
6027
  }
5767
6028
  if (typeof options.maxRetries === "number" && options.maxRetries < 0) {
5768
- throw new Error("maxRetries must be non-negative");
6029
+ throw new Error(
6030
+ `maxRetries must be non-negative, got ${options.maxRetries}. Suggestion: Use 0 or positive integer for retry attempts.`
6031
+ );
5769
6032
  }
5770
6033
  if (typeof options.retryDelay === "number" && options.retryDelay < 0) {
5771
- throw new Error("retryDelay must be non-negative");
6034
+ throw new Error(
6035
+ `retryDelay must be non-negative, got ${options.retryDelay}ms. Suggestion: Use 0 or positive number for delay in milliseconds.`
6036
+ );
5772
6037
  }
5773
6038
  if (typeof options.ttl === "number" && options.ttl <= 0) {
5774
- throw new Error("ttl must be positive");
6039
+ throw new Error(
6040
+ `ttl must be positive, got ${options.ttl}. Suggestion: Use positive number for TTL in seconds, or 0 to disable TTL.`
6041
+ );
5775
6042
  }
5776
6043
  if (typeof options.memoryConfig?.maxItems === "number" && options.memoryConfig.maxItems <= 0) {
5777
- throw new Error("memoryConfig.maxItems must be positive");
6044
+ throw new Error(
6045
+ `memoryConfig.maxItems must be positive, got ${options.memoryConfig.maxItems}. Suggestion: Use positive integer for maximum cache items.`
6046
+ );
5778
6047
  }
5779
6048
  if (options.memoryConfig?.size) {
5780
6049
  validateSizeConfig(options.memoryConfig.size);
@@ -5874,16 +6143,43 @@ Did you mean: ${suggestions.join(", ")}?`);
5874
6143
  if (["localStorage", "sessionStorage"].includes(options.cacheType)) {
5875
6144
  const isRealBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement === "function";
5876
6145
  if (!isRealBrowser) {
5877
- throw new Error(`${options.cacheType} is not available in non-browser environments`);
6146
+ logger25.error("Browser cache type used in non-browser environment", {
6147
+ component: "cache",
6148
+ operation: "validateOptions",
6149
+ cacheType: options.cacheType,
6150
+ environment: typeof window === "undefined" ? "node" : "unknown",
6151
+ suggestion: 'Use cacheType: "memory" for Node.js/server environments, or ensure code runs in browser'
6152
+ });
6153
+ throw new Error(
6154
+ `${options.cacheType} is not available in non-browser environments. Detected environment: ${typeof window === "undefined" ? "Node.js/server" : "non-browser"}. Suggestion: Use cacheType: "memory" for server-side caching.`
6155
+ );
5878
6156
  }
5879
6157
  }
5880
6158
  if (options.cacheType === "indexedDB") {
5881
6159
  if (typeof window === "undefined" || !window.indexedDB) {
5882
- throw new Error(`${options.cacheType} is not available in this environment`);
6160
+ logger25.error("IndexedDB not available", {
6161
+ component: "cache",
6162
+ operation: "validateOptions",
6163
+ cacheType: "indexedDB",
6164
+ hasWindow: typeof window !== "undefined",
6165
+ hasIndexedDB: typeof window !== "undefined" && !!window.indexedDB,
6166
+ suggestion: "Use memory cache for Node.js, or check browser IndexedDB support"
6167
+ });
6168
+ throw new Error(
6169
+ `IndexedDB is not available in this environment. Browser support required. Suggestion: Use cacheType: "memory" for server-side or unsupported browsers.`
6170
+ );
5883
6171
  }
5884
6172
  }
5885
6173
  if (options.cacheType === "asyncIndexedDB") {
5886
- throw new Error("asyncIndexedDB cannot be used with synchronous cache factory. Use AsyncIndexDBCacheMap directly for async operations.");
6174
+ logger25.error("AsyncIndexedDB cannot be used with sync factory", {
6175
+ component: "cache",
6176
+ operation: "validateOptions",
6177
+ cacheType: "asyncIndexedDB",
6178
+ suggestion: 'Use AsyncIndexDBCacheMap directly for async operations, or use cacheType: "indexedDB" for sync wrapper'
6179
+ });
6180
+ throw new Error(
6181
+ 'asyncIndexedDB cannot be used with synchronous cache factory. Use AsyncIndexDBCacheMap directly for async operations, or use cacheType: "indexedDB" for the sync wrapper.'
6182
+ );
5887
6183
  }
5888
6184
  };
5889
6185
 
@@ -5898,7 +6194,11 @@ var reset = async (coordinate, options) => {
5898
6194
  }
5899
6195
  };
5900
6196
 
6197
+ // src/ttl/TTLCalculator.ts
6198
+ var logger26 = logger_default.get("TTLCalculator");
6199
+
5901
6200
  // src/ttl/TTLConfig.ts
6201
+ var logger27 = logger_default.get("TTLConfig");
5902
6202
  var defaultTTLConfig = {
5903
6203
  item: {
5904
6204
  default: 3600,
@@ -5997,10 +6297,10 @@ var highTrafficTTLConfig = {
5997
6297
  };
5998
6298
 
5999
6299
  // src/cache/warming/CacheWarmer.ts
6000
- var logger25 = logger_default.get("CacheWarmer");
6300
+ var logger28 = logger_default.get("CacheWarmer");
6001
6301
 
6002
6302
  // src/Operations.ts
6003
- var logger26 = logger_default.get("Operations");
6303
+ var logger29 = logger_default.get("Operations");
6004
6304
  var CacheMapOperations = class {
6005
6305
  constructor(api, coordinate, cacheMap, pkType, options, eventEmitter, ttlManager, evictionManager, statsManager, registry) {
6006
6306
  this.api = api;
@@ -6014,7 +6314,7 @@ var CacheMapOperations = class {
6014
6314
  this.statsManager = statsManager;
6015
6315
  this.registry = registry;
6016
6316
  if (this.options.enableDebugLogging) {
6017
- logger26.debug("CacheMapOperations initialized", {
6317
+ logger29.debug("CacheMapOperations initialized", {
6018
6318
  cacheType: this.cacheMap.implementationType,
6019
6319
  isTwoLayer: this.cacheMap instanceof TwoLayerCacheMap
6020
6320
  });
@@ -6107,7 +6407,7 @@ var createOperations = (api, coordinate, cacheMap, pkType, options, eventEmitter
6107
6407
  };
6108
6408
 
6109
6409
  // src/eviction/EvictionManager.ts
6110
- var logger27 = logger_default.get("EvictionManager");
6410
+ var logger30 = logger_default.get("EvictionManager");
6111
6411
  var EvictionManager = class {
6112
6412
  evictionStrategy;
6113
6413
  constructor(evictionStrategy) {
@@ -6119,7 +6419,7 @@ var EvictionManager = class {
6119
6419
  */
6120
6420
  setEvictionStrategy(strategy) {
6121
6421
  this.evictionStrategy = strategy;
6122
- logger27.debug("Eviction strategy updated", {
6422
+ logger30.debug("Eviction strategy updated", {
6123
6423
  strategy: strategy?.getStrategyName() || "none"
6124
6424
  });
6125
6425
  }
@@ -6140,13 +6440,13 @@ var EvictionManager = class {
6140
6440
  return;
6141
6441
  }
6142
6442
  try {
6143
- logger27.debug("EVICTION: Item accessed, updating metadata", {
6443
+ logger30.debug("EVICTION: Item accessed, updating metadata", {
6144
6444
  key,
6145
6445
  strategy: this.evictionStrategy.getStrategyName()
6146
6446
  });
6147
6447
  await this.evictionStrategy.onItemAccessed(key, metadataProvider);
6148
6448
  } catch (error) {
6149
- logger27.error("EVICTION: Error in eviction strategy onItemAccessed", {
6449
+ logger30.error("EVICTION: Error in eviction strategy onItemAccessed", {
6150
6450
  key,
6151
6451
  error,
6152
6452
  strategy: this.evictionStrategy?.getStrategyName()
@@ -6164,12 +6464,12 @@ var EvictionManager = class {
6164
6464
  const startTime = Date.now();
6165
6465
  const evictedKeys = [];
6166
6466
  if (!this.evictionStrategy) {
6167
- logger27.debug("EVICTION: No eviction strategy configured", { key });
6467
+ logger30.debug("EVICTION: No eviction strategy configured", { key });
6168
6468
  return evictedKeys;
6169
6469
  }
6170
6470
  try {
6171
6471
  const estimatedSize = estimateValueSize(value);
6172
- logger27.debug("EVICTION: Item addition started", {
6472
+ logger30.debug("EVICTION: Item addition started", {
6173
6473
  key,
6174
6474
  estimatedSize,
6175
6475
  strategy: this.evictionStrategy.getStrategyName()
@@ -6177,7 +6477,7 @@ var EvictionManager = class {
6177
6477
  const contextStartTime = Date.now();
6178
6478
  const context = await this.createEvictionContext(metadataProvider, estimatedSize);
6179
6479
  const contextDuration = Date.now() - contextStartTime;
6180
- logger27.debug("EVICTION: Current cache state", {
6480
+ logger30.debug("EVICTION: Current cache state", {
6181
6481
  key,
6182
6482
  currentItemCount: context.currentSize.itemCount,
6183
6483
  currentSizeBytes: context.currentSize.sizeBytes,
@@ -6190,7 +6490,7 @@ var EvictionManager = class {
6190
6490
  const keysToEvict = await this.evictionStrategy.selectForEviction(metadataProvider, context);
6191
6491
  const selectionDuration = Date.now() - selectionStartTime;
6192
6492
  if (keysToEvict.length > 0) {
6193
- logger27.debug("EVICTION: Items selected for eviction", {
6493
+ logger30.debug("EVICTION: Items selected for eviction", {
6194
6494
  key,
6195
6495
  evictCount: keysToEvict.length,
6196
6496
  keysToEvict,
@@ -6202,7 +6502,7 @@ var EvictionManager = class {
6202
6502
  for (const evictKey of keysToEvict) {
6203
6503
  await this.evictionStrategy.onItemRemoved(evictKey, metadataProvider);
6204
6504
  evictedKeys.push(evictKey);
6205
- logger27.debug("EVICTION: Marked item for eviction", {
6505
+ logger30.debug("EVICTION: Marked item for eviction", {
6206
6506
  evictedKey: evictKey,
6207
6507
  newKey: key
6208
6508
  });
@@ -6213,7 +6513,7 @@ var EvictionManager = class {
6213
6513
  const addMetadataDuration = Date.now() - addMetadataStart;
6214
6514
  const totalDuration = Date.now() - startTime;
6215
6515
  if (evictedKeys.length > 0) {
6216
- logger27.debug("EVICTION: Eviction completed", {
6516
+ logger30.debug("EVICTION: Eviction completed", {
6217
6517
  newKey: key,
6218
6518
  evictedCount: evictedKeys.length,
6219
6519
  evictedKeys,
@@ -6224,14 +6524,14 @@ var EvictionManager = class {
6224
6524
  totalDuration
6225
6525
  });
6226
6526
  } else {
6227
- logger27.debug("EVICTION: No eviction needed", {
6527
+ logger30.debug("EVICTION: No eviction needed", {
6228
6528
  newKey: key,
6229
6529
  estimatedSize,
6230
6530
  totalDuration
6231
6531
  });
6232
6532
  }
6233
6533
  } catch (error) {
6234
- logger27.error("EVICTION: Error in eviction strategy onItemAdded", {
6534
+ logger30.error("EVICTION: Error in eviction strategy onItemAdded", {
6235
6535
  key,
6236
6536
  error,
6237
6537
  strategy: this.evictionStrategy?.getStrategyName()
@@ -6251,7 +6551,7 @@ var EvictionManager = class {
6251
6551
  try {
6252
6552
  this.evictionStrategy.onItemRemoved(key, metadataProvider);
6253
6553
  } catch (error) {
6254
- logger27.error("Error in eviction strategy onItemRemoved", { key, error });
6554
+ logger30.error("Error in eviction strategy onItemRemoved", { key, error });
6255
6555
  }
6256
6556
  }
6257
6557
  /**
@@ -6263,15 +6563,15 @@ var EvictionManager = class {
6263
6563
  const startTime = Date.now();
6264
6564
  const evictedKeys = [];
6265
6565
  if (!this.evictionStrategy) {
6266
- logger27.debug("EVICTION: No eviction strategy configured for manual eviction");
6566
+ logger30.debug("EVICTION: No eviction strategy configured for manual eviction");
6267
6567
  return evictedKeys;
6268
6568
  }
6269
6569
  try {
6270
- logger27.debug("EVICTION: Manual eviction started", {
6570
+ logger30.debug("EVICTION: Manual eviction started", {
6271
6571
  strategy: this.evictionStrategy.getStrategyName()
6272
6572
  });
6273
6573
  const context = await this.createEvictionContext(metadataProvider);
6274
- logger27.debug("EVICTION: Manual eviction - current cache state", {
6574
+ logger30.debug("EVICTION: Manual eviction - current cache state", {
6275
6575
  currentItemCount: context.currentSize.itemCount,
6276
6576
  currentSizeBytes: context.currentSize.sizeBytes,
6277
6577
  maxItems: context.limits.maxItems,
@@ -6284,20 +6584,20 @@ var EvictionManager = class {
6284
6584
  }
6285
6585
  const duration = Date.now() - startTime;
6286
6586
  if (evictedKeys.length > 0) {
6287
- logger27.debug("EVICTION: Manual eviction completed", {
6587
+ logger30.debug("EVICTION: Manual eviction completed", {
6288
6588
  evictedCount: evictedKeys.length,
6289
6589
  evictedKeys,
6290
6590
  strategy: this.evictionStrategy.getStrategyName(),
6291
6591
  duration
6292
6592
  });
6293
6593
  } else {
6294
- logger27.debug("EVICTION: Manual eviction - no items to evict", {
6594
+ logger30.debug("EVICTION: Manual eviction - no items to evict", {
6295
6595
  strategy: this.evictionStrategy.getStrategyName(),
6296
6596
  duration
6297
6597
  });
6298
6598
  }
6299
6599
  } catch (error) {
6300
- logger27.error("EVICTION: Error in manual eviction", {
6600
+ logger30.error("EVICTION: Error in manual eviction", {
6301
6601
  error,
6302
6602
  strategy: this.evictionStrategy?.getStrategyName()
6303
6603
  });
@@ -6320,7 +6620,7 @@ var EvictionManager = class {
6320
6620
  this.evictionStrategy.reset();
6321
6621
  }
6322
6622
  }
6323
- logger27.debug("Eviction manager cleared");
6623
+ logger30.debug("Eviction manager cleared");
6324
6624
  }
6325
6625
  /**
6326
6626
  * Create eviction context from current cache state
@@ -6458,61 +6758,149 @@ var LRUEvictionStrategy = class extends EvictionStrategy {
6458
6758
  // src/eviction/EvictionStrategyValidation.ts
6459
6759
  function validateNumberRange(value, min, max, fieldName) {
6460
6760
  if (typeof value !== "number" || isNaN(value) || !isFinite(value)) {
6461
- throw new Error(`${fieldName} must be a finite number`);
6761
+ throw new Error(
6762
+ `${fieldName} must be a finite number, got ${typeof value} (${value}). Suggestion: Provide a valid numeric value for ${fieldName}.`
6763
+ );
6462
6764
  }
6463
6765
  if (value < min || value > max) {
6464
- throw new Error(`${fieldName} must be between ${min} and ${max}, got ${value}`);
6766
+ throw new Error(
6767
+ `${fieldName} must be between ${min} and ${max}, got ${value}. Suggestion: Adjust ${fieldName} to be within the valid range.`
6768
+ );
6465
6769
  }
6466
6770
  }
6467
6771
  function validatePositiveInteger(value, fieldName) {
6468
6772
  if (typeof value !== "number" || isNaN(value) || !isFinite(value)) {
6469
- throw new Error(`${fieldName} must be a finite number`);
6773
+ throw new Error(
6774
+ `${fieldName} must be a finite number, got ${typeof value} (${value}). Suggestion: Provide a valid numeric value for ${fieldName}.`
6775
+ );
6470
6776
  }
6471
6777
  if (!Number.isInteger(value) || value <= 0) {
6472
- throw new Error(`${fieldName} must be a positive integer, got ${value}`);
6778
+ throw new Error(
6779
+ `${fieldName} must be a positive integer, got ${value}. Suggestion: Use a positive whole number (1, 2, 3, ...) for ${fieldName}.`
6780
+ );
6473
6781
  }
6474
6782
  }
6475
6783
  function sanitizeLFUConfig(config) {
6476
6784
  const sanitized = { ...config };
6477
6785
  if (typeof sanitized.decayFactor === "number") {
6478
6786
  if (sanitized.decayFactor < 0) {
6479
- console.warn(`decayFactor must be between 0 and 1, got ${sanitized.decayFactor}. Correcting to 0.`);
6787
+ const warning = {
6788
+ component: "cache",
6789
+ subcomponent: "EvictionStrategyValidation",
6790
+ operation: "sanitizeLFUConfig",
6791
+ field: "decayFactor",
6792
+ invalidValue: sanitized.decayFactor,
6793
+ correctedValue: 0,
6794
+ validRange: "0-1",
6795
+ note: "Auto-correcting invalid configuration value"
6796
+ };
6797
+ console.warn("Invalid decayFactor corrected:", JSON.stringify(warning, null, 2));
6480
6798
  sanitized.decayFactor = 0;
6481
6799
  } else if (sanitized.decayFactor > 1) {
6482
- console.warn(`decayFactor must be between 0 and 1, got ${sanitized.decayFactor}. Correcting to 1.`);
6800
+ const warning = {
6801
+ component: "cache",
6802
+ subcomponent: "EvictionStrategyValidation",
6803
+ operation: "sanitizeLFUConfig",
6804
+ field: "decayFactor",
6805
+ invalidValue: sanitized.decayFactor,
6806
+ correctedValue: 1,
6807
+ validRange: "0-1",
6808
+ note: "Auto-correcting invalid configuration value"
6809
+ };
6810
+ console.warn("Invalid decayFactor corrected:", JSON.stringify(warning, null, 2));
6483
6811
  sanitized.decayFactor = 1;
6484
6812
  }
6485
6813
  }
6486
6814
  if (typeof sanitized.decayInterval === "number" && sanitized.decayInterval <= 0) {
6487
- console.warn(`decayInterval must be positive, got ${sanitized.decayInterval}. Correcting to 300000.`);
6815
+ const warning = {
6816
+ component: "cache",
6817
+ subcomponent: "EvictionStrategyValidation",
6818
+ operation: "sanitizeLFUConfig",
6819
+ field: "decayInterval",
6820
+ invalidValue: sanitized.decayInterval,
6821
+ correctedValue: 3e5,
6822
+ minimumValue: 1,
6823
+ note: "Auto-correcting to 5 minutes (300000ms) default"
6824
+ };
6825
+ console.warn("Invalid decayInterval corrected:", JSON.stringify(warning, null, 2));
6488
6826
  sanitized.decayInterval = 3e5;
6489
6827
  }
6490
6828
  if (typeof sanitized.sketchWidth === "number") {
6491
6829
  if (sanitized.sketchWidth <= 0) {
6492
- console.warn(`sketchWidth must be positive, got ${sanitized.sketchWidth}. Correcting to 1024.`);
6830
+ console.warn("Invalid sketchWidth corrected:", JSON.stringify({
6831
+ component: "cache",
6832
+ subcomponent: "EvictionStrategyValidation",
6833
+ field: "sketchWidth",
6834
+ invalidValue: sanitized.sketchWidth,
6835
+ correctedValue: 1024,
6836
+ note: "Auto-correcting invalid configuration"
6837
+ }, null, 2));
6493
6838
  sanitized.sketchWidth = 1024;
6494
6839
  } else if (sanitized.sketchWidth < 16) {
6495
- console.warn(`sketchWidth should be at least 16 for optimal performance, got ${sanitized.sketchWidth}. Correcting to 16.`);
6840
+ console.warn("Suboptimal sketchWidth corrected:", JSON.stringify({
6841
+ component: "cache",
6842
+ subcomponent: "EvictionStrategyValidation",
6843
+ field: "sketchWidth",
6844
+ invalidValue: sanitized.sketchWidth,
6845
+ correctedValue: 16,
6846
+ minimumRecommended: 16,
6847
+ note: "Correcting for optimal performance"
6848
+ }, null, 2));
6496
6849
  sanitized.sketchWidth = 16;
6497
6850
  } else if (sanitized.sketchWidth > 65536) {
6498
- console.warn(`sketchWidth should not exceed 65536 for optimal performance, got ${sanitized.sketchWidth}. Correcting to 65536.`);
6851
+ console.warn("Excessive sketchWidth corrected:", JSON.stringify({
6852
+ component: "cache",
6853
+ subcomponent: "EvictionStrategyValidation",
6854
+ field: "sketchWidth",
6855
+ invalidValue: sanitized.sketchWidth,
6856
+ correctedValue: 65536,
6857
+ maximumRecommended: 65536,
6858
+ note: "Correcting for optimal performance"
6859
+ }, null, 2));
6499
6860
  sanitized.sketchWidth = 65536;
6500
6861
  }
6501
6862
  }
6502
6863
  if (typeof sanitized.sketchDepth === "number") {
6503
6864
  if (sanitized.sketchDepth <= 0) {
6504
- console.warn(`sketchDepth must be positive, got ${sanitized.sketchDepth}. Correcting to 4.`);
6865
+ console.warn("Invalid sketchDepth corrected:", JSON.stringify({
6866
+ component: "cache",
6867
+ subcomponent: "EvictionStrategyValidation",
6868
+ field: "sketchDepth",
6869
+ invalidValue: sanitized.sketchDepth,
6870
+ correctedValue: 4
6871
+ }, null, 2));
6505
6872
  sanitized.sketchDepth = 4;
6506
6873
  } else if (sanitized.sketchDepth < 1) {
6507
- console.warn(`sketchDepth should be at least 1 for optimal accuracy, got ${sanitized.sketchDepth}. Correcting to 1.`);
6874
+ console.warn("Suboptimal sketchDepth corrected:", JSON.stringify({
6875
+ component: "cache",
6876
+ subcomponent: "EvictionStrategyValidation",
6877
+ field: "sketchDepth",
6878
+ invalidValue: sanitized.sketchDepth,
6879
+ correctedValue: 1,
6880
+ minimumRecommended: 1
6881
+ }, null, 2));
6508
6882
  sanitized.sketchDepth = 1;
6509
6883
  } else if (sanitized.sketchDepth > 16) {
6510
- console.warn(`sketchDepth should not exceed 16 for optimal accuracy, got ${sanitized.sketchDepth}. Correcting to 16.`);
6884
+ console.warn("Excessive sketchDepth corrected:", JSON.stringify({
6885
+ component: "cache",
6886
+ subcomponent: "EvictionStrategyValidation",
6887
+ field: "sketchDepth",
6888
+ invalidValue: sanitized.sketchDepth,
6889
+ correctedValue: 16,
6890
+ maximumRecommended: 16
6891
+ }, null, 2));
6511
6892
  sanitized.sketchDepth = 16;
6512
6893
  }
6513
6894
  }
6514
6895
  if (typeof sanitized.minFrequencyThreshold === "number" && sanitized.minFrequencyThreshold <= 0) {
6515
- console.warn(`minFrequencyThreshold must be positive, got ${sanitized.minFrequencyThreshold}. Correcting to 1.`);
6896
+ console.warn("Invalid minFrequencyThreshold corrected:", JSON.stringify({
6897
+ component: "cache",
6898
+ subcomponent: "EvictionStrategyValidation",
6899
+ field: "minFrequencyThreshold",
6900
+ invalidValue: sanitized.minFrequencyThreshold,
6901
+ correctedValue: 1,
6902
+ minimumValue: 1
6903
+ }, null, 2));
6516
6904
  sanitized.minFrequencyThreshold = 1;
6517
6905
  }
6518
6906
  return sanitized;
@@ -6543,32 +6931,86 @@ function validateLFUConfig(config) {
6543
6931
  function sanitizeARCConfig(config) {
6544
6932
  const sanitized = { ...config };
6545
6933
  if (typeof sanitized.maxCacheSize === "number" && sanitized.maxCacheSize <= 0) {
6546
- console.warn(`maxCacheSize must be positive, got ${sanitized.maxCacheSize}. Correcting to 1000.`);
6934
+ console.warn("Invalid maxCacheSize corrected:", JSON.stringify({
6935
+ component: "cache",
6936
+ subcomponent: "EvictionStrategyValidation",
6937
+ operation: "sanitizeARCConfig",
6938
+ field: "maxCacheSize",
6939
+ invalidValue: sanitized.maxCacheSize,
6940
+ correctedValue: 1e3
6941
+ }, null, 2));
6547
6942
  sanitized.maxCacheSize = 1e3;
6548
6943
  }
6549
6944
  if (typeof sanitized.frequencyThreshold === "number" && sanitized.frequencyThreshold <= 0) {
6550
- console.warn(`frequencyThreshold must be positive, got ${sanitized.frequencyThreshold}. Correcting to 2.`);
6945
+ console.warn("Invalid frequencyThreshold corrected:", JSON.stringify({
6946
+ component: "cache",
6947
+ subcomponent: "EvictionStrategyValidation",
6948
+ operation: "sanitizeARCConfig",
6949
+ field: "frequencyThreshold",
6950
+ invalidValue: sanitized.frequencyThreshold,
6951
+ correctedValue: 2
6952
+ }, null, 2));
6551
6953
  sanitized.frequencyThreshold = 2;
6552
6954
  }
6553
6955
  if (typeof sanitized.frequencyDecayFactor === "number") {
6554
6956
  if (sanitized.frequencyDecayFactor < 0) {
6555
- console.warn(`frequencyDecayFactor must be between 0 and 1, got ${sanitized.frequencyDecayFactor}. Correcting to 0.`);
6957
+ console.warn("Invalid frequencyDecayFactor corrected:", JSON.stringify({
6958
+ component: "cache",
6959
+ subcomponent: "EvictionStrategyValidation",
6960
+ operation: "sanitizeARCConfig",
6961
+ field: "frequencyDecayFactor",
6962
+ invalidValue: sanitized.frequencyDecayFactor,
6963
+ correctedValue: 0,
6964
+ validRange: "0-1"
6965
+ }, null, 2));
6556
6966
  sanitized.frequencyDecayFactor = 0;
6557
6967
  } else if (sanitized.frequencyDecayFactor > 1) {
6558
- console.warn(`frequencyDecayFactor must be between 0 and 1, got ${sanitized.frequencyDecayFactor}. Correcting to 1.`);
6968
+ console.warn("Invalid frequencyDecayFactor corrected:", JSON.stringify({
6969
+ component: "cache",
6970
+ subcomponent: "EvictionStrategyValidation",
6971
+ operation: "sanitizeARCConfig",
6972
+ field: "frequencyDecayFactor",
6973
+ invalidValue: sanitized.frequencyDecayFactor,
6974
+ correctedValue: 1,
6975
+ validRange: "0-1"
6976
+ }, null, 2));
6559
6977
  sanitized.frequencyDecayFactor = 1;
6560
6978
  }
6561
6979
  }
6562
6980
  if (typeof sanitized.frequencyDecayInterval === "number" && sanitized.frequencyDecayInterval <= 0) {
6563
- console.warn(`frequencyDecayInterval must be positive, got ${sanitized.frequencyDecayInterval}. Correcting to 60000.`);
6981
+ console.warn("Invalid frequencyDecayInterval corrected:", JSON.stringify({
6982
+ component: "cache",
6983
+ subcomponent: "EvictionStrategyValidation",
6984
+ operation: "sanitizeARCConfig",
6985
+ field: "frequencyDecayInterval",
6986
+ invalidValue: sanitized.frequencyDecayInterval,
6987
+ correctedValue: 6e4,
6988
+ note: "Corrected to 1 minute default"
6989
+ }, null, 2));
6564
6990
  sanitized.frequencyDecayInterval = 6e4;
6565
6991
  }
6566
6992
  if (typeof sanitized.adaptiveLearningRate === "number") {
6567
6993
  if (sanitized.adaptiveLearningRate < 0) {
6568
- console.warn(`adaptiveLearningRate must be between 0 and 10, got ${sanitized.adaptiveLearningRate}. Correcting to 0.`);
6994
+ console.warn("Invalid adaptiveLearningRate corrected:", JSON.stringify({
6995
+ component: "cache",
6996
+ subcomponent: "EvictionStrategyValidation",
6997
+ operation: "sanitizeARCConfig",
6998
+ field: "adaptiveLearningRate",
6999
+ invalidValue: sanitized.adaptiveLearningRate,
7000
+ correctedValue: 0,
7001
+ validRange: "0-10"
7002
+ }, null, 2));
6569
7003
  sanitized.adaptiveLearningRate = 0;
6570
7004
  } else if (sanitized.adaptiveLearningRate > 10) {
6571
- console.warn(`adaptiveLearningRate must be between 0 and 10, got ${sanitized.adaptiveLearningRate}. Correcting to 10.`);
7005
+ console.warn("Invalid adaptiveLearningRate corrected:", JSON.stringify({
7006
+ component: "cache",
7007
+ subcomponent: "EvictionStrategyValidation",
7008
+ operation: "sanitizeARCConfig",
7009
+ field: "adaptiveLearningRate",
7010
+ invalidValue: sanitized.adaptiveLearningRate,
7011
+ correctedValue: 10,
7012
+ validRange: "0-10"
7013
+ }, null, 2));
6572
7014
  sanitized.adaptiveLearningRate = 10;
6573
7015
  }
6574
7016
  }
@@ -6594,24 +7036,62 @@ function validateARCConfig(config) {
6594
7036
  function sanitizeTwoQueueConfig(config) {
6595
7037
  const sanitized = { ...config };
6596
7038
  if (typeof sanitized.maxCacheSize === "number" && sanitized.maxCacheSize <= 0) {
6597
- console.warn(`maxCacheSize must be positive, got ${sanitized.maxCacheSize}. Correcting to 1000.`);
7039
+ console.warn("Invalid maxCacheSize corrected:", JSON.stringify({
7040
+ component: "cache",
7041
+ subcomponent: "EvictionStrategyValidation",
7042
+ operation: "sanitizeTwoQueueConfig",
7043
+ field: "maxCacheSize",
7044
+ invalidValue: sanitized.maxCacheSize,
7045
+ correctedValue: 1e3
7046
+ }, null, 2));
6598
7047
  sanitized.maxCacheSize = 1e3;
6599
7048
  }
6600
7049
  if (typeof sanitized.promotionThreshold === "number" && sanitized.promotionThreshold <= 0) {
6601
- console.warn(`promotionThreshold must be positive, got ${sanitized.promotionThreshold}. Correcting to 2.`);
7050
+ console.warn("Invalid promotionThreshold corrected:", JSON.stringify({
7051
+ component: "cache",
7052
+ subcomponent: "EvictionStrategyValidation",
7053
+ operation: "sanitizeTwoQueueConfig",
7054
+ field: "promotionThreshold",
7055
+ invalidValue: sanitized.promotionThreshold,
7056
+ correctedValue: 2
7057
+ }, null, 2));
6602
7058
  sanitized.promotionThreshold = 2;
6603
7059
  }
6604
7060
  if (typeof sanitized.hotQueueDecayFactor === "number") {
6605
7061
  if (sanitized.hotQueueDecayFactor < 0) {
6606
- console.warn(`hotQueueDecayFactor must be between 0 and 1, got ${sanitized.hotQueueDecayFactor}. Correcting to 0.`);
7062
+ console.warn("Invalid hotQueueDecayFactor corrected:", JSON.stringify({
7063
+ component: "cache",
7064
+ subcomponent: "EvictionStrategyValidation",
7065
+ operation: "sanitizeTwoQueueConfig",
7066
+ field: "hotQueueDecayFactor",
7067
+ invalidValue: sanitized.hotQueueDecayFactor,
7068
+ correctedValue: 0,
7069
+ validRange: "0-1"
7070
+ }, null, 2));
6607
7071
  sanitized.hotQueueDecayFactor = 0;
6608
7072
  } else if (sanitized.hotQueueDecayFactor > 1) {
6609
- console.warn(`hotQueueDecayFactor must be between 0 and 1, got ${sanitized.hotQueueDecayFactor}. Correcting to 1.`);
7073
+ console.warn("Invalid hotQueueDecayFactor corrected:", JSON.stringify({
7074
+ component: "cache",
7075
+ subcomponent: "EvictionStrategyValidation",
7076
+ operation: "sanitizeTwoQueueConfig",
7077
+ field: "hotQueueDecayFactor",
7078
+ invalidValue: sanitized.hotQueueDecayFactor,
7079
+ correctedValue: 1,
7080
+ validRange: "0-1"
7081
+ }, null, 2));
6610
7082
  sanitized.hotQueueDecayFactor = 1;
6611
7083
  }
6612
7084
  }
6613
7085
  if (typeof sanitized.hotQueueDecayInterval === "number" && sanitized.hotQueueDecayInterval <= 0) {
6614
- console.warn(`hotQueueDecayInterval must be positive, got ${sanitized.hotQueueDecayInterval}. Correcting to 300000.`);
7086
+ console.warn("Invalid hotQueueDecayInterval corrected:", JSON.stringify({
7087
+ component: "cache",
7088
+ subcomponent: "EvictionStrategyValidation",
7089
+ operation: "sanitizeTwoQueueConfig",
7090
+ field: "hotQueueDecayInterval",
7091
+ invalidValue: sanitized.hotQueueDecayInterval,
7092
+ correctedValue: 3e5,
7093
+ note: "Corrected to 5 minutes default"
7094
+ }, null, 2));
6615
7095
  sanitized.hotQueueDecayInterval = 3e5;
6616
7096
  }
6617
7097
  return sanitized;
@@ -7658,7 +8138,7 @@ function createEvictionStrategy(policy, maxCacheSize, config) {
7658
8138
  }
7659
8139
 
7660
8140
  // src/ttl/TTLManager.ts
7661
- var logger28 = logger_default.get("TTLManager");
8141
+ var logger31 = logger_default.get("TTLManager");
7662
8142
  var TTLManager = class {
7663
8143
  config;
7664
8144
  cleanupTimer;
@@ -7670,7 +8150,7 @@ var TTLManager = class {
7670
8150
  validateOnAccess: true,
7671
8151
  ...config
7672
8152
  };
7673
- logger28.debug("TTL_DEBUG: TTLManager created", {
8153
+ logger31.debug("TTL_DEBUG: TTLManager created", {
7674
8154
  config: this.config,
7675
8155
  isTTLEnabled: this.isTTLEnabled(),
7676
8156
  defaultTTL: this.config.defaultTTL
@@ -7703,13 +8183,13 @@ var TTLManager = class {
7703
8183
  this.startAutoCleanup();
7704
8184
  }
7705
8185
  }
7706
- logger28.debug("TTL configuration updated", { config: this.config });
8186
+ logger31.debug("TTL configuration updated", { config: this.config });
7707
8187
  }
7708
8188
  /**
7709
8189
  * Set TTL metadata for an item when it's added
7710
8190
  */
7711
8191
  async onItemAdded(key, metadataProvider, itemTTL) {
7712
- logger28.debug("TTL_DEBUG: onItemAdded called", {
8192
+ logger31.debug("TTL_DEBUG: onItemAdded called", {
7713
8193
  key,
7714
8194
  itemTTL,
7715
8195
  isTTLEnabled: this.isTTLEnabled(),
@@ -7717,19 +8197,19 @@ var TTLManager = class {
7717
8197
  metadataProviderType: metadataProvider?.constructor?.name
7718
8198
  });
7719
8199
  if (!this.isTTLEnabled() && !itemTTL) {
7720
- logger28.debug("TTL_DEBUG: No TTL configured for item - returning early", { key });
8200
+ logger31.debug("TTL_DEBUG: No TTL configured for item - returning early", { key });
7721
8201
  return;
7722
8202
  }
7723
- logger28.debug("TTL_DEBUG: Getting metadata for key", { key });
8203
+ logger31.debug("TTL_DEBUG: Getting metadata for key", { key });
7724
8204
  const metadata = await metadataProvider.getMetadata(key);
7725
- logger28.debug("TTL_DEBUG: Retrieved metadata", {
8205
+ logger31.debug("TTL_DEBUG: Retrieved metadata", {
7726
8206
  key,
7727
8207
  hasMetadata: !!metadata,
7728
8208
  metadataKeys: metadata ? Object.keys(metadata) : null,
7729
8209
  metadata
7730
8210
  });
7731
8211
  if (!metadata) {
7732
- logger28.debug("TTL_DEBUG: No metadata found for item when setting TTL", {
8212
+ logger31.debug("TTL_DEBUG: No metadata found for item when setting TTL", {
7733
8213
  key,
7734
8214
  metadataProviderType: metadataProvider?.constructor?.name,
7735
8215
  metadataProviderMethods: metadataProvider ? Object.getOwnPropertyNames(Object.getPrototypeOf(metadataProvider)) : null
@@ -7737,7 +8217,7 @@ var TTLManager = class {
7737
8217
  return;
7738
8218
  }
7739
8219
  const ttl = itemTTL || this.config.defaultTTL;
7740
- logger28.debug("TTL_DEBUG: Calculated TTL value", {
8220
+ logger31.debug("TTL_DEBUG: Calculated TTL value", {
7741
8221
  key,
7742
8222
  itemTTL,
7743
8223
  defaultTTL: this.config.defaultTTL,
@@ -7750,7 +8230,7 @@ var TTLManager = class {
7750
8230
  expiresAt: metadata.addedAt + ttl,
7751
8231
  ttl
7752
8232
  };
7753
- logger28.debug("TTL_DEBUG: Setting TTL metadata", {
8233
+ logger31.debug("TTL_DEBUG: Setting TTL metadata", {
7754
8234
  key,
7755
8235
  ttl,
7756
8236
  addedAt: metadata.addedAt,
@@ -7758,9 +8238,9 @@ var TTLManager = class {
7758
8238
  ttlMetadata
7759
8239
  });
7760
8240
  await metadataProvider.setMetadata(key, ttlMetadata);
7761
- logger28.trace("TTL_DEBUG: TTL set for item", { key, ttl, expiresAt: ttlMetadata.expiresAt });
8241
+ logger31.trace("TTL_DEBUG: TTL set for item", { key, ttl, expiresAt: ttlMetadata.expiresAt });
7762
8242
  } else {
7763
- logger28.debug("TTL_DEBUG: No TTL set - invalid TTL value", { key, ttl });
8243
+ logger31.debug("TTL_DEBUG: No TTL set - invalid TTL value", { key, ttl });
7764
8244
  }
7765
8245
  }
7766
8246
  /**
@@ -7769,14 +8249,14 @@ var TTLManager = class {
7769
8249
  async isExpired(key, metadataProvider) {
7770
8250
  const metadata = await metadataProvider.getMetadata(key);
7771
8251
  if (!metadata || !metadata.expiresAt) {
7772
- logger28.debug("TTL_CHECK: No TTL set for item", { key, hasMetadata: !!metadata });
8252
+ logger31.debug("TTL_CHECK: No TTL set for item", { key, hasMetadata: !!metadata });
7773
8253
  return false;
7774
8254
  }
7775
8255
  const now = Date.now();
7776
8256
  const expired = now >= metadata.expiresAt;
7777
8257
  const remainingMs = metadata.expiresAt - now;
7778
8258
  if (expired) {
7779
- logger28.debug("TTL_CHECK: Item EXPIRED", {
8259
+ logger31.debug("TTL_CHECK: Item EXPIRED", {
7780
8260
  key,
7781
8261
  expiresAt: new Date(metadata.expiresAt).toISOString(),
7782
8262
  now: new Date(now).toISOString(),
@@ -7784,7 +8264,7 @@ var TTLManager = class {
7784
8264
  ttl: metadata.ttl
7785
8265
  });
7786
8266
  } else {
7787
- logger28.debug("TTL_CHECK: Item still valid", {
8267
+ logger31.debug("TTL_CHECK: Item still valid", {
7788
8268
  key,
7789
8269
  expiresAt: new Date(metadata.expiresAt).toISOString(),
7790
8270
  remainingMs,
@@ -7800,17 +8280,17 @@ var TTLManager = class {
7800
8280
  */
7801
8281
  async validateItem(key, metadataProvider) {
7802
8282
  if (!this.config.validateOnAccess) {
7803
- logger28.debug("TTL_VALIDATE: Validation disabled, skipping check", { key });
8283
+ logger31.debug("TTL_VALIDATE: Validation disabled, skipping check", { key });
7804
8284
  return true;
7805
8285
  }
7806
- logger28.debug("TTL_VALIDATE: Validating item", {
8286
+ logger31.debug("TTL_VALIDATE: Validating item", {
7807
8287
  key,
7808
8288
  ttlEnabled: this.isTTLEnabled(),
7809
8289
  defaultTTL: this.config.defaultTTL
7810
8290
  });
7811
8291
  const isExpired = await this.isExpired(key, metadataProvider);
7812
8292
  const isValid = !isExpired;
7813
- logger28.debug("TTL_VALIDATE: Validation result", {
8293
+ logger31.debug("TTL_VALIDATE: Validation result", {
7814
8294
  key,
7815
8295
  isValid,
7816
8296
  isExpired
@@ -7844,7 +8324,7 @@ var TTLManager = class {
7844
8324
  const expiredKeys = [];
7845
8325
  const allMetadata = await metadataProvider.getAllMetadata();
7846
8326
  const now = Date.now();
7847
- logger28.debug("TTL_CLEANUP: Scanning for expired items", {
8327
+ logger31.debug("TTL_CLEANUP: Scanning for expired items", {
7848
8328
  totalItems: allMetadata.size,
7849
8329
  now: new Date(now).toISOString()
7850
8330
  });
@@ -7855,7 +8335,7 @@ var TTLManager = class {
7855
8335
  itemsWithTTL++;
7856
8336
  if (now >= ttlMetadata.expiresAt) {
7857
8337
  expiredKeys.push(key);
7858
- logger28.debug("TTL_CLEANUP: Found expired item", {
8338
+ logger31.debug("TTL_CLEANUP: Found expired item", {
7859
8339
  key,
7860
8340
  expiresAt: new Date(ttlMetadata.expiresAt).toISOString(),
7861
8341
  expiredByMs: now - ttlMetadata.expiresAt
@@ -7865,7 +8345,7 @@ var TTLManager = class {
7865
8345
  }
7866
8346
  const duration = Date.now() - startTime;
7867
8347
  if (expiredKeys.length > 0) {
7868
- logger28.debug("TTL_CLEANUP: Expired items found", {
8348
+ logger31.debug("TTL_CLEANUP: Expired items found", {
7869
8349
  expiredCount: expiredKeys.length,
7870
8350
  totalItems: allMetadata.size,
7871
8351
  itemsWithTTL,
@@ -7873,7 +8353,7 @@ var TTLManager = class {
7873
8353
  duration
7874
8354
  });
7875
8355
  } else {
7876
- logger28.debug("TTL_CLEANUP: No expired items found", {
8356
+ logger31.debug("TTL_CLEANUP: No expired items found", {
7877
8357
  totalItems: allMetadata.size,
7878
8358
  itemsWithTTL,
7879
8359
  duration
@@ -7905,7 +8385,7 @@ var TTLManager = class {
7905
8385
  }
7906
8386
  metadata.expiresAt += additionalTTL;
7907
8387
  await metadataProvider.setMetadata(key, metadata);
7908
- logger28.trace("TTL extended for item", { key, additionalTTL, newExpiresAt: metadata.expiresAt });
8388
+ logger31.trace("TTL extended for item", { key, additionalTTL, newExpiresAt: metadata.expiresAt });
7909
8389
  return true;
7910
8390
  }
7911
8391
  /**
@@ -7927,7 +8407,7 @@ var TTLManager = class {
7927
8407
  ttl
7928
8408
  };
7929
8409
  await metadataProvider.setMetadata(key, ttlMetadata);
7930
- logger28.trace("TTL refreshed for item", { key, ttl, expiresAt: ttlMetadata.expiresAt });
8410
+ logger31.trace("TTL refreshed for item", { key, ttl, expiresAt: ttlMetadata.expiresAt });
7931
8411
  return true;
7932
8412
  }
7933
8413
  /**
@@ -7939,9 +8419,9 @@ var TTLManager = class {
7939
8419
  }
7940
8420
  if (this.config.cleanupInterval) {
7941
8421
  this.cleanupTimer = setInterval(() => {
7942
- logger28.trace("Auto cleanup timer triggered");
8422
+ logger31.trace("Auto cleanup timer triggered");
7943
8423
  }, this.config.cleanupInterval);
7944
- logger28.debug("Auto cleanup started", { interval: this.config.cleanupInterval });
8424
+ logger31.debug("Auto cleanup started", { interval: this.config.cleanupInterval });
7945
8425
  }
7946
8426
  }
7947
8427
  /**
@@ -7951,7 +8431,7 @@ var TTLManager = class {
7951
8431
  if (this.cleanupTimer) {
7952
8432
  clearInterval(this.cleanupTimer);
7953
8433
  this.cleanupTimer = null;
7954
- logger28.debug("Auto cleanup stopped");
8434
+ logger31.debug("Auto cleanup stopped");
7955
8435
  }
7956
8436
  }
7957
8437
  /**
@@ -7959,18 +8439,31 @@ var TTLManager = class {
7959
8439
  */
7960
8440
  clear() {
7961
8441
  this.stopAutoCleanup();
7962
- logger28.debug("TTL manager cleared");
8442
+ logger31.debug("TTL manager cleared");
7963
8443
  }
7964
8444
  /**
7965
8445
  * Cleanup resources
7966
8446
  */
7967
8447
  destroy() {
8448
+ logger31.debug("TTL manager destroy started", {
8449
+ component: "cache",
8450
+ subcomponent: "TTLManager",
8451
+ operation: "destroy",
8452
+ autoCleanupEnabled: !!this.config.cleanupInterval,
8453
+ note: "Stopping auto-cleanup and clearing TTL data"
8454
+ });
7968
8455
  this.stopAutoCleanup();
7969
- logger28.debug("TTL manager destroyed");
8456
+ logger31.debug("TTL manager destroyed", {
8457
+ component: "cache",
8458
+ subcomponent: "TTLManager",
8459
+ operation: "destroy",
8460
+ note: "All TTL tracking data cleared"
8461
+ });
7970
8462
  }
7971
8463
  };
7972
8464
 
7973
8465
  // src/events/CacheEventEmitter.ts
8466
+ var logger32 = logger_default.get("CacheEventEmitter");
7974
8467
  var CacheEventEmitter = class {
7975
8468
  subscriptions = /* @__PURE__ */ new Map();
7976
8469
  nextSubscriptionId = 1;
@@ -8071,9 +8564,17 @@ var CacheEventEmitter = class {
8071
8564
  */
8072
8565
  emit(event) {
8073
8566
  if (this.isDestroyed) {
8567
+ logger32.debug("Event emission skipped - emitter is destroyed", {
8568
+ component: "cache",
8569
+ subcomponent: "CacheEventEmitter",
8570
+ eventType: event.type,
8571
+ suggestion: "This is expected during cleanup. Ensure emitter is not used after destroy()."
8572
+ });
8074
8573
  return;
8075
8574
  }
8076
8575
  let emittedCount = 0;
8576
+ const totalSubscriptions = this.subscriptions.size;
8577
+ const activeSubscriptions = Array.from(this.subscriptions.values()).filter((s) => s.isActive).length;
8077
8578
  for (const subscription of this.subscriptions.values()) {
8078
8579
  if (!subscription.isActive) {
8079
8580
  continue;
@@ -8083,6 +8584,17 @@ var CacheEventEmitter = class {
8083
8584
  emittedCount++;
8084
8585
  }
8085
8586
  }
8587
+ logger32.trace("Event emitted to subscriptions", {
8588
+ component: "cache",
8589
+ subcomponent: "CacheEventEmitter",
8590
+ eventType: event.type,
8591
+ eventSource: event.source,
8592
+ eventKey: "key" in event ? JSON.stringify(event.key) : void 0,
8593
+ totalSubscriptions,
8594
+ activeSubscriptions,
8595
+ emittedCount,
8596
+ note: emittedCount === 0 ? "No subscriptions matched this event" : void 0
8597
+ });
8086
8598
  }
8087
8599
  /**
8088
8600
  * Get count of active subscriptions
@@ -8287,20 +8799,36 @@ var CacheEventEmitter = class {
8287
8799
  */
8288
8800
  handleListenerError(error, event, subscription) {
8289
8801
  const errorObj = error instanceof Error ? error : new Error(String(error));
8802
+ const errorContext = {
8803
+ component: "CacheEventEmitter",
8804
+ operation: "event-listener",
8805
+ eventType: event.type,
8806
+ eventKey: "key" in event ? JSON.stringify(event.key) : void 0,
8807
+ subscriptionId: subscription.id,
8808
+ errorType: errorObj.constructor.name,
8809
+ errorMessage: errorObj.message,
8810
+ suggestion: "Review event listener implementation for errors. Consider adding error handling in the listener.",
8811
+ stack: errorObj.stack
8812
+ };
8290
8813
  if (subscription.options.onError) {
8291
8814
  try {
8292
8815
  subscription.options.onError(errorObj, event);
8293
8816
  } catch (handlerError) {
8294
- console.error("Error in cache event listener:", errorObj);
8817
+ console.error("Error in cache event listener:", JSON.stringify(errorContext, null, 2));
8818
+ console.error("Original error:", errorObj);
8295
8819
  console.error("Error in error handler:", handlerError);
8820
+ console.error("Critical: Both the event listener and its error handler failed. Review error handling logic.");
8296
8821
  }
8297
8822
  } else {
8298
- console.error("Error in cache event listener:", errorObj);
8823
+ console.error("Error in cache event listener (no error handler configured):", JSON.stringify(errorContext, null, 2));
8824
+ console.error("Original error:", errorObj);
8825
+ console.error("Suggestion: Add an onError handler to your subscription to handle listener errors gracefully.");
8299
8826
  }
8300
8827
  }
8301
8828
  };
8302
8829
 
8303
8830
  // src/CacheStats.ts
8831
+ var logger33 = logger_default.get("CacheStats");
8304
8832
  var CacheStatsManager = class {
8305
8833
  stats = {
8306
8834
  numRequests: 0,
@@ -8310,11 +8838,22 @@ var CacheStatsManager = class {
8310
8838
  numUnsubscriptions: 0,
8311
8839
  activeSubscriptions: 0
8312
8840
  };
8841
+ lastLoggedStats = {
8842
+ numRequests: 0,
8843
+ numMisses: 0,
8844
+ numHits: 0,
8845
+ numSubscriptions: 0,
8846
+ numUnsubscriptions: 0,
8847
+ activeSubscriptions: 0
8848
+ };
8849
+ LOG_THRESHOLD = 100;
8850
+ // Log every 100 requests
8313
8851
  /**
8314
8852
  * Increment the request counter
8315
8853
  */
8316
8854
  incrementRequests() {
8317
8855
  this.stats.numRequests++;
8856
+ this.maybeLogStats();
8318
8857
  }
8319
8858
  /**
8320
8859
  * Increment the cache hit counter
@@ -8328,6 +8867,27 @@ var CacheStatsManager = class {
8328
8867
  incrementMisses() {
8329
8868
  this.stats.numMisses++;
8330
8869
  }
8870
+ /**
8871
+ * Log statistics periodically for monitoring
8872
+ */
8873
+ maybeLogStats() {
8874
+ const requestsSinceLastLog = this.stats.numRequests - this.lastLoggedStats.numRequests;
8875
+ if (requestsSinceLastLog >= this.LOG_THRESHOLD) {
8876
+ const hitRate = this.stats.numRequests > 0 ? (this.stats.numHits / this.stats.numRequests * 100).toFixed(2) : "0.00";
8877
+ logger33.debug("Cache statistics update", {
8878
+ component: "cache",
8879
+ subcomponent: "CacheStatsManager",
8880
+ totalRequests: this.stats.numRequests,
8881
+ hits: this.stats.numHits,
8882
+ misses: this.stats.numMisses,
8883
+ hitRate: `${hitRate}%`,
8884
+ activeSubscriptions: this.stats.activeSubscriptions,
8885
+ requestsSinceLastLog,
8886
+ note: `Statistics logged every ${this.LOG_THRESHOLD} requests for monitoring`
8887
+ });
8888
+ this.lastLoggedStats = { ...this.stats };
8889
+ }
8890
+ }
8331
8891
  /**
8332
8892
  * Increment the subscription counter
8333
8893
  */
@@ -8366,9 +8926,17 @@ var CacheStatsManager = class {
8366
8926
  };
8367
8927
 
8368
8928
  // src/Cache.ts
8369
- var logger29 = logger_default.get("Cache");
8929
+ var logger34 = logger_default.get("Cache");
8370
8930
  var createCache = (api, coordinate, registry, options) => {
8371
- logger29.debug("createCache", { coordinate, registry, options });
8931
+ logger34.debug("createCache", {
8932
+ component: "cache",
8933
+ operation: "createCache",
8934
+ itemType: coordinate.kta[0],
8935
+ hierarchy: coordinate.kta,
8936
+ cacheType: options?.cacheType,
8937
+ hasRegistry: !!registry,
8938
+ note: "Cache creation started"
8939
+ });
8372
8940
  const completeOptions = createOptions(options);
8373
8941
  const cacheMap = createCacheMap(coordinate.kta, completeOptions);
8374
8942
  const pkType = coordinate.kta[0];
@@ -8448,18 +9016,24 @@ var isCache2 = (cache) => {
8448
9016
  };
8449
9017
 
8450
9018
  // src/InstanceFactory.ts
8451
- var logger30 = logger_default.get("InstanceFactory");
9019
+ var logger35 = logger_default.get("InstanceFactory");
8452
9020
  var createInstanceFactory = (api, options) => {
8453
9021
  const templateOptions = createOptions(options);
8454
9022
  validateOptions(templateOptions);
8455
9023
  return (coordinate, context) => {
8456
9024
  const instanceOptions = createOptions(options);
8457
- logger30.debug("Creating cache instance", {
8458
- coordinate,
8459
- registry: context.registry,
8460
- api,
9025
+ logger35.debug("Creating cache instance", {
9026
+ component: "cache",
9027
+ operation: "createInstance",
9028
+ itemType: coordinate.kta[0],
9029
+ hierarchy: coordinate.kta,
8461
9030
  cacheType: instanceOptions.cacheType,
8462
- options: instanceOptions
9031
+ ttlEnabled: !!instanceOptions.ttl,
9032
+ ttlValue: instanceOptions.ttl,
9033
+ evictionEnabled: !!instanceOptions.evictionConfig,
9034
+ evictionStrategy: instanceOptions.evictionConfig?.type,
9035
+ twoLayerEnabled: !!instanceOptions.twoLayer,
9036
+ note: "Cache instance initialization started"
8463
9037
  });
8464
9038
  const cacheMap = createCacheMap(coordinate.kta, instanceOptions);
8465
9039
  const pkType = coordinate.kta[0];
@@ -8521,9 +9095,9 @@ var createInstanceFactory = (api, options) => {
8521
9095
  };
8522
9096
 
8523
9097
  // src/Instance.ts
8524
- var logger31 = logger_default.get("Instance");
9098
+ var logger36 = logger_default.get("Instance");
8525
9099
  var createInstance = (registry, coordinate, api, options) => {
8526
- logger31.debug("createInstance", { coordinate, api, registry, options });
9100
+ logger36.debug("createInstance", { coordinate, api, registry, options });
8527
9101
  return createCache(api, coordinate, registry, options);
8528
9102
  };
8529
9103
  var isInstance = (instance) => {
@@ -8531,7 +9105,7 @@ var isInstance = (instance) => {
8531
9105
  };
8532
9106
 
8533
9107
  // src/Aggregator.ts
8534
- var logger32 = logger_default.get("ItemAggregator");
9108
+ var logger37 = logger_default.get("ItemAggregator");
8535
9109
  var toCacheConfig = (config) => {
8536
9110
  let cacheConfig;
8537
9111
  if (config.optional === void 0) {
@@ -8543,23 +9117,32 @@ var toCacheConfig = (config) => {
8543
9117
  };
8544
9118
  var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8545
9119
  const populate = async (item) => {
8546
- logger32.default("populate", { item });
9120
+ logger37.default("populate", { item });
8547
9121
  for (const key in aggregates) {
8548
9122
  await populateAggregate(key, item);
8549
9123
  }
8550
9124
  for (const key in events) {
8551
9125
  await populateEvent(key, item);
8552
9126
  }
8553
- logger32.default("populate done", { item });
9127
+ logger37.default("populate done", { item });
8554
9128
  return item;
8555
9129
  };
8556
9130
  const populateAggregate = async (key, item) => {
8557
- logger32.default("populate aggregate key", { key });
9131
+ logger37.default("populate aggregate key", { key });
8558
9132
  const cacheConfig = toCacheConfig(aggregates[key]);
8559
9133
  if (item.refs === void 0) {
8560
9134
  if (cacheConfig.optional === false) {
8561
- logger32.error("Item does not have refs an is not optional ", { item });
8562
- throw new Error("Item does not have refs an is not optional " + JSON.stringify(item));
9135
+ logger37.error("Item missing required refs property", {
9136
+ component: "cache",
9137
+ subcomponent: "Aggregator",
9138
+ operation: "populateRef",
9139
+ refKey: key,
9140
+ item: JSON.stringify(item),
9141
+ suggestion: "Ensure the item has a refs property or mark this reference as optional in cache configuration"
9142
+ });
9143
+ throw new Error(
9144
+ `Item missing required refs property for reference '${key}'. Item: ${JSON.stringify(item)}. Suggestion: Add refs property to item or set optional: true in cache config.`
9145
+ );
8563
9146
  } else {
8564
9147
  if (item.events && Object.prototype.hasOwnProperty.call(item.events, key)) {
8565
9148
  delete item.events[key];
@@ -8567,8 +9150,18 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8567
9150
  }
8568
9151
  } else if (item.refs[key] === void 0) {
8569
9152
  if (cacheConfig.optional === false) {
8570
- logger32.error("Item does not have mandatory ref with key, not optional ", { key, item });
8571
- throw new Error("Item does not have mandatory ref with key, not optional " + key + " " + JSON.stringify(item));
9153
+ logger37.error("Item missing required reference", {
9154
+ component: "cache",
9155
+ subcomponent: "Aggregator",
9156
+ operation: "populateRef",
9157
+ refKey: key,
9158
+ availableRefs: Object.keys(item.refs || {}),
9159
+ item: JSON.stringify(item),
9160
+ suggestion: `Ensure the item has refs.${key} property or mark this reference as optional in cache configuration`
9161
+ });
9162
+ throw new Error(
9163
+ `Item missing required reference '${key}'. Available refs: [${Object.keys(item.refs || {}).join(", ")}]. Item: ${JSON.stringify(item)}. Suggestion: Add refs.${key} to item or set optional: true in cache config.`
9164
+ );
8572
9165
  } else {
8573
9166
  if (item.events && Object.prototype.hasOwnProperty.call(item.events, key)) {
8574
9167
  delete item.events[key];
@@ -8576,7 +9169,7 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8576
9169
  }
8577
9170
  } else {
8578
9171
  const ref = item.refs[key];
8579
- logger32.default("AGG Retrieving Item in Populate", { key: ref });
9172
+ logger37.default("AGG Retrieving Item in Populate", { key: ref });
8580
9173
  const newItem = await cacheConfig.cache.operations.retrieve(ref);
8581
9174
  if (newItem) {
8582
9175
  if (item.aggs === void 0) {
@@ -8593,25 +9186,52 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8593
9186
  }
8594
9187
  };
8595
9188
  const populateEvent = async (key, item) => {
8596
- logger32.default("populate event key", { key });
9189
+ logger37.default("populate event key", { key });
8597
9190
  const cacheConfig = toCacheConfig(events[key]);
8598
9191
  if (item.events === void 0) {
8599
- throw new Error("Item does not have events " + JSON.stringify(item));
9192
+ logger37.error("Item missing events property", {
9193
+ component: "cache",
9194
+ subcomponent: "Aggregator",
9195
+ operation: "populateEvent",
9196
+ eventKey: key,
9197
+ item: JSON.stringify(item),
9198
+ suggestion: "Ensure the item has an events property with event data"
9199
+ });
9200
+ throw new Error(
9201
+ `Item missing events property for event '${key}'. Item: ${JSON.stringify(item)}. Suggestion: Ensure events are properly tracked on this item type.`
9202
+ );
8600
9203
  } else if (item.events[key] === void 0) {
8601
9204
  if (cacheConfig.optional === false) {
8602
- logger32.error("Item does not have mandatory event with key", { key, item });
8603
- throw new Error("Item does not have mandatory event with key " + key + " " + JSON.stringify(item));
9205
+ logger37.error("Item missing required event", {
9206
+ component: "cache",
9207
+ subcomponent: "Aggregator",
9208
+ operation: "populateEvent",
9209
+ eventKey: key,
9210
+ availableEvents: Object.keys(item.events || {}),
9211
+ item: JSON.stringify(item),
9212
+ suggestion: `Ensure the item has events.${key} property or mark this event as optional`
9213
+ });
9214
+ throw new Error(
9215
+ `Item missing required event '${key}'. Available events: [${Object.keys(item.events || {}).join(", ")}]. Item: ${JSON.stringify(item)}. Suggestion: Add events.${key} to item or set optional: true in cache config.`
9216
+ );
8604
9217
  }
8605
9218
  } else {
8606
9219
  const event = item.events[key];
8607
9220
  if (event.by === void 0) {
8608
- logger32.error(
8609
- "populateEvent with an Event that does not have by",
8610
- { event, ik: item.key, eventKey: key }
9221
+ logger37.error('Event missing required "by" field', {
9222
+ component: "cache",
9223
+ subcomponent: "Aggregator",
9224
+ operation: "populateEvent",
9225
+ eventKey: key,
9226
+ event,
9227
+ itemKey: item.key,
9228
+ suggestion: 'Ensure event has a "by" field with the user/actor who triggered the event'
9229
+ });
9230
+ throw new Error(
9231
+ `Event '${key}' missing required "by" field. Event: ${JSON.stringify(event)}. Item: ${JSON.stringify(item.key)}. Suggestion: Events must include a "by" field to track who performed the action.`
8611
9232
  );
8612
- throw new Error("populateEvent with an Event that does not have by: " + JSON.stringify({ key }));
8613
9233
  }
8614
- logger32.default("EVENT Retrieving Item in Populate", { key: event.by });
9234
+ logger37.default("EVENT Retrieving Item in Populate", { key: event.by });
8615
9235
  const newItem = await cacheConfig.cache.operations.retrieve(event.by);
8616
9236
  if (newItem) {
8617
9237
  event.agg = newItem;
@@ -8619,13 +9239,13 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8619
9239
  }
8620
9240
  };
8621
9241
  const all2 = async (query = {}, locations = []) => {
8622
- logger32.default("all", { query, locations });
9242
+ logger37.default("all", { query, locations });
8623
9243
  const result = await cache.operations.all(query, locations);
8624
9244
  const populatedItems = await Promise.all(result.items.map(async (item) => populate(item)));
8625
9245
  return populatedItems;
8626
9246
  };
8627
9247
  const one2 = async (query = {}, locations = []) => {
8628
- logger32.default("one", { query, locations });
9248
+ logger37.default("one", { query, locations });
8629
9249
  const item = await cache.operations.one(query, locations);
8630
9250
  let populatedItem = null;
8631
9251
  if (item) {
@@ -8634,30 +9254,30 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8634
9254
  return populatedItem;
8635
9255
  };
8636
9256
  const action2 = async (key, action3, body = {}) => {
8637
- logger32.default("action", { key, action: action3, body });
9257
+ logger37.default("action", { key, action: action3, body });
8638
9258
  const [item, affectedItems] = await cache.operations.action(key, action3, body);
8639
9259
  const populatedItem = await populate(item);
8640
9260
  return [populatedItem, affectedItems];
8641
9261
  };
8642
9262
  const allAction2 = async (action3, body = {}, locations = []) => {
8643
- logger32.default("action", { action: action3, body, locations });
9263
+ logger37.default("action", { action: action3, body, locations });
8644
9264
  const [items, affectedItems] = await cache.operations.allAction(action3, body, locations);
8645
9265
  const populatedItems = await Promise.all(items.map(async (item) => populate(item)));
8646
9266
  return [populatedItems, affectedItems];
8647
9267
  };
8648
9268
  const allFacet2 = async (facet3, params = {}, locations = []) => {
8649
- logger32.default("allFacet", { facet: facet3, params, locations });
9269
+ logger37.default("allFacet", { facet: facet3, params, locations });
8650
9270
  const response = await cache.operations.allFacet(facet3, params, locations);
8651
9271
  return response;
8652
9272
  };
8653
9273
  const create2 = async (v, locations = []) => {
8654
- logger32.default("create", { v, locations });
9274
+ logger37.default("create", { v, locations });
8655
9275
  const item = locations.length === 0 ? await cache.operations.create(v) : await cache.operations.create(v, { locations });
8656
9276
  const populatedItem = await populate(item);
8657
9277
  return populatedItem;
8658
9278
  };
8659
9279
  const get2 = async (key) => {
8660
- logger32.default("get", { key });
9280
+ logger37.default("get", { key });
8661
9281
  const item = await cache.operations.get(key);
8662
9282
  let populatedItem = null;
8663
9283
  if (item) {
@@ -8666,7 +9286,7 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8666
9286
  return populatedItem;
8667
9287
  };
8668
9288
  const retrieve2 = async (key) => {
8669
- logger32.default("retrieve", { key });
9289
+ logger37.default("retrieve", { key });
8670
9290
  const item = await cache.operations.retrieve(key);
8671
9291
  let populatedItem = null;
8672
9292
  if (item) {
@@ -8675,22 +9295,22 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8675
9295
  return populatedItem;
8676
9296
  };
8677
9297
  const remove2 = async (key) => {
8678
- logger32.default("remove", { key });
9298
+ logger37.default("remove", { key });
8679
9299
  await cache.operations.remove(key);
8680
9300
  };
8681
9301
  const update2 = async (key, v) => {
8682
- logger32.default("update", { key, v });
9302
+ logger37.default("update", { key, v });
8683
9303
  const item = await cache.operations.update(key, v);
8684
9304
  const populatedItem = await populate(item);
8685
9305
  return populatedItem;
8686
9306
  };
8687
9307
  const facet2 = async (key, facet3) => {
8688
- logger32.default("facet", { key, facet: facet3 });
9308
+ logger37.default("facet", { key, facet: facet3 });
8689
9309
  const response = await cache.operations.facet(key, facet3);
8690
9310
  return response;
8691
9311
  };
8692
9312
  const find2 = async (finder, finderParams = {}, locations = [], findOptions) => {
8693
- logger32.default("find", { finder, finderParams, locations, findOptions });
9313
+ logger37.default("find", { finder, finderParams, locations, findOptions });
8694
9314
  const result = await cache.operations.find(finder, finderParams, locations, findOptions);
8695
9315
  const populatedItems = await Promise.all(result.items.map(async (item) => populate(item)));
8696
9316
  return {
@@ -8699,7 +9319,7 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8699
9319
  };
8700
9320
  };
8701
9321
  const findOne2 = async (finder, finderParams = {}, locations = []) => {
8702
- logger32.default("find", { finder, finderParams, locations });
9322
+ logger37.default("find", { finder, finderParams, locations });
8703
9323
  const item = await cache.operations.findOne(finder, finderParams, locations);
8704
9324
  if (!item) {
8705
9325
  return null;
@@ -8708,7 +9328,7 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8708
9328
  return populatedItem;
8709
9329
  };
8710
9330
  const set2 = async (key, v) => {
8711
- logger32.default("set", { key, v });
9331
+ logger37.default("set", { key, v });
8712
9332
  const item = await cache.operations.set(key, v);
8713
9333
  const populatedItem = await populate(item);
8714
9334
  return populatedItem;
@@ -8760,13 +9380,13 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8760
9380
  import {
8761
9381
  createRegistry as createBaseRegistry
8762
9382
  } from "@fjell/registry";
8763
- var logger33 = logger_default.get("Registry");
9383
+ var logger38 = logger_default.get("Registry");
8764
9384
  var createRegistryFactory = () => {
8765
9385
  return (type, registryHub) => {
8766
9386
  if (type !== "cache") {
8767
9387
  throw new Error(`Cache registry factory can only create 'cache' type registries, got: ${type}`);
8768
9388
  }
8769
- logger33.debug("Creating cache registry", { type, registryHub });
9389
+ logger38.debug("Creating cache registry", { type, registryHub });
8770
9390
  const baseRegistry = createBaseRegistry(type, registryHub);
8771
9391
  return baseRegistry;
8772
9392
  };