@fjell/cache 4.7.60 → 4.7.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -606,7 +606,20 @@ var createQueryHash = (pkType, query, locations) => {
606
606
  };
607
607
  const hash = deterministicStringify(hashInput);
608
608
  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 })}`);
609
+ const errorContext = {
610
+ component: "cache",
611
+ subcomponent: "normalization",
612
+ operation: "createQueryHash",
613
+ pkType,
614
+ query: JSON.stringify(query),
615
+ locations: JSON.stringify(locations),
616
+ hashResult: hash,
617
+ suggestion: "This indicates a bug in query normalization. Check query and location structures."
618
+ };
619
+ console.error("Invalid query hash generated:", JSON.stringify(errorContext, null, 2));
620
+ throw new Error(
621
+ `Invalid query hash generated: hash is empty or invalid. Input: ${JSON.stringify({ pkType, query, locations })}. This indicates a bug in query normalization logic.`
622
+ );
610
623
  }
611
624
  return hash;
612
625
  };
@@ -866,10 +879,27 @@ async function executeAllLogic(query, locations, context, allOptions) {
866
879
  logger4.debug("Cache bypass enabled, fetching directly from API", { query, locations });
867
880
  try {
868
881
  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 });
882
+ logger4.debug("API response received (not cached due to bypass)", {
883
+ operation: "all",
884
+ mode: "bypass",
885
+ query,
886
+ locations,
887
+ itemCount: ret.items.length,
888
+ metadata: ret.metadata
889
+ });
870
890
  return ret;
871
891
  } catch (error) {
872
- logger4.error("API request failed", { query, locations, error });
892
+ logger4.error("API request failed in bypass mode", {
893
+ operation: "all",
894
+ mode: "bypass",
895
+ query,
896
+ locations,
897
+ errorType: error.constructor?.name || typeof error,
898
+ errorMessage: error.message,
899
+ errorCode: error.code || error.errorInfo?.code,
900
+ suggestion: "Verify API endpoint is accessible, query syntax is correct, and locations are valid",
901
+ error
902
+ });
873
903
  throw error;
874
904
  }
875
905
  }
@@ -955,8 +985,15 @@ async function executeAllLogic(query, locations, context, allOptions) {
955
985
  }
956
986
  } catch (error) {
957
987
  logger4.debug("QUERY_CACHE: Error querying cache directly, proceeding to API", {
988
+ operation: "all",
989
+ phase: "cache-query",
958
990
  queryHash,
959
- error: error instanceof Error ? error.message : String(error)
991
+ query: JSON.stringify(query),
992
+ locations: JSON.stringify(locations),
993
+ errorType: error.constructor?.name || typeof error,
994
+ errorMessage: error instanceof Error ? error.message : String(error),
995
+ cacheType: cacheMap.implementationType,
996
+ note: "This is expected behavior - falling back to API when cache query fails"
960
997
  });
961
998
  }
962
999
  } else {
@@ -1031,9 +1068,19 @@ async function executeAllLogic(query, locations, context, allOptions) {
1031
1068
  await cacheMap.setQueryResult(queryHash, []);
1032
1069
  logger4.debug("QUERY_CACHE: Cached empty query result for not found", { queryHash });
1033
1070
  } else {
1034
- logger4.debug("QUERY_CACHE: API error occurred", {
1071
+ logger4.error("QUERY_CACHE: API error occurred during all() operation", {
1072
+ operation: "all",
1073
+ phase: "api-fetch",
1035
1074
  queryHash,
1036
- error: e instanceof Error ? e.message : String(e)
1075
+ query: JSON.stringify(query),
1076
+ locations: JSON.stringify(locations),
1077
+ errorType: e instanceof Error ? e.constructor.name : typeof e,
1078
+ errorMessage: e instanceof Error ? e.message : String(e),
1079
+ errorCode: e.code || e.errorInfo?.code,
1080
+ cacheType: cacheMap.implementationType,
1081
+ inFlightRequestsCount: inFlightRequests.size,
1082
+ suggestion: "Check API connectivity, query syntax, location keys, and network connectivity",
1083
+ error: e
1037
1084
  });
1038
1085
  throw e;
1039
1086
  }
@@ -1405,27 +1452,63 @@ var create = async (v, locations = [], context) => {
1405
1452
  return [context, result];
1406
1453
  };
1407
1454
  async function executeCreateLogic(v, locations, context) {
1455
+ const startTime = Date.now();
1408
1456
  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);
1457
+ try {
1458
+ logger6.debug("CACHE_OP: create() started", {
1459
+ operation: "create",
1460
+ itemType: pkType,
1461
+ hasLocations: locations.length > 0,
1462
+ locationCount: locations.length,
1463
+ itemData: JSON.stringify(v)
1464
+ });
1465
+ const created = await api.create(v, locations.length > 0 ? { locations } : void 0);
1466
+ const apiDuration = Date.now() - startTime;
1467
+ cacheMap.set(created.key, created);
1468
+ const keyStr = JSON.stringify(created.key);
1469
+ ttlManager.onItemAdded(keyStr, cacheMap);
1470
+ const evictedKeys = await evictionManager.onItemAdded(keyStr, created, cacheMap);
1471
+ for (const evictedKey of evictedKeys) {
1472
+ const parsedKey = JSON.parse(evictedKey);
1473
+ await cacheMap.delete(parsedKey);
1474
+ }
1475
+ await cacheMap.clearQueryResults();
1476
+ const itemEvent = CacheEventFactory.itemCreated(created.key, created, "api");
1477
+ eventEmitter.emit(itemEvent);
1478
+ const queryInvalidatedEvent = CacheEventFactory.createQueryInvalidatedEvent(
1479
+ [],
1480
+ // We don't track which specific queries were invalidated
1481
+ "item_changed",
1482
+ { source: "operation", context: { operation: "create" } }
1483
+ );
1484
+ eventEmitter.emit(queryInvalidatedEvent);
1485
+ const totalDuration = Date.now() - startTime;
1486
+ logger6.debug("CACHE_OP: create() completed successfully", {
1487
+ operation: "create",
1488
+ itemType: pkType,
1489
+ key: keyStr,
1490
+ evictedCount: evictedKeys.length,
1491
+ apiDuration,
1492
+ totalDuration
1493
+ });
1494
+ return created;
1495
+ } catch (e) {
1496
+ const duration = Date.now() - startTime;
1497
+ logger6.error("CACHE_OP: create() operation failed", {
1498
+ operation: "create",
1499
+ itemType: pkType,
1500
+ itemData: JSON.stringify(v),
1501
+ locations: JSON.stringify(locations),
1502
+ duration,
1503
+ errorType: e.constructor?.name || typeof e,
1504
+ errorMessage: e.message,
1505
+ errorCode: e.code || e.errorInfo?.code,
1506
+ cacheType: cacheMap.implementationType,
1507
+ suggestion: "Check validation errors, duplicate constraints, required fields, and API connectivity",
1508
+ stack: e.stack
1509
+ });
1510
+ throw e;
1417
1511
  }
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
1512
  }
1430
1513
 
1431
1514
  // src/ops/get.ts
@@ -1475,8 +1558,15 @@ async function executeGetLogic(key, context) {
1475
1558
  });
1476
1559
  statsManager.incrementRequests();
1477
1560
  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");
1561
+ logger7.error("CACHE_OP: Invalid key for get operation", {
1562
+ key: keyStr,
1563
+ keyType: typeof key,
1564
+ reason: "Key validation failed - must be a valid PriKey or ComKey",
1565
+ suggestion: "Ensure the key has the correct structure: PriKey { kt, pk } or ComKey { kt, sk, lk }",
1566
+ itemType: pkType,
1567
+ coordinate: JSON.stringify(context.coordinate)
1568
+ });
1569
+ throw new Error(`Invalid key for get operation: ${keyStr}. Expected valid PriKey or ComKey structure.`);
1480
1570
  }
1481
1571
  if (context.options?.bypassCache) {
1482
1572
  logger7.debug("CACHE_OP: Cache bypass enabled, fetching directly from API", { key: keyStr });
@@ -1501,8 +1591,15 @@ async function executeGetLogic(key, context) {
1501
1591
  }
1502
1592
  } catch (error) {
1503
1593
  logger7.error("CACHE_OP: API request failed in bypass mode", {
1594
+ operation: "get",
1595
+ mode: "bypass",
1504
1596
  key: keyStr,
1597
+ itemType: pkType,
1505
1598
  duration: Date.now() - startTime,
1599
+ errorType: error.constructor?.name || typeof error,
1600
+ errorMessage: error.message,
1601
+ errorCode: error.code || error.errorInfo?.code,
1602
+ suggestion: "Verify API endpoint is accessible and key exists. Cache bypass mode does not retry.",
1506
1603
  error
1507
1604
  });
1508
1605
  throw error;
@@ -1671,10 +1768,19 @@ async function executeGetLogic(key, context) {
1671
1768
  } catch (e) {
1672
1769
  inFlightRequests2.delete(requestKeyStr);
1673
1770
  const duration = Date.now() - startTime;
1674
- logger7.error("CACHE_OP: Error in get() operation", {
1771
+ logger7.error("CACHE_OP: get() operation failed", {
1772
+ operation: "get",
1675
1773
  key: keyStr,
1774
+ itemType: pkType,
1676
1775
  duration,
1677
- message: e.message,
1776
+ errorType: e.constructor?.name || typeof e,
1777
+ errorMessage: e.message,
1778
+ errorCode: e.code || e.errorInfo?.code,
1779
+ cacheType: cacheMap.implementationType,
1780
+ ttlEnabled: ttlManager.isTTLEnabled(),
1781
+ bypassMode: context.options?.bypassCache || false,
1782
+ inFlightRequestsCount: inFlightRequests2.size,
1783
+ suggestion: "Check API connectivity, key validity, and cache configuration",
1678
1784
  stack: e.stack
1679
1785
  });
1680
1786
  throw e;
@@ -1798,13 +1904,27 @@ var remove = async (key, context) => {
1798
1904
  };
1799
1905
  async function executeRemoveLogic(key, context) {
1800
1906
  const { api, cacheMap } = context;
1907
+ const keyStr = JSON.stringify(key);
1801
1908
  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");
1909
+ logger9.error("CACHE_OP: Invalid key for remove operation", {
1910
+ operation: "remove",
1911
+ key: keyStr,
1912
+ keyType: typeof key,
1913
+ reason: "Key validation failed - must be a valid PriKey or ComKey",
1914
+ suggestion: "Ensure the key has the correct structure: PriKey { kt, pk } or ComKey { kt, sk, lk }"
1915
+ });
1916
+ throw new Error(`Invalid key for remove operation: ${keyStr}. Expected valid PriKey or ComKey structure.`);
1804
1917
  }
1918
+ const startTime = Date.now();
1805
1919
  try {
1920
+ logger9.debug("CACHE_OP: remove() started", {
1921
+ operation: "remove",
1922
+ key: keyStr,
1923
+ cacheType: cacheMap.implementationType
1924
+ });
1806
1925
  const previousItem = await cacheMap.get(key);
1807
1926
  await api.remove(key);
1927
+ const apiDuration = Date.now() - startTime;
1808
1928
  cacheMap.delete(key);
1809
1929
  await cacheMap.clearQueryResults();
1810
1930
  if (previousItem) {
@@ -1817,9 +1937,27 @@ async function executeRemoveLogic(key, context) {
1817
1937
  { source: "operation", context: { operation: "remove" } }
1818
1938
  );
1819
1939
  context.eventEmitter.emit(queryInvalidatedEvent);
1820
- logger9.debug("Successfully removed item from API and cache", { key });
1940
+ const totalDuration = Date.now() - startTime;
1941
+ logger9.debug("CACHE_OP: remove() completed successfully", {
1942
+ operation: "remove",
1943
+ key: keyStr,
1944
+ hadCachedItem: !!previousItem,
1945
+ apiDuration,
1946
+ totalDuration
1947
+ });
1821
1948
  } catch (e) {
1822
- logger9.error("Error deleting item", { error: e });
1949
+ const duration = Date.now() - startTime;
1950
+ logger9.error("CACHE_OP: remove() operation failed", {
1951
+ operation: "remove",
1952
+ key: keyStr,
1953
+ duration,
1954
+ errorType: e.constructor?.name || typeof e,
1955
+ errorMessage: e.message,
1956
+ errorCode: e.code || e.errorInfo?.code,
1957
+ cacheType: cacheMap.implementationType,
1958
+ suggestion: "Check item exists, delete permissions, referential integrity constraints, and API connectivity",
1959
+ stack: e.stack
1960
+ });
1823
1961
  throw e;
1824
1962
  }
1825
1963
  }
@@ -1845,33 +1983,52 @@ var update = async (key, v, context) => {
1845
1983
  async function executeUpdateLogic(key, v, context) {
1846
1984
  const { api, cacheMap, pkType } = context;
1847
1985
  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");
1986
+ logger10.error("CACHE_OP: Invalid key for update operation", {
1987
+ operation: "update",
1988
+ key: JSON.stringify(key),
1989
+ keyType: typeof key,
1990
+ itemType: pkType,
1991
+ reason: "Key validation failed - must be a valid PriKey or ComKey",
1992
+ suggestion: "Ensure the key has the correct structure: PriKey { kt, pk } or ComKey { kt, sk, lk }"
1993
+ });
1994
+ throw new Error(`Invalid key for update operation: ${JSON.stringify(key)}. Expected valid PriKey or ComKey structure.`);
1850
1995
  }
1851
1996
  logger10.debug("Invalidating item key before update", { key });
1852
1997
  cacheMap.invalidateItemKeys([key]);
1853
1998
  await cacheMap.clearQueryResults();
1999
+ const startTime = Date.now();
2000
+ const keyStr = JSON.stringify(key);
1854
2001
  try {
2002
+ logger10.debug("CACHE_OP: update() started", {
2003
+ operation: "update",
2004
+ key: keyStr,
2005
+ itemType: pkType,
2006
+ updateData: JSON.stringify(v)
2007
+ });
1855
2008
  const previousItem = await cacheMap.get(key);
1856
2009
  const updated = await api.update(key, v);
1857
- logger10.debug("Caching update result", { updatedKey: updated.key });
2010
+ const apiDuration = Date.now() - startTime;
2011
+ logger10.debug("CACHE_OP: Caching update result", {
2012
+ operation: "update",
2013
+ updatedKey: JSON.stringify(updated.key)
2014
+ });
1858
2015
  await cacheMap.set(updated.key, updated);
1859
2016
  const cachedItem = await cacheMap.get(updated.key);
1860
- const keyStr = JSON.stringify(updated.key);
1861
- const metadata = await cacheMap.getMetadata(keyStr);
2017
+ const updatedKeyStr = JSON.stringify(updated.key);
2018
+ const metadata = await cacheMap.getMetadata(updatedKeyStr);
1862
2019
  if (!metadata) {
1863
2020
  const now = Date.now();
1864
2021
  const baseMetadata = {
1865
- key: keyStr,
2022
+ key: updatedKeyStr,
1866
2023
  addedAt: now,
1867
2024
  lastAccessedAt: now,
1868
2025
  accessCount: 1,
1869
2026
  estimatedSize: estimateValueSize(updated)
1870
2027
  };
1871
- await cacheMap.setMetadata(keyStr, baseMetadata);
2028
+ await cacheMap.setMetadata(updatedKeyStr, baseMetadata);
1872
2029
  }
1873
- await context.ttlManager.onItemAdded(keyStr, cacheMap);
1874
- const evictedKeys = await context.evictionManager.onItemAdded(keyStr, updated, cacheMap);
2030
+ await context.ttlManager.onItemAdded(updatedKeyStr, cacheMap);
2031
+ const evictedKeys = await context.evictionManager.onItemAdded(updatedKeyStr, updated, cacheMap);
1875
2032
  for (const evictedKey of evictedKeys) {
1876
2033
  const parsedKey = JSON.parse(evictedKey);
1877
2034
  await cacheMap.delete(parsedKey);
@@ -1885,9 +2042,31 @@ async function executeUpdateLogic(key, v, context) {
1885
2042
  { source: "operation", context: { operation: "update" } }
1886
2043
  );
1887
2044
  context.eventEmitter.emit(queryInvalidatedEvent);
2045
+ const totalDuration = Date.now() - startTime;
2046
+ logger10.debug("CACHE_OP: update() completed successfully", {
2047
+ operation: "update",
2048
+ key: updatedKeyStr,
2049
+ itemType: pkType,
2050
+ evictedCount: evictedKeys.length,
2051
+ apiDuration,
2052
+ totalDuration
2053
+ });
1888
2054
  return updated;
1889
2055
  } catch (e) {
1890
- logger10.error("Error updating item", { error: e });
2056
+ const duration = Date.now() - startTime;
2057
+ logger10.error("CACHE_OP: update() operation failed", {
2058
+ operation: "update",
2059
+ key: keyStr,
2060
+ itemType: pkType,
2061
+ updateData: JSON.stringify(v),
2062
+ duration,
2063
+ errorType: e.constructor?.name || typeof e,
2064
+ errorMessage: e.message,
2065
+ errorCode: e.code || e.errorInfo?.code,
2066
+ cacheType: cacheMap.implementationType,
2067
+ suggestion: "Check item exists, validation rules, update permissions, and API connectivity",
2068
+ stack: e.stack
2069
+ });
1891
2070
  throw e;
1892
2071
  }
1893
2072
  }
@@ -3524,7 +3703,17 @@ var LocalStorageCacheMap = class _LocalStorageCacheMap extends CacheMap {
3524
3703
  const useAggressiveCleanup = attempt > 0;
3525
3704
  this.tryCleanupOldEntries(useAggressiveCleanup);
3526
3705
  if (isLastAttempt) {
3527
- throw new Error("Failed to store item in localStorage: storage quota exceeded even after multiple cleanup attempts");
3706
+ logger21.error("LocalStorage quota exceeded after all cleanup attempts", {
3707
+ component: "cache",
3708
+ subcomponent: "LocalStorageCacheMap",
3709
+ operation: "set",
3710
+ key: JSON.stringify(key),
3711
+ retryAttempts: attempt + 1,
3712
+ suggestion: "Reduce cache size limits, clear more data, or use IndexedDB for larger storage needs"
3713
+ });
3714
+ throw new Error(
3715
+ "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."
3716
+ );
3528
3717
  }
3529
3718
  continue;
3530
3719
  }
@@ -3665,8 +3854,18 @@ var LocalStorageCacheMap = class _LocalStorageCacheMap extends CacheMap {
3665
3854
  async setQueryResult(queryHash, itemKeys, metadata) {
3666
3855
  logger21.trace("setQueryResult", { queryHash, itemKeys, hasMetadata: !!metadata });
3667
3856
  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)}`);
3857
+ logger21.error("Invalid queryHash provided to setQueryResult", {
3858
+ component: "cache",
3859
+ subcomponent: "LocalStorageCacheMap",
3860
+ operation: "setQueryResult",
3861
+ queryHash,
3862
+ queryHashType: typeof queryHash,
3863
+ itemKeys,
3864
+ suggestion: "Ensure queryHash is a non-empty string generated from query normalization"
3865
+ });
3866
+ throw new Error(
3867
+ `Invalid queryHash provided to setQueryResult: ${JSON.stringify(queryHash)}. Expected non-empty string, got ${typeof queryHash}. This usually indicates a bug in query hash generation.`
3868
+ );
3670
3869
  }
3671
3870
  const queryKey = `${this.keyPrefix}:query:${queryHash}`;
3672
3871
  const entry = {
@@ -4081,8 +4280,19 @@ var SessionStorageCacheMap = class _SessionStorageCacheMap extends CacheMap {
4081
4280
  const jsonString = safeStringify2(toStore);
4082
4281
  sessionStorage.setItem(storageKey, jsonString);
4083
4282
  } catch (error) {
4084
- logger22.error("Error storing to sessionStorage", { errorMessage: error?.message });
4085
- throw new Error(`Failed to store item in sessionStorage: ${error}`);
4283
+ const isQuotaError = error?.name === "QuotaExceededError" || error?.message?.includes("quota") || error?.code === 22;
4284
+ logger22.error("Error storing to sessionStorage", {
4285
+ component: "cache",
4286
+ subcomponent: "SessionStorageCacheMap",
4287
+ operation: "set",
4288
+ key: JSON.stringify(key),
4289
+ errorType: error?.name,
4290
+ errorMessage: error?.message,
4291
+ isQuotaError,
4292
+ suggestion: isQuotaError ? "SessionStorage quota exceeded. Clear old data, reduce cache size, or use IndexedDB instead." : "Check browser sessionStorage support and data serializability."
4293
+ });
4294
+ const errorMsg = isQuotaError ? "SessionStorage quota exceeded. Try clearing old cache data or reducing cache size." : `Failed to store item in sessionStorage: ${error?.message || error}`;
4295
+ throw new Error(errorMsg);
4086
4296
  }
4087
4297
  }
4088
4298
  async includesKey(key) {
@@ -4667,8 +4877,18 @@ var AsyncIndexDBCacheMap = class _AsyncIndexDBCacheMap {
4667
4877
  try {
4668
4878
  storageKey = this.getStorageKey(key);
4669
4879
  } 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}`);
4880
+ logger23.error("Storage key generation failed", {
4881
+ component: "cache",
4882
+ subcomponent: "AsyncIndexDBCacheMap",
4883
+ operation: "set",
4884
+ key: JSON.stringify(key),
4885
+ errorType: keyError?.constructor?.name,
4886
+ errorMessage: keyError?.message,
4887
+ suggestion: "Check key structure and normalization logic"
4888
+ });
4889
+ throw new Error(
4890
+ `Failed to generate storage key for IndexedDB: ${keyError?.message || keyError}. Key: ${JSON.stringify(key)}. This indicates a key normalization issue.`
4891
+ );
4672
4892
  }
4673
4893
  const storedItem = {
4674
4894
  originalKey: key,
@@ -4692,8 +4912,19 @@ var AsyncIndexDBCacheMap = class _AsyncIndexDBCacheMap {
4692
4912
  }
4693
4913
  });
4694
4914
  } catch (error) {
4695
- logger23.error("Error in IndexedDB set operation", { key, value, error });
4696
- throw new Error(`Failed to store item in IndexedDB: ${error}`);
4915
+ const isQuotaError = error?.name === "QuotaExceededError" || error?.message?.includes("quota");
4916
+ logger23.error("Error in IndexedDB set operation", {
4917
+ component: "cache",
4918
+ subcomponent: "AsyncIndexDBCacheMap",
4919
+ operation: "set",
4920
+ key: JSON.stringify(key),
4921
+ errorType: error?.name,
4922
+ errorMessage: error?.message,
4923
+ isQuotaError,
4924
+ suggestion: isQuotaError ? "IndexedDB quota exceeded. Clear old data, reduce cache size, or request more storage quota." : "Check IndexedDB support, permissions, and data serializability."
4925
+ });
4926
+ const errorMsg = isQuotaError ? "IndexedDB quota exceeded. Try clearing old cache data or reducing cache size." : `Failed to store item in IndexedDB: ${error?.message || error}`;
4927
+ throw new Error(errorMsg);
4697
4928
  }
4698
4929
  }
4699
4930
  /**
@@ -5573,6 +5804,7 @@ var IndexDBCacheMap = class _IndexDBCacheMap extends CacheMap {
5573
5804
  };
5574
5805
 
5575
5806
  // src/Options.ts
5807
+ var logger25 = logger_default.get("Options");
5576
5808
  var DEFAULT_CACHE_OPTIONS = {
5577
5809
  cacheType: "memory",
5578
5810
  enableDebugLogging: false,
@@ -5676,12 +5908,29 @@ var createCacheMap = (kta, options) => {
5676
5908
  break;
5677
5909
  case "custom":
5678
5910
  if (!options.customCacheMapFactory) {
5679
- throw new Error('Custom cache map factory is required when cacheType is "custom"');
5911
+ logger25.error("Custom cache map factory missing", {
5912
+ component: "cache",
5913
+ operation: "createCacheMap",
5914
+ cacheType: "custom",
5915
+ suggestion: 'Provide customCacheMapFactory function in cache options when using cacheType: "custom"'
5916
+ });
5917
+ throw new Error(
5918
+ 'Custom cache map factory is required when cacheType is "custom". Provide customCacheMapFactory in cache options.'
5919
+ );
5680
5920
  }
5681
5921
  underlyingCache = options.customCacheMapFactory(kta);
5682
5922
  break;
5683
5923
  default:
5684
- throw new Error(`Unsupported cache type: ${options.cacheType}`);
5924
+ logger25.error("Unsupported cache type", {
5925
+ component: "cache",
5926
+ operation: "createCacheMap",
5927
+ cacheType: options.cacheType,
5928
+ validTypes: ["memory", "localStorage", "sessionStorage", "indexedDB", "asyncIndexedDB", "custom"],
5929
+ suggestion: "Use one of: memory, localStorage, sessionStorage, indexedDB, asyncIndexedDB, or custom"
5930
+ });
5931
+ throw new Error(
5932
+ `Unsupported cache type: ${options.cacheType}. Valid types: memory, localStorage, sessionStorage, indexedDB, asyncIndexedDB, custom.`
5933
+ );
5685
5934
  }
5686
5935
  if (options.twoLayer && Object.keys(options.twoLayer).length > 0) {
5687
5936
  return new TwoLayerCacheMap(underlyingCache, options.twoLayer);
@@ -5762,19 +6011,29 @@ Did you mean: ${suggestions.join(", ")}?`;
5762
6011
  throw new Error(errorMessage);
5763
6012
  }
5764
6013
  if (options.cacheType === "custom" && !options.customCacheMapFactory) {
5765
- throw new Error('customCacheMapFactory is required when cacheType is "custom"');
6014
+ throw new Error(
6015
+ 'customCacheMapFactory is required when cacheType is "custom". Provide a factory function that creates your custom CacheMap implementation.'
6016
+ );
5766
6017
  }
5767
6018
  if (typeof options.maxRetries === "number" && options.maxRetries < 0) {
5768
- throw new Error("maxRetries must be non-negative");
6019
+ throw new Error(
6020
+ `maxRetries must be non-negative, got ${options.maxRetries}. Suggestion: Use 0 or positive integer for retry attempts.`
6021
+ );
5769
6022
  }
5770
6023
  if (typeof options.retryDelay === "number" && options.retryDelay < 0) {
5771
- throw new Error("retryDelay must be non-negative");
6024
+ throw new Error(
6025
+ `retryDelay must be non-negative, got ${options.retryDelay}ms. Suggestion: Use 0 or positive number for delay in milliseconds.`
6026
+ );
5772
6027
  }
5773
6028
  if (typeof options.ttl === "number" && options.ttl <= 0) {
5774
- throw new Error("ttl must be positive");
6029
+ throw new Error(
6030
+ `ttl must be positive, got ${options.ttl}. Suggestion: Use positive number for TTL in seconds, or 0 to disable TTL.`
6031
+ );
5775
6032
  }
5776
6033
  if (typeof options.memoryConfig?.maxItems === "number" && options.memoryConfig.maxItems <= 0) {
5777
- throw new Error("memoryConfig.maxItems must be positive");
6034
+ throw new Error(
6035
+ `memoryConfig.maxItems must be positive, got ${options.memoryConfig.maxItems}. Suggestion: Use positive integer for maximum cache items.`
6036
+ );
5778
6037
  }
5779
6038
  if (options.memoryConfig?.size) {
5780
6039
  validateSizeConfig(options.memoryConfig.size);
@@ -5874,16 +6133,43 @@ Did you mean: ${suggestions.join(", ")}?`);
5874
6133
  if (["localStorage", "sessionStorage"].includes(options.cacheType)) {
5875
6134
  const isRealBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement === "function";
5876
6135
  if (!isRealBrowser) {
5877
- throw new Error(`${options.cacheType} is not available in non-browser environments`);
6136
+ logger25.error("Browser cache type used in non-browser environment", {
6137
+ component: "cache",
6138
+ operation: "validateOptions",
6139
+ cacheType: options.cacheType,
6140
+ environment: typeof window === "undefined" ? "node" : "unknown",
6141
+ suggestion: 'Use cacheType: "memory" for Node.js/server environments, or ensure code runs in browser'
6142
+ });
6143
+ throw new Error(
6144
+ `${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.`
6145
+ );
5878
6146
  }
5879
6147
  }
5880
6148
  if (options.cacheType === "indexedDB") {
5881
6149
  if (typeof window === "undefined" || !window.indexedDB) {
5882
- throw new Error(`${options.cacheType} is not available in this environment`);
6150
+ logger25.error("IndexedDB not available", {
6151
+ component: "cache",
6152
+ operation: "validateOptions",
6153
+ cacheType: "indexedDB",
6154
+ hasWindow: typeof window !== "undefined",
6155
+ hasIndexedDB: typeof window !== "undefined" && !!window.indexedDB,
6156
+ suggestion: "Use memory cache for Node.js, or check browser IndexedDB support"
6157
+ });
6158
+ throw new Error(
6159
+ `IndexedDB is not available in this environment. Browser support required. Suggestion: Use cacheType: "memory" for server-side or unsupported browsers.`
6160
+ );
5883
6161
  }
5884
6162
  }
5885
6163
  if (options.cacheType === "asyncIndexedDB") {
5886
- throw new Error("asyncIndexedDB cannot be used with synchronous cache factory. Use AsyncIndexDBCacheMap directly for async operations.");
6164
+ logger25.error("AsyncIndexedDB cannot be used with sync factory", {
6165
+ component: "cache",
6166
+ operation: "validateOptions",
6167
+ cacheType: "asyncIndexedDB",
6168
+ suggestion: 'Use AsyncIndexDBCacheMap directly for async operations, or use cacheType: "indexedDB" for sync wrapper'
6169
+ });
6170
+ throw new Error(
6171
+ 'asyncIndexedDB cannot be used with synchronous cache factory. Use AsyncIndexDBCacheMap directly for async operations, or use cacheType: "indexedDB" for the sync wrapper.'
6172
+ );
5887
6173
  }
5888
6174
  };
5889
6175
 
@@ -5898,7 +6184,11 @@ var reset = async (coordinate, options) => {
5898
6184
  }
5899
6185
  };
5900
6186
 
6187
+ // src/ttl/TTLCalculator.ts
6188
+ var logger26 = logger_default.get("TTLCalculator");
6189
+
5901
6190
  // src/ttl/TTLConfig.ts
6191
+ var logger27 = logger_default.get("TTLConfig");
5902
6192
  var defaultTTLConfig = {
5903
6193
  item: {
5904
6194
  default: 3600,
@@ -5997,10 +6287,10 @@ var highTrafficTTLConfig = {
5997
6287
  };
5998
6288
 
5999
6289
  // src/cache/warming/CacheWarmer.ts
6000
- var logger25 = logger_default.get("CacheWarmer");
6290
+ var logger28 = logger_default.get("CacheWarmer");
6001
6291
 
6002
6292
  // src/Operations.ts
6003
- var logger26 = logger_default.get("Operations");
6293
+ var logger29 = logger_default.get("Operations");
6004
6294
  var CacheMapOperations = class {
6005
6295
  constructor(api, coordinate, cacheMap, pkType, options, eventEmitter, ttlManager, evictionManager, statsManager, registry) {
6006
6296
  this.api = api;
@@ -6014,7 +6304,7 @@ var CacheMapOperations = class {
6014
6304
  this.statsManager = statsManager;
6015
6305
  this.registry = registry;
6016
6306
  if (this.options.enableDebugLogging) {
6017
- logger26.debug("CacheMapOperations initialized", {
6307
+ logger29.debug("CacheMapOperations initialized", {
6018
6308
  cacheType: this.cacheMap.implementationType,
6019
6309
  isTwoLayer: this.cacheMap instanceof TwoLayerCacheMap
6020
6310
  });
@@ -6107,7 +6397,7 @@ var createOperations = (api, coordinate, cacheMap, pkType, options, eventEmitter
6107
6397
  };
6108
6398
 
6109
6399
  // src/eviction/EvictionManager.ts
6110
- var logger27 = logger_default.get("EvictionManager");
6400
+ var logger30 = logger_default.get("EvictionManager");
6111
6401
  var EvictionManager = class {
6112
6402
  evictionStrategy;
6113
6403
  constructor(evictionStrategy) {
@@ -6119,7 +6409,7 @@ var EvictionManager = class {
6119
6409
  */
6120
6410
  setEvictionStrategy(strategy) {
6121
6411
  this.evictionStrategy = strategy;
6122
- logger27.debug("Eviction strategy updated", {
6412
+ logger30.debug("Eviction strategy updated", {
6123
6413
  strategy: strategy?.getStrategyName() || "none"
6124
6414
  });
6125
6415
  }
@@ -6140,13 +6430,13 @@ var EvictionManager = class {
6140
6430
  return;
6141
6431
  }
6142
6432
  try {
6143
- logger27.debug("EVICTION: Item accessed, updating metadata", {
6433
+ logger30.debug("EVICTION: Item accessed, updating metadata", {
6144
6434
  key,
6145
6435
  strategy: this.evictionStrategy.getStrategyName()
6146
6436
  });
6147
6437
  await this.evictionStrategy.onItemAccessed(key, metadataProvider);
6148
6438
  } catch (error) {
6149
- logger27.error("EVICTION: Error in eviction strategy onItemAccessed", {
6439
+ logger30.error("EVICTION: Error in eviction strategy onItemAccessed", {
6150
6440
  key,
6151
6441
  error,
6152
6442
  strategy: this.evictionStrategy?.getStrategyName()
@@ -6164,12 +6454,12 @@ var EvictionManager = class {
6164
6454
  const startTime = Date.now();
6165
6455
  const evictedKeys = [];
6166
6456
  if (!this.evictionStrategy) {
6167
- logger27.debug("EVICTION: No eviction strategy configured", { key });
6457
+ logger30.debug("EVICTION: No eviction strategy configured", { key });
6168
6458
  return evictedKeys;
6169
6459
  }
6170
6460
  try {
6171
6461
  const estimatedSize = estimateValueSize(value);
6172
- logger27.debug("EVICTION: Item addition started", {
6462
+ logger30.debug("EVICTION: Item addition started", {
6173
6463
  key,
6174
6464
  estimatedSize,
6175
6465
  strategy: this.evictionStrategy.getStrategyName()
@@ -6177,7 +6467,7 @@ var EvictionManager = class {
6177
6467
  const contextStartTime = Date.now();
6178
6468
  const context = await this.createEvictionContext(metadataProvider, estimatedSize);
6179
6469
  const contextDuration = Date.now() - contextStartTime;
6180
- logger27.debug("EVICTION: Current cache state", {
6470
+ logger30.debug("EVICTION: Current cache state", {
6181
6471
  key,
6182
6472
  currentItemCount: context.currentSize.itemCount,
6183
6473
  currentSizeBytes: context.currentSize.sizeBytes,
@@ -6190,7 +6480,7 @@ var EvictionManager = class {
6190
6480
  const keysToEvict = await this.evictionStrategy.selectForEviction(metadataProvider, context);
6191
6481
  const selectionDuration = Date.now() - selectionStartTime;
6192
6482
  if (keysToEvict.length > 0) {
6193
- logger27.debug("EVICTION: Items selected for eviction", {
6483
+ logger30.debug("EVICTION: Items selected for eviction", {
6194
6484
  key,
6195
6485
  evictCount: keysToEvict.length,
6196
6486
  keysToEvict,
@@ -6202,7 +6492,7 @@ var EvictionManager = class {
6202
6492
  for (const evictKey of keysToEvict) {
6203
6493
  await this.evictionStrategy.onItemRemoved(evictKey, metadataProvider);
6204
6494
  evictedKeys.push(evictKey);
6205
- logger27.debug("EVICTION: Marked item for eviction", {
6495
+ logger30.debug("EVICTION: Marked item for eviction", {
6206
6496
  evictedKey: evictKey,
6207
6497
  newKey: key
6208
6498
  });
@@ -6213,7 +6503,7 @@ var EvictionManager = class {
6213
6503
  const addMetadataDuration = Date.now() - addMetadataStart;
6214
6504
  const totalDuration = Date.now() - startTime;
6215
6505
  if (evictedKeys.length > 0) {
6216
- logger27.debug("EVICTION: Eviction completed", {
6506
+ logger30.debug("EVICTION: Eviction completed", {
6217
6507
  newKey: key,
6218
6508
  evictedCount: evictedKeys.length,
6219
6509
  evictedKeys,
@@ -6224,14 +6514,14 @@ var EvictionManager = class {
6224
6514
  totalDuration
6225
6515
  });
6226
6516
  } else {
6227
- logger27.debug("EVICTION: No eviction needed", {
6517
+ logger30.debug("EVICTION: No eviction needed", {
6228
6518
  newKey: key,
6229
6519
  estimatedSize,
6230
6520
  totalDuration
6231
6521
  });
6232
6522
  }
6233
6523
  } catch (error) {
6234
- logger27.error("EVICTION: Error in eviction strategy onItemAdded", {
6524
+ logger30.error("EVICTION: Error in eviction strategy onItemAdded", {
6235
6525
  key,
6236
6526
  error,
6237
6527
  strategy: this.evictionStrategy?.getStrategyName()
@@ -6251,7 +6541,7 @@ var EvictionManager = class {
6251
6541
  try {
6252
6542
  this.evictionStrategy.onItemRemoved(key, metadataProvider);
6253
6543
  } catch (error) {
6254
- logger27.error("Error in eviction strategy onItemRemoved", { key, error });
6544
+ logger30.error("Error in eviction strategy onItemRemoved", { key, error });
6255
6545
  }
6256
6546
  }
6257
6547
  /**
@@ -6263,15 +6553,15 @@ var EvictionManager = class {
6263
6553
  const startTime = Date.now();
6264
6554
  const evictedKeys = [];
6265
6555
  if (!this.evictionStrategy) {
6266
- logger27.debug("EVICTION: No eviction strategy configured for manual eviction");
6556
+ logger30.debug("EVICTION: No eviction strategy configured for manual eviction");
6267
6557
  return evictedKeys;
6268
6558
  }
6269
6559
  try {
6270
- logger27.debug("EVICTION: Manual eviction started", {
6560
+ logger30.debug("EVICTION: Manual eviction started", {
6271
6561
  strategy: this.evictionStrategy.getStrategyName()
6272
6562
  });
6273
6563
  const context = await this.createEvictionContext(metadataProvider);
6274
- logger27.debug("EVICTION: Manual eviction - current cache state", {
6564
+ logger30.debug("EVICTION: Manual eviction - current cache state", {
6275
6565
  currentItemCount: context.currentSize.itemCount,
6276
6566
  currentSizeBytes: context.currentSize.sizeBytes,
6277
6567
  maxItems: context.limits.maxItems,
@@ -6284,20 +6574,20 @@ var EvictionManager = class {
6284
6574
  }
6285
6575
  const duration = Date.now() - startTime;
6286
6576
  if (evictedKeys.length > 0) {
6287
- logger27.debug("EVICTION: Manual eviction completed", {
6577
+ logger30.debug("EVICTION: Manual eviction completed", {
6288
6578
  evictedCount: evictedKeys.length,
6289
6579
  evictedKeys,
6290
6580
  strategy: this.evictionStrategy.getStrategyName(),
6291
6581
  duration
6292
6582
  });
6293
6583
  } else {
6294
- logger27.debug("EVICTION: Manual eviction - no items to evict", {
6584
+ logger30.debug("EVICTION: Manual eviction - no items to evict", {
6295
6585
  strategy: this.evictionStrategy.getStrategyName(),
6296
6586
  duration
6297
6587
  });
6298
6588
  }
6299
6589
  } catch (error) {
6300
- logger27.error("EVICTION: Error in manual eviction", {
6590
+ logger30.error("EVICTION: Error in manual eviction", {
6301
6591
  error,
6302
6592
  strategy: this.evictionStrategy?.getStrategyName()
6303
6593
  });
@@ -6320,7 +6610,7 @@ var EvictionManager = class {
6320
6610
  this.evictionStrategy.reset();
6321
6611
  }
6322
6612
  }
6323
- logger27.debug("Eviction manager cleared");
6613
+ logger30.debug("Eviction manager cleared");
6324
6614
  }
6325
6615
  /**
6326
6616
  * Create eviction context from current cache state
@@ -6458,61 +6748,149 @@ var LRUEvictionStrategy = class extends EvictionStrategy {
6458
6748
  // src/eviction/EvictionStrategyValidation.ts
6459
6749
  function validateNumberRange(value, min, max, fieldName) {
6460
6750
  if (typeof value !== "number" || isNaN(value) || !isFinite(value)) {
6461
- throw new Error(`${fieldName} must be a finite number`);
6751
+ throw new Error(
6752
+ `${fieldName} must be a finite number, got ${typeof value} (${value}). Suggestion: Provide a valid numeric value for ${fieldName}.`
6753
+ );
6462
6754
  }
6463
6755
  if (value < min || value > max) {
6464
- throw new Error(`${fieldName} must be between ${min} and ${max}, got ${value}`);
6756
+ throw new Error(
6757
+ `${fieldName} must be between ${min} and ${max}, got ${value}. Suggestion: Adjust ${fieldName} to be within the valid range.`
6758
+ );
6465
6759
  }
6466
6760
  }
6467
6761
  function validatePositiveInteger(value, fieldName) {
6468
6762
  if (typeof value !== "number" || isNaN(value) || !isFinite(value)) {
6469
- throw new Error(`${fieldName} must be a finite number`);
6763
+ throw new Error(
6764
+ `${fieldName} must be a finite number, got ${typeof value} (${value}). Suggestion: Provide a valid numeric value for ${fieldName}.`
6765
+ );
6470
6766
  }
6471
6767
  if (!Number.isInteger(value) || value <= 0) {
6472
- throw new Error(`${fieldName} must be a positive integer, got ${value}`);
6768
+ throw new Error(
6769
+ `${fieldName} must be a positive integer, got ${value}. Suggestion: Use a positive whole number (1, 2, 3, ...) for ${fieldName}.`
6770
+ );
6473
6771
  }
6474
6772
  }
6475
6773
  function sanitizeLFUConfig(config) {
6476
6774
  const sanitized = { ...config };
6477
6775
  if (typeof sanitized.decayFactor === "number") {
6478
6776
  if (sanitized.decayFactor < 0) {
6479
- console.warn(`decayFactor must be between 0 and 1, got ${sanitized.decayFactor}. Correcting to 0.`);
6777
+ const warning = {
6778
+ component: "cache",
6779
+ subcomponent: "EvictionStrategyValidation",
6780
+ operation: "sanitizeLFUConfig",
6781
+ field: "decayFactor",
6782
+ invalidValue: sanitized.decayFactor,
6783
+ correctedValue: 0,
6784
+ validRange: "0-1",
6785
+ note: "Auto-correcting invalid configuration value"
6786
+ };
6787
+ console.warn("Invalid decayFactor corrected:", JSON.stringify(warning, null, 2));
6480
6788
  sanitized.decayFactor = 0;
6481
6789
  } else if (sanitized.decayFactor > 1) {
6482
- console.warn(`decayFactor must be between 0 and 1, got ${sanitized.decayFactor}. Correcting to 1.`);
6790
+ const warning = {
6791
+ component: "cache",
6792
+ subcomponent: "EvictionStrategyValidation",
6793
+ operation: "sanitizeLFUConfig",
6794
+ field: "decayFactor",
6795
+ invalidValue: sanitized.decayFactor,
6796
+ correctedValue: 1,
6797
+ validRange: "0-1",
6798
+ note: "Auto-correcting invalid configuration value"
6799
+ };
6800
+ console.warn("Invalid decayFactor corrected:", JSON.stringify(warning, null, 2));
6483
6801
  sanitized.decayFactor = 1;
6484
6802
  }
6485
6803
  }
6486
6804
  if (typeof sanitized.decayInterval === "number" && sanitized.decayInterval <= 0) {
6487
- console.warn(`decayInterval must be positive, got ${sanitized.decayInterval}. Correcting to 300000.`);
6805
+ const warning = {
6806
+ component: "cache",
6807
+ subcomponent: "EvictionStrategyValidation",
6808
+ operation: "sanitizeLFUConfig",
6809
+ field: "decayInterval",
6810
+ invalidValue: sanitized.decayInterval,
6811
+ correctedValue: 3e5,
6812
+ minimumValue: 1,
6813
+ note: "Auto-correcting to 5 minutes (300000ms) default"
6814
+ };
6815
+ console.warn("Invalid decayInterval corrected:", JSON.stringify(warning, null, 2));
6488
6816
  sanitized.decayInterval = 3e5;
6489
6817
  }
6490
6818
  if (typeof sanitized.sketchWidth === "number") {
6491
6819
  if (sanitized.sketchWidth <= 0) {
6492
- console.warn(`sketchWidth must be positive, got ${sanitized.sketchWidth}. Correcting to 1024.`);
6820
+ console.warn("Invalid sketchWidth corrected:", JSON.stringify({
6821
+ component: "cache",
6822
+ subcomponent: "EvictionStrategyValidation",
6823
+ field: "sketchWidth",
6824
+ invalidValue: sanitized.sketchWidth,
6825
+ correctedValue: 1024,
6826
+ note: "Auto-correcting invalid configuration"
6827
+ }, null, 2));
6493
6828
  sanitized.sketchWidth = 1024;
6494
6829
  } else if (sanitized.sketchWidth < 16) {
6495
- console.warn(`sketchWidth should be at least 16 for optimal performance, got ${sanitized.sketchWidth}. Correcting to 16.`);
6830
+ console.warn("Suboptimal sketchWidth corrected:", JSON.stringify({
6831
+ component: "cache",
6832
+ subcomponent: "EvictionStrategyValidation",
6833
+ field: "sketchWidth",
6834
+ invalidValue: sanitized.sketchWidth,
6835
+ correctedValue: 16,
6836
+ minimumRecommended: 16,
6837
+ note: "Correcting for optimal performance"
6838
+ }, null, 2));
6496
6839
  sanitized.sketchWidth = 16;
6497
6840
  } else if (sanitized.sketchWidth > 65536) {
6498
- console.warn(`sketchWidth should not exceed 65536 for optimal performance, got ${sanitized.sketchWidth}. Correcting to 65536.`);
6841
+ console.warn("Excessive sketchWidth corrected:", JSON.stringify({
6842
+ component: "cache",
6843
+ subcomponent: "EvictionStrategyValidation",
6844
+ field: "sketchWidth",
6845
+ invalidValue: sanitized.sketchWidth,
6846
+ correctedValue: 65536,
6847
+ maximumRecommended: 65536,
6848
+ note: "Correcting for optimal performance"
6849
+ }, null, 2));
6499
6850
  sanitized.sketchWidth = 65536;
6500
6851
  }
6501
6852
  }
6502
6853
  if (typeof sanitized.sketchDepth === "number") {
6503
6854
  if (sanitized.sketchDepth <= 0) {
6504
- console.warn(`sketchDepth must be positive, got ${sanitized.sketchDepth}. Correcting to 4.`);
6855
+ console.warn("Invalid sketchDepth corrected:", JSON.stringify({
6856
+ component: "cache",
6857
+ subcomponent: "EvictionStrategyValidation",
6858
+ field: "sketchDepth",
6859
+ invalidValue: sanitized.sketchDepth,
6860
+ correctedValue: 4
6861
+ }, null, 2));
6505
6862
  sanitized.sketchDepth = 4;
6506
6863
  } else if (sanitized.sketchDepth < 1) {
6507
- console.warn(`sketchDepth should be at least 1 for optimal accuracy, got ${sanitized.sketchDepth}. Correcting to 1.`);
6864
+ console.warn("Suboptimal sketchDepth corrected:", JSON.stringify({
6865
+ component: "cache",
6866
+ subcomponent: "EvictionStrategyValidation",
6867
+ field: "sketchDepth",
6868
+ invalidValue: sanitized.sketchDepth,
6869
+ correctedValue: 1,
6870
+ minimumRecommended: 1
6871
+ }, null, 2));
6508
6872
  sanitized.sketchDepth = 1;
6509
6873
  } else if (sanitized.sketchDepth > 16) {
6510
- console.warn(`sketchDepth should not exceed 16 for optimal accuracy, got ${sanitized.sketchDepth}. Correcting to 16.`);
6874
+ console.warn("Excessive sketchDepth corrected:", JSON.stringify({
6875
+ component: "cache",
6876
+ subcomponent: "EvictionStrategyValidation",
6877
+ field: "sketchDepth",
6878
+ invalidValue: sanitized.sketchDepth,
6879
+ correctedValue: 16,
6880
+ maximumRecommended: 16
6881
+ }, null, 2));
6511
6882
  sanitized.sketchDepth = 16;
6512
6883
  }
6513
6884
  }
6514
6885
  if (typeof sanitized.minFrequencyThreshold === "number" && sanitized.minFrequencyThreshold <= 0) {
6515
- console.warn(`minFrequencyThreshold must be positive, got ${sanitized.minFrequencyThreshold}. Correcting to 1.`);
6886
+ console.warn("Invalid minFrequencyThreshold corrected:", JSON.stringify({
6887
+ component: "cache",
6888
+ subcomponent: "EvictionStrategyValidation",
6889
+ field: "minFrequencyThreshold",
6890
+ invalidValue: sanitized.minFrequencyThreshold,
6891
+ correctedValue: 1,
6892
+ minimumValue: 1
6893
+ }, null, 2));
6516
6894
  sanitized.minFrequencyThreshold = 1;
6517
6895
  }
6518
6896
  return sanitized;
@@ -6543,32 +6921,86 @@ function validateLFUConfig(config) {
6543
6921
  function sanitizeARCConfig(config) {
6544
6922
  const sanitized = { ...config };
6545
6923
  if (typeof sanitized.maxCacheSize === "number" && sanitized.maxCacheSize <= 0) {
6546
- console.warn(`maxCacheSize must be positive, got ${sanitized.maxCacheSize}. Correcting to 1000.`);
6924
+ console.warn("Invalid maxCacheSize corrected:", JSON.stringify({
6925
+ component: "cache",
6926
+ subcomponent: "EvictionStrategyValidation",
6927
+ operation: "sanitizeARCConfig",
6928
+ field: "maxCacheSize",
6929
+ invalidValue: sanitized.maxCacheSize,
6930
+ correctedValue: 1e3
6931
+ }, null, 2));
6547
6932
  sanitized.maxCacheSize = 1e3;
6548
6933
  }
6549
6934
  if (typeof sanitized.frequencyThreshold === "number" && sanitized.frequencyThreshold <= 0) {
6550
- console.warn(`frequencyThreshold must be positive, got ${sanitized.frequencyThreshold}. Correcting to 2.`);
6935
+ console.warn("Invalid frequencyThreshold corrected:", JSON.stringify({
6936
+ component: "cache",
6937
+ subcomponent: "EvictionStrategyValidation",
6938
+ operation: "sanitizeARCConfig",
6939
+ field: "frequencyThreshold",
6940
+ invalidValue: sanitized.frequencyThreshold,
6941
+ correctedValue: 2
6942
+ }, null, 2));
6551
6943
  sanitized.frequencyThreshold = 2;
6552
6944
  }
6553
6945
  if (typeof sanitized.frequencyDecayFactor === "number") {
6554
6946
  if (sanitized.frequencyDecayFactor < 0) {
6555
- console.warn(`frequencyDecayFactor must be between 0 and 1, got ${sanitized.frequencyDecayFactor}. Correcting to 0.`);
6947
+ console.warn("Invalid frequencyDecayFactor corrected:", JSON.stringify({
6948
+ component: "cache",
6949
+ subcomponent: "EvictionStrategyValidation",
6950
+ operation: "sanitizeARCConfig",
6951
+ field: "frequencyDecayFactor",
6952
+ invalidValue: sanitized.frequencyDecayFactor,
6953
+ correctedValue: 0,
6954
+ validRange: "0-1"
6955
+ }, null, 2));
6556
6956
  sanitized.frequencyDecayFactor = 0;
6557
6957
  } else if (sanitized.frequencyDecayFactor > 1) {
6558
- console.warn(`frequencyDecayFactor must be between 0 and 1, got ${sanitized.frequencyDecayFactor}. Correcting to 1.`);
6958
+ console.warn("Invalid frequencyDecayFactor corrected:", JSON.stringify({
6959
+ component: "cache",
6960
+ subcomponent: "EvictionStrategyValidation",
6961
+ operation: "sanitizeARCConfig",
6962
+ field: "frequencyDecayFactor",
6963
+ invalidValue: sanitized.frequencyDecayFactor,
6964
+ correctedValue: 1,
6965
+ validRange: "0-1"
6966
+ }, null, 2));
6559
6967
  sanitized.frequencyDecayFactor = 1;
6560
6968
  }
6561
6969
  }
6562
6970
  if (typeof sanitized.frequencyDecayInterval === "number" && sanitized.frequencyDecayInterval <= 0) {
6563
- console.warn(`frequencyDecayInterval must be positive, got ${sanitized.frequencyDecayInterval}. Correcting to 60000.`);
6971
+ console.warn("Invalid frequencyDecayInterval corrected:", JSON.stringify({
6972
+ component: "cache",
6973
+ subcomponent: "EvictionStrategyValidation",
6974
+ operation: "sanitizeARCConfig",
6975
+ field: "frequencyDecayInterval",
6976
+ invalidValue: sanitized.frequencyDecayInterval,
6977
+ correctedValue: 6e4,
6978
+ note: "Corrected to 1 minute default"
6979
+ }, null, 2));
6564
6980
  sanitized.frequencyDecayInterval = 6e4;
6565
6981
  }
6566
6982
  if (typeof sanitized.adaptiveLearningRate === "number") {
6567
6983
  if (sanitized.adaptiveLearningRate < 0) {
6568
- console.warn(`adaptiveLearningRate must be between 0 and 10, got ${sanitized.adaptiveLearningRate}. Correcting to 0.`);
6984
+ console.warn("Invalid adaptiveLearningRate corrected:", JSON.stringify({
6985
+ component: "cache",
6986
+ subcomponent: "EvictionStrategyValidation",
6987
+ operation: "sanitizeARCConfig",
6988
+ field: "adaptiveLearningRate",
6989
+ invalidValue: sanitized.adaptiveLearningRate,
6990
+ correctedValue: 0,
6991
+ validRange: "0-10"
6992
+ }, null, 2));
6569
6993
  sanitized.adaptiveLearningRate = 0;
6570
6994
  } else if (sanitized.adaptiveLearningRate > 10) {
6571
- console.warn(`adaptiveLearningRate must be between 0 and 10, got ${sanitized.adaptiveLearningRate}. Correcting to 10.`);
6995
+ console.warn("Invalid adaptiveLearningRate corrected:", JSON.stringify({
6996
+ component: "cache",
6997
+ subcomponent: "EvictionStrategyValidation",
6998
+ operation: "sanitizeARCConfig",
6999
+ field: "adaptiveLearningRate",
7000
+ invalidValue: sanitized.adaptiveLearningRate,
7001
+ correctedValue: 10,
7002
+ validRange: "0-10"
7003
+ }, null, 2));
6572
7004
  sanitized.adaptiveLearningRate = 10;
6573
7005
  }
6574
7006
  }
@@ -6594,24 +7026,62 @@ function validateARCConfig(config) {
6594
7026
  function sanitizeTwoQueueConfig(config) {
6595
7027
  const sanitized = { ...config };
6596
7028
  if (typeof sanitized.maxCacheSize === "number" && sanitized.maxCacheSize <= 0) {
6597
- console.warn(`maxCacheSize must be positive, got ${sanitized.maxCacheSize}. Correcting to 1000.`);
7029
+ console.warn("Invalid maxCacheSize corrected:", JSON.stringify({
7030
+ component: "cache",
7031
+ subcomponent: "EvictionStrategyValidation",
7032
+ operation: "sanitizeTwoQueueConfig",
7033
+ field: "maxCacheSize",
7034
+ invalidValue: sanitized.maxCacheSize,
7035
+ correctedValue: 1e3
7036
+ }, null, 2));
6598
7037
  sanitized.maxCacheSize = 1e3;
6599
7038
  }
6600
7039
  if (typeof sanitized.promotionThreshold === "number" && sanitized.promotionThreshold <= 0) {
6601
- console.warn(`promotionThreshold must be positive, got ${sanitized.promotionThreshold}. Correcting to 2.`);
7040
+ console.warn("Invalid promotionThreshold corrected:", JSON.stringify({
7041
+ component: "cache",
7042
+ subcomponent: "EvictionStrategyValidation",
7043
+ operation: "sanitizeTwoQueueConfig",
7044
+ field: "promotionThreshold",
7045
+ invalidValue: sanitized.promotionThreshold,
7046
+ correctedValue: 2
7047
+ }, null, 2));
6602
7048
  sanitized.promotionThreshold = 2;
6603
7049
  }
6604
7050
  if (typeof sanitized.hotQueueDecayFactor === "number") {
6605
7051
  if (sanitized.hotQueueDecayFactor < 0) {
6606
- console.warn(`hotQueueDecayFactor must be between 0 and 1, got ${sanitized.hotQueueDecayFactor}. Correcting to 0.`);
7052
+ console.warn("Invalid hotQueueDecayFactor corrected:", JSON.stringify({
7053
+ component: "cache",
7054
+ subcomponent: "EvictionStrategyValidation",
7055
+ operation: "sanitizeTwoQueueConfig",
7056
+ field: "hotQueueDecayFactor",
7057
+ invalidValue: sanitized.hotQueueDecayFactor,
7058
+ correctedValue: 0,
7059
+ validRange: "0-1"
7060
+ }, null, 2));
6607
7061
  sanitized.hotQueueDecayFactor = 0;
6608
7062
  } else if (sanitized.hotQueueDecayFactor > 1) {
6609
- console.warn(`hotQueueDecayFactor must be between 0 and 1, got ${sanitized.hotQueueDecayFactor}. Correcting to 1.`);
7063
+ console.warn("Invalid hotQueueDecayFactor corrected:", JSON.stringify({
7064
+ component: "cache",
7065
+ subcomponent: "EvictionStrategyValidation",
7066
+ operation: "sanitizeTwoQueueConfig",
7067
+ field: "hotQueueDecayFactor",
7068
+ invalidValue: sanitized.hotQueueDecayFactor,
7069
+ correctedValue: 1,
7070
+ validRange: "0-1"
7071
+ }, null, 2));
6610
7072
  sanitized.hotQueueDecayFactor = 1;
6611
7073
  }
6612
7074
  }
6613
7075
  if (typeof sanitized.hotQueueDecayInterval === "number" && sanitized.hotQueueDecayInterval <= 0) {
6614
- console.warn(`hotQueueDecayInterval must be positive, got ${sanitized.hotQueueDecayInterval}. Correcting to 300000.`);
7076
+ console.warn("Invalid hotQueueDecayInterval corrected:", JSON.stringify({
7077
+ component: "cache",
7078
+ subcomponent: "EvictionStrategyValidation",
7079
+ operation: "sanitizeTwoQueueConfig",
7080
+ field: "hotQueueDecayInterval",
7081
+ invalidValue: sanitized.hotQueueDecayInterval,
7082
+ correctedValue: 3e5,
7083
+ note: "Corrected to 5 minutes default"
7084
+ }, null, 2));
6615
7085
  sanitized.hotQueueDecayInterval = 3e5;
6616
7086
  }
6617
7087
  return sanitized;
@@ -7658,7 +8128,7 @@ function createEvictionStrategy(policy, maxCacheSize, config) {
7658
8128
  }
7659
8129
 
7660
8130
  // src/ttl/TTLManager.ts
7661
- var logger28 = logger_default.get("TTLManager");
8131
+ var logger31 = logger_default.get("TTLManager");
7662
8132
  var TTLManager = class {
7663
8133
  config;
7664
8134
  cleanupTimer;
@@ -7670,7 +8140,7 @@ var TTLManager = class {
7670
8140
  validateOnAccess: true,
7671
8141
  ...config
7672
8142
  };
7673
- logger28.debug("TTL_DEBUG: TTLManager created", {
8143
+ logger31.debug("TTL_DEBUG: TTLManager created", {
7674
8144
  config: this.config,
7675
8145
  isTTLEnabled: this.isTTLEnabled(),
7676
8146
  defaultTTL: this.config.defaultTTL
@@ -7703,13 +8173,13 @@ var TTLManager = class {
7703
8173
  this.startAutoCleanup();
7704
8174
  }
7705
8175
  }
7706
- logger28.debug("TTL configuration updated", { config: this.config });
8176
+ logger31.debug("TTL configuration updated", { config: this.config });
7707
8177
  }
7708
8178
  /**
7709
8179
  * Set TTL metadata for an item when it's added
7710
8180
  */
7711
8181
  async onItemAdded(key, metadataProvider, itemTTL) {
7712
- logger28.debug("TTL_DEBUG: onItemAdded called", {
8182
+ logger31.debug("TTL_DEBUG: onItemAdded called", {
7713
8183
  key,
7714
8184
  itemTTL,
7715
8185
  isTTLEnabled: this.isTTLEnabled(),
@@ -7717,19 +8187,19 @@ var TTLManager = class {
7717
8187
  metadataProviderType: metadataProvider?.constructor?.name
7718
8188
  });
7719
8189
  if (!this.isTTLEnabled() && !itemTTL) {
7720
- logger28.debug("TTL_DEBUG: No TTL configured for item - returning early", { key });
8190
+ logger31.debug("TTL_DEBUG: No TTL configured for item - returning early", { key });
7721
8191
  return;
7722
8192
  }
7723
- logger28.debug("TTL_DEBUG: Getting metadata for key", { key });
8193
+ logger31.debug("TTL_DEBUG: Getting metadata for key", { key });
7724
8194
  const metadata = await metadataProvider.getMetadata(key);
7725
- logger28.debug("TTL_DEBUG: Retrieved metadata", {
8195
+ logger31.debug("TTL_DEBUG: Retrieved metadata", {
7726
8196
  key,
7727
8197
  hasMetadata: !!metadata,
7728
8198
  metadataKeys: metadata ? Object.keys(metadata) : null,
7729
8199
  metadata
7730
8200
  });
7731
8201
  if (!metadata) {
7732
- logger28.debug("TTL_DEBUG: No metadata found for item when setting TTL", {
8202
+ logger31.debug("TTL_DEBUG: No metadata found for item when setting TTL", {
7733
8203
  key,
7734
8204
  metadataProviderType: metadataProvider?.constructor?.name,
7735
8205
  metadataProviderMethods: metadataProvider ? Object.getOwnPropertyNames(Object.getPrototypeOf(metadataProvider)) : null
@@ -7737,7 +8207,7 @@ var TTLManager = class {
7737
8207
  return;
7738
8208
  }
7739
8209
  const ttl = itemTTL || this.config.defaultTTL;
7740
- logger28.debug("TTL_DEBUG: Calculated TTL value", {
8210
+ logger31.debug("TTL_DEBUG: Calculated TTL value", {
7741
8211
  key,
7742
8212
  itemTTL,
7743
8213
  defaultTTL: this.config.defaultTTL,
@@ -7750,7 +8220,7 @@ var TTLManager = class {
7750
8220
  expiresAt: metadata.addedAt + ttl,
7751
8221
  ttl
7752
8222
  };
7753
- logger28.debug("TTL_DEBUG: Setting TTL metadata", {
8223
+ logger31.debug("TTL_DEBUG: Setting TTL metadata", {
7754
8224
  key,
7755
8225
  ttl,
7756
8226
  addedAt: metadata.addedAt,
@@ -7758,9 +8228,9 @@ var TTLManager = class {
7758
8228
  ttlMetadata
7759
8229
  });
7760
8230
  await metadataProvider.setMetadata(key, ttlMetadata);
7761
- logger28.trace("TTL_DEBUG: TTL set for item", { key, ttl, expiresAt: ttlMetadata.expiresAt });
8231
+ logger31.trace("TTL_DEBUG: TTL set for item", { key, ttl, expiresAt: ttlMetadata.expiresAt });
7762
8232
  } else {
7763
- logger28.debug("TTL_DEBUG: No TTL set - invalid TTL value", { key, ttl });
8233
+ logger31.debug("TTL_DEBUG: No TTL set - invalid TTL value", { key, ttl });
7764
8234
  }
7765
8235
  }
7766
8236
  /**
@@ -7769,14 +8239,14 @@ var TTLManager = class {
7769
8239
  async isExpired(key, metadataProvider) {
7770
8240
  const metadata = await metadataProvider.getMetadata(key);
7771
8241
  if (!metadata || !metadata.expiresAt) {
7772
- logger28.debug("TTL_CHECK: No TTL set for item", { key, hasMetadata: !!metadata });
8242
+ logger31.debug("TTL_CHECK: No TTL set for item", { key, hasMetadata: !!metadata });
7773
8243
  return false;
7774
8244
  }
7775
8245
  const now = Date.now();
7776
8246
  const expired = now >= metadata.expiresAt;
7777
8247
  const remainingMs = metadata.expiresAt - now;
7778
8248
  if (expired) {
7779
- logger28.debug("TTL_CHECK: Item EXPIRED", {
8249
+ logger31.debug("TTL_CHECK: Item EXPIRED", {
7780
8250
  key,
7781
8251
  expiresAt: new Date(metadata.expiresAt).toISOString(),
7782
8252
  now: new Date(now).toISOString(),
@@ -7784,7 +8254,7 @@ var TTLManager = class {
7784
8254
  ttl: metadata.ttl
7785
8255
  });
7786
8256
  } else {
7787
- logger28.debug("TTL_CHECK: Item still valid", {
8257
+ logger31.debug("TTL_CHECK: Item still valid", {
7788
8258
  key,
7789
8259
  expiresAt: new Date(metadata.expiresAt).toISOString(),
7790
8260
  remainingMs,
@@ -7800,17 +8270,17 @@ var TTLManager = class {
7800
8270
  */
7801
8271
  async validateItem(key, metadataProvider) {
7802
8272
  if (!this.config.validateOnAccess) {
7803
- logger28.debug("TTL_VALIDATE: Validation disabled, skipping check", { key });
8273
+ logger31.debug("TTL_VALIDATE: Validation disabled, skipping check", { key });
7804
8274
  return true;
7805
8275
  }
7806
- logger28.debug("TTL_VALIDATE: Validating item", {
8276
+ logger31.debug("TTL_VALIDATE: Validating item", {
7807
8277
  key,
7808
8278
  ttlEnabled: this.isTTLEnabled(),
7809
8279
  defaultTTL: this.config.defaultTTL
7810
8280
  });
7811
8281
  const isExpired = await this.isExpired(key, metadataProvider);
7812
8282
  const isValid = !isExpired;
7813
- logger28.debug("TTL_VALIDATE: Validation result", {
8283
+ logger31.debug("TTL_VALIDATE: Validation result", {
7814
8284
  key,
7815
8285
  isValid,
7816
8286
  isExpired
@@ -7844,7 +8314,7 @@ var TTLManager = class {
7844
8314
  const expiredKeys = [];
7845
8315
  const allMetadata = await metadataProvider.getAllMetadata();
7846
8316
  const now = Date.now();
7847
- logger28.debug("TTL_CLEANUP: Scanning for expired items", {
8317
+ logger31.debug("TTL_CLEANUP: Scanning for expired items", {
7848
8318
  totalItems: allMetadata.size,
7849
8319
  now: new Date(now).toISOString()
7850
8320
  });
@@ -7855,7 +8325,7 @@ var TTLManager = class {
7855
8325
  itemsWithTTL++;
7856
8326
  if (now >= ttlMetadata.expiresAt) {
7857
8327
  expiredKeys.push(key);
7858
- logger28.debug("TTL_CLEANUP: Found expired item", {
8328
+ logger31.debug("TTL_CLEANUP: Found expired item", {
7859
8329
  key,
7860
8330
  expiresAt: new Date(ttlMetadata.expiresAt).toISOString(),
7861
8331
  expiredByMs: now - ttlMetadata.expiresAt
@@ -7865,7 +8335,7 @@ var TTLManager = class {
7865
8335
  }
7866
8336
  const duration = Date.now() - startTime;
7867
8337
  if (expiredKeys.length > 0) {
7868
- logger28.debug("TTL_CLEANUP: Expired items found", {
8338
+ logger31.debug("TTL_CLEANUP: Expired items found", {
7869
8339
  expiredCount: expiredKeys.length,
7870
8340
  totalItems: allMetadata.size,
7871
8341
  itemsWithTTL,
@@ -7873,7 +8343,7 @@ var TTLManager = class {
7873
8343
  duration
7874
8344
  });
7875
8345
  } else {
7876
- logger28.debug("TTL_CLEANUP: No expired items found", {
8346
+ logger31.debug("TTL_CLEANUP: No expired items found", {
7877
8347
  totalItems: allMetadata.size,
7878
8348
  itemsWithTTL,
7879
8349
  duration
@@ -7905,7 +8375,7 @@ var TTLManager = class {
7905
8375
  }
7906
8376
  metadata.expiresAt += additionalTTL;
7907
8377
  await metadataProvider.setMetadata(key, metadata);
7908
- logger28.trace("TTL extended for item", { key, additionalTTL, newExpiresAt: metadata.expiresAt });
8378
+ logger31.trace("TTL extended for item", { key, additionalTTL, newExpiresAt: metadata.expiresAt });
7909
8379
  return true;
7910
8380
  }
7911
8381
  /**
@@ -7927,7 +8397,7 @@ var TTLManager = class {
7927
8397
  ttl
7928
8398
  };
7929
8399
  await metadataProvider.setMetadata(key, ttlMetadata);
7930
- logger28.trace("TTL refreshed for item", { key, ttl, expiresAt: ttlMetadata.expiresAt });
8400
+ logger31.trace("TTL refreshed for item", { key, ttl, expiresAt: ttlMetadata.expiresAt });
7931
8401
  return true;
7932
8402
  }
7933
8403
  /**
@@ -7939,9 +8409,9 @@ var TTLManager = class {
7939
8409
  }
7940
8410
  if (this.config.cleanupInterval) {
7941
8411
  this.cleanupTimer = setInterval(() => {
7942
- logger28.trace("Auto cleanup timer triggered");
8412
+ logger31.trace("Auto cleanup timer triggered");
7943
8413
  }, this.config.cleanupInterval);
7944
- logger28.debug("Auto cleanup started", { interval: this.config.cleanupInterval });
8414
+ logger31.debug("Auto cleanup started", { interval: this.config.cleanupInterval });
7945
8415
  }
7946
8416
  }
7947
8417
  /**
@@ -7951,7 +8421,7 @@ var TTLManager = class {
7951
8421
  if (this.cleanupTimer) {
7952
8422
  clearInterval(this.cleanupTimer);
7953
8423
  this.cleanupTimer = null;
7954
- logger28.debug("Auto cleanup stopped");
8424
+ logger31.debug("Auto cleanup stopped");
7955
8425
  }
7956
8426
  }
7957
8427
  /**
@@ -7959,18 +8429,31 @@ var TTLManager = class {
7959
8429
  */
7960
8430
  clear() {
7961
8431
  this.stopAutoCleanup();
7962
- logger28.debug("TTL manager cleared");
8432
+ logger31.debug("TTL manager cleared");
7963
8433
  }
7964
8434
  /**
7965
8435
  * Cleanup resources
7966
8436
  */
7967
8437
  destroy() {
8438
+ logger31.debug("TTL manager destroy started", {
8439
+ component: "cache",
8440
+ subcomponent: "TTLManager",
8441
+ operation: "destroy",
8442
+ autoCleanupEnabled: !!this.config.cleanupInterval,
8443
+ note: "Stopping auto-cleanup and clearing TTL data"
8444
+ });
7968
8445
  this.stopAutoCleanup();
7969
- logger28.debug("TTL manager destroyed");
8446
+ logger31.debug("TTL manager destroyed", {
8447
+ component: "cache",
8448
+ subcomponent: "TTLManager",
8449
+ operation: "destroy",
8450
+ note: "All TTL tracking data cleared"
8451
+ });
7970
8452
  }
7971
8453
  };
7972
8454
 
7973
8455
  // src/events/CacheEventEmitter.ts
8456
+ var logger32 = logger_default.get("CacheEventEmitter");
7974
8457
  var CacheEventEmitter = class {
7975
8458
  subscriptions = /* @__PURE__ */ new Map();
7976
8459
  nextSubscriptionId = 1;
@@ -8071,9 +8554,17 @@ var CacheEventEmitter = class {
8071
8554
  */
8072
8555
  emit(event) {
8073
8556
  if (this.isDestroyed) {
8557
+ logger32.debug("Event emission skipped - emitter is destroyed", {
8558
+ component: "cache",
8559
+ subcomponent: "CacheEventEmitter",
8560
+ eventType: event.type,
8561
+ suggestion: "This is expected during cleanup. Ensure emitter is not used after destroy()."
8562
+ });
8074
8563
  return;
8075
8564
  }
8076
8565
  let emittedCount = 0;
8566
+ const totalSubscriptions = this.subscriptions.size;
8567
+ const activeSubscriptions = Array.from(this.subscriptions.values()).filter((s) => s.isActive).length;
8077
8568
  for (const subscription of this.subscriptions.values()) {
8078
8569
  if (!subscription.isActive) {
8079
8570
  continue;
@@ -8083,6 +8574,17 @@ var CacheEventEmitter = class {
8083
8574
  emittedCount++;
8084
8575
  }
8085
8576
  }
8577
+ logger32.trace("Event emitted to subscriptions", {
8578
+ component: "cache",
8579
+ subcomponent: "CacheEventEmitter",
8580
+ eventType: event.type,
8581
+ eventSource: event.source,
8582
+ eventKey: "key" in event ? JSON.stringify(event.key) : void 0,
8583
+ totalSubscriptions,
8584
+ activeSubscriptions,
8585
+ emittedCount,
8586
+ note: emittedCount === 0 ? "No subscriptions matched this event" : void 0
8587
+ });
8086
8588
  }
8087
8589
  /**
8088
8590
  * Get count of active subscriptions
@@ -8287,20 +8789,36 @@ var CacheEventEmitter = class {
8287
8789
  */
8288
8790
  handleListenerError(error, event, subscription) {
8289
8791
  const errorObj = error instanceof Error ? error : new Error(String(error));
8792
+ const errorContext = {
8793
+ component: "CacheEventEmitter",
8794
+ operation: "event-listener",
8795
+ eventType: event.type,
8796
+ eventKey: "key" in event ? JSON.stringify(event.key) : void 0,
8797
+ subscriptionId: subscription.id,
8798
+ errorType: errorObj.constructor.name,
8799
+ errorMessage: errorObj.message,
8800
+ suggestion: "Review event listener implementation for errors. Consider adding error handling in the listener.",
8801
+ stack: errorObj.stack
8802
+ };
8290
8803
  if (subscription.options.onError) {
8291
8804
  try {
8292
8805
  subscription.options.onError(errorObj, event);
8293
8806
  } catch (handlerError) {
8294
- console.error("Error in cache event listener:", errorObj);
8807
+ console.error("Error in cache event listener:", JSON.stringify(errorContext, null, 2));
8808
+ console.error("Original error:", errorObj);
8295
8809
  console.error("Error in error handler:", handlerError);
8810
+ console.error("Critical: Both the event listener and its error handler failed. Review error handling logic.");
8296
8811
  }
8297
8812
  } else {
8298
- console.error("Error in cache event listener:", errorObj);
8813
+ console.error("Error in cache event listener (no error handler configured):", JSON.stringify(errorContext, null, 2));
8814
+ console.error("Original error:", errorObj);
8815
+ console.error("Suggestion: Add an onError handler to your subscription to handle listener errors gracefully.");
8299
8816
  }
8300
8817
  }
8301
8818
  };
8302
8819
 
8303
8820
  // src/CacheStats.ts
8821
+ var logger33 = logger_default.get("CacheStats");
8304
8822
  var CacheStatsManager = class {
8305
8823
  stats = {
8306
8824
  numRequests: 0,
@@ -8310,11 +8828,22 @@ var CacheStatsManager = class {
8310
8828
  numUnsubscriptions: 0,
8311
8829
  activeSubscriptions: 0
8312
8830
  };
8831
+ lastLoggedStats = {
8832
+ numRequests: 0,
8833
+ numMisses: 0,
8834
+ numHits: 0,
8835
+ numSubscriptions: 0,
8836
+ numUnsubscriptions: 0,
8837
+ activeSubscriptions: 0
8838
+ };
8839
+ LOG_THRESHOLD = 100;
8840
+ // Log every 100 requests
8313
8841
  /**
8314
8842
  * Increment the request counter
8315
8843
  */
8316
8844
  incrementRequests() {
8317
8845
  this.stats.numRequests++;
8846
+ this.maybeLogStats();
8318
8847
  }
8319
8848
  /**
8320
8849
  * Increment the cache hit counter
@@ -8328,6 +8857,27 @@ var CacheStatsManager = class {
8328
8857
  incrementMisses() {
8329
8858
  this.stats.numMisses++;
8330
8859
  }
8860
+ /**
8861
+ * Log statistics periodically for monitoring
8862
+ */
8863
+ maybeLogStats() {
8864
+ const requestsSinceLastLog = this.stats.numRequests - this.lastLoggedStats.numRequests;
8865
+ if (requestsSinceLastLog >= this.LOG_THRESHOLD) {
8866
+ const hitRate = this.stats.numRequests > 0 ? (this.stats.numHits / this.stats.numRequests * 100).toFixed(2) : "0.00";
8867
+ logger33.debug("Cache statistics update", {
8868
+ component: "cache",
8869
+ subcomponent: "CacheStatsManager",
8870
+ totalRequests: this.stats.numRequests,
8871
+ hits: this.stats.numHits,
8872
+ misses: this.stats.numMisses,
8873
+ hitRate: `${hitRate}%`,
8874
+ activeSubscriptions: this.stats.activeSubscriptions,
8875
+ requestsSinceLastLog,
8876
+ note: `Statistics logged every ${this.LOG_THRESHOLD} requests for monitoring`
8877
+ });
8878
+ this.lastLoggedStats = { ...this.stats };
8879
+ }
8880
+ }
8331
8881
  /**
8332
8882
  * Increment the subscription counter
8333
8883
  */
@@ -8366,9 +8916,17 @@ var CacheStatsManager = class {
8366
8916
  };
8367
8917
 
8368
8918
  // src/Cache.ts
8369
- var logger29 = logger_default.get("Cache");
8919
+ var logger34 = logger_default.get("Cache");
8370
8920
  var createCache = (api, coordinate, registry, options) => {
8371
- logger29.debug("createCache", { coordinate, registry, options });
8921
+ logger34.debug("createCache", {
8922
+ component: "cache",
8923
+ operation: "createCache",
8924
+ itemType: coordinate.kta[0],
8925
+ hierarchy: coordinate.kta,
8926
+ cacheType: options?.cacheType,
8927
+ hasRegistry: !!registry,
8928
+ note: "Cache creation started"
8929
+ });
8372
8930
  const completeOptions = createOptions(options);
8373
8931
  const cacheMap = createCacheMap(coordinate.kta, completeOptions);
8374
8932
  const pkType = coordinate.kta[0];
@@ -8448,18 +9006,24 @@ var isCache2 = (cache) => {
8448
9006
  };
8449
9007
 
8450
9008
  // src/InstanceFactory.ts
8451
- var logger30 = logger_default.get("InstanceFactory");
9009
+ var logger35 = logger_default.get("InstanceFactory");
8452
9010
  var createInstanceFactory = (api, options) => {
8453
9011
  const templateOptions = createOptions(options);
8454
9012
  validateOptions(templateOptions);
8455
9013
  return (coordinate, context) => {
8456
9014
  const instanceOptions = createOptions(options);
8457
- logger30.debug("Creating cache instance", {
8458
- coordinate,
8459
- registry: context.registry,
8460
- api,
9015
+ logger35.debug("Creating cache instance", {
9016
+ component: "cache",
9017
+ operation: "createInstance",
9018
+ itemType: coordinate.kta[0],
9019
+ hierarchy: coordinate.kta,
8461
9020
  cacheType: instanceOptions.cacheType,
8462
- options: instanceOptions
9021
+ ttlEnabled: !!instanceOptions.ttl,
9022
+ ttlValue: instanceOptions.ttl,
9023
+ evictionEnabled: !!instanceOptions.evictionConfig,
9024
+ evictionStrategy: instanceOptions.evictionConfig?.type,
9025
+ twoLayerEnabled: !!instanceOptions.twoLayer,
9026
+ note: "Cache instance initialization started"
8463
9027
  });
8464
9028
  const cacheMap = createCacheMap(coordinate.kta, instanceOptions);
8465
9029
  const pkType = coordinate.kta[0];
@@ -8521,9 +9085,9 @@ var createInstanceFactory = (api, options) => {
8521
9085
  };
8522
9086
 
8523
9087
  // src/Instance.ts
8524
- var logger31 = logger_default.get("Instance");
9088
+ var logger36 = logger_default.get("Instance");
8525
9089
  var createInstance = (registry, coordinate, api, options) => {
8526
- logger31.debug("createInstance", { coordinate, api, registry, options });
9090
+ logger36.debug("createInstance", { coordinate, api, registry, options });
8527
9091
  return createCache(api, coordinate, registry, options);
8528
9092
  };
8529
9093
  var isInstance = (instance) => {
@@ -8531,7 +9095,7 @@ var isInstance = (instance) => {
8531
9095
  };
8532
9096
 
8533
9097
  // src/Aggregator.ts
8534
- var logger32 = logger_default.get("ItemAggregator");
9098
+ var logger37 = logger_default.get("ItemAggregator");
8535
9099
  var toCacheConfig = (config) => {
8536
9100
  let cacheConfig;
8537
9101
  if (config.optional === void 0) {
@@ -8543,23 +9107,32 @@ var toCacheConfig = (config) => {
8543
9107
  };
8544
9108
  var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8545
9109
  const populate = async (item) => {
8546
- logger32.default("populate", { item });
9110
+ logger37.default("populate", { item });
8547
9111
  for (const key in aggregates) {
8548
9112
  await populateAggregate(key, item);
8549
9113
  }
8550
9114
  for (const key in events) {
8551
9115
  await populateEvent(key, item);
8552
9116
  }
8553
- logger32.default("populate done", { item });
9117
+ logger37.default("populate done", { item });
8554
9118
  return item;
8555
9119
  };
8556
9120
  const populateAggregate = async (key, item) => {
8557
- logger32.default("populate aggregate key", { key });
9121
+ logger37.default("populate aggregate key", { key });
8558
9122
  const cacheConfig = toCacheConfig(aggregates[key]);
8559
9123
  if (item.refs === void 0) {
8560
9124
  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));
9125
+ logger37.error("Item missing required refs property", {
9126
+ component: "cache",
9127
+ subcomponent: "Aggregator",
9128
+ operation: "populateRef",
9129
+ refKey: key,
9130
+ item: JSON.stringify(item),
9131
+ suggestion: "Ensure the item has a refs property or mark this reference as optional in cache configuration"
9132
+ });
9133
+ throw new Error(
9134
+ `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.`
9135
+ );
8563
9136
  } else {
8564
9137
  if (item.events && Object.prototype.hasOwnProperty.call(item.events, key)) {
8565
9138
  delete item.events[key];
@@ -8567,8 +9140,18 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8567
9140
  }
8568
9141
  } else if (item.refs[key] === void 0) {
8569
9142
  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));
9143
+ logger37.error("Item missing required reference", {
9144
+ component: "cache",
9145
+ subcomponent: "Aggregator",
9146
+ operation: "populateRef",
9147
+ refKey: key,
9148
+ availableRefs: Object.keys(item.refs || {}),
9149
+ item: JSON.stringify(item),
9150
+ suggestion: `Ensure the item has refs.${key} property or mark this reference as optional in cache configuration`
9151
+ });
9152
+ throw new Error(
9153
+ `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.`
9154
+ );
8572
9155
  } else {
8573
9156
  if (item.events && Object.prototype.hasOwnProperty.call(item.events, key)) {
8574
9157
  delete item.events[key];
@@ -8576,7 +9159,7 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8576
9159
  }
8577
9160
  } else {
8578
9161
  const ref = item.refs[key];
8579
- logger32.default("AGG Retrieving Item in Populate", { key: ref });
9162
+ logger37.default("AGG Retrieving Item in Populate", { key: ref });
8580
9163
  const newItem = await cacheConfig.cache.operations.retrieve(ref);
8581
9164
  if (newItem) {
8582
9165
  if (item.aggs === void 0) {
@@ -8593,25 +9176,52 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8593
9176
  }
8594
9177
  };
8595
9178
  const populateEvent = async (key, item) => {
8596
- logger32.default("populate event key", { key });
9179
+ logger37.default("populate event key", { key });
8597
9180
  const cacheConfig = toCacheConfig(events[key]);
8598
9181
  if (item.events === void 0) {
8599
- throw new Error("Item does not have events " + JSON.stringify(item));
9182
+ logger37.error("Item missing events property", {
9183
+ component: "cache",
9184
+ subcomponent: "Aggregator",
9185
+ operation: "populateEvent",
9186
+ eventKey: key,
9187
+ item: JSON.stringify(item),
9188
+ suggestion: "Ensure the item has an events property with event data"
9189
+ });
9190
+ throw new Error(
9191
+ `Item missing events property for event '${key}'. Item: ${JSON.stringify(item)}. Suggestion: Ensure events are properly tracked on this item type.`
9192
+ );
8600
9193
  } else if (item.events[key] === void 0) {
8601
9194
  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));
9195
+ logger37.error("Item missing required event", {
9196
+ component: "cache",
9197
+ subcomponent: "Aggregator",
9198
+ operation: "populateEvent",
9199
+ eventKey: key,
9200
+ availableEvents: Object.keys(item.events || {}),
9201
+ item: JSON.stringify(item),
9202
+ suggestion: `Ensure the item has events.${key} property or mark this event as optional`
9203
+ });
9204
+ throw new Error(
9205
+ `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.`
9206
+ );
8604
9207
  }
8605
9208
  } else {
8606
9209
  const event = item.events[key];
8607
9210
  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 }
9211
+ logger37.error('Event missing required "by" field', {
9212
+ component: "cache",
9213
+ subcomponent: "Aggregator",
9214
+ operation: "populateEvent",
9215
+ eventKey: key,
9216
+ event,
9217
+ itemKey: item.key,
9218
+ suggestion: 'Ensure event has a "by" field with the user/actor who triggered the event'
9219
+ });
9220
+ throw new Error(
9221
+ `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
9222
  );
8612
- throw new Error("populateEvent with an Event that does not have by: " + JSON.stringify({ key }));
8613
9223
  }
8614
- logger32.default("EVENT Retrieving Item in Populate", { key: event.by });
9224
+ logger37.default("EVENT Retrieving Item in Populate", { key: event.by });
8615
9225
  const newItem = await cacheConfig.cache.operations.retrieve(event.by);
8616
9226
  if (newItem) {
8617
9227
  event.agg = newItem;
@@ -8619,13 +9229,13 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8619
9229
  }
8620
9230
  };
8621
9231
  const all2 = async (query = {}, locations = []) => {
8622
- logger32.default("all", { query, locations });
9232
+ logger37.default("all", { query, locations });
8623
9233
  const result = await cache.operations.all(query, locations);
8624
9234
  const populatedItems = await Promise.all(result.items.map(async (item) => populate(item)));
8625
9235
  return populatedItems;
8626
9236
  };
8627
9237
  const one2 = async (query = {}, locations = []) => {
8628
- logger32.default("one", { query, locations });
9238
+ logger37.default("one", { query, locations });
8629
9239
  const item = await cache.operations.one(query, locations);
8630
9240
  let populatedItem = null;
8631
9241
  if (item) {
@@ -8634,30 +9244,30 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8634
9244
  return populatedItem;
8635
9245
  };
8636
9246
  const action2 = async (key, action3, body = {}) => {
8637
- logger32.default("action", { key, action: action3, body });
9247
+ logger37.default("action", { key, action: action3, body });
8638
9248
  const [item, affectedItems] = await cache.operations.action(key, action3, body);
8639
9249
  const populatedItem = await populate(item);
8640
9250
  return [populatedItem, affectedItems];
8641
9251
  };
8642
9252
  const allAction2 = async (action3, body = {}, locations = []) => {
8643
- logger32.default("action", { action: action3, body, locations });
9253
+ logger37.default("action", { action: action3, body, locations });
8644
9254
  const [items, affectedItems] = await cache.operations.allAction(action3, body, locations);
8645
9255
  const populatedItems = await Promise.all(items.map(async (item) => populate(item)));
8646
9256
  return [populatedItems, affectedItems];
8647
9257
  };
8648
9258
  const allFacet2 = async (facet3, params = {}, locations = []) => {
8649
- logger32.default("allFacet", { facet: facet3, params, locations });
9259
+ logger37.default("allFacet", { facet: facet3, params, locations });
8650
9260
  const response = await cache.operations.allFacet(facet3, params, locations);
8651
9261
  return response;
8652
9262
  };
8653
9263
  const create2 = async (v, locations = []) => {
8654
- logger32.default("create", { v, locations });
9264
+ logger37.default("create", { v, locations });
8655
9265
  const item = locations.length === 0 ? await cache.operations.create(v) : await cache.operations.create(v, { locations });
8656
9266
  const populatedItem = await populate(item);
8657
9267
  return populatedItem;
8658
9268
  };
8659
9269
  const get2 = async (key) => {
8660
- logger32.default("get", { key });
9270
+ logger37.default("get", { key });
8661
9271
  const item = await cache.operations.get(key);
8662
9272
  let populatedItem = null;
8663
9273
  if (item) {
@@ -8666,7 +9276,7 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8666
9276
  return populatedItem;
8667
9277
  };
8668
9278
  const retrieve2 = async (key) => {
8669
- logger32.default("retrieve", { key });
9279
+ logger37.default("retrieve", { key });
8670
9280
  const item = await cache.operations.retrieve(key);
8671
9281
  let populatedItem = null;
8672
9282
  if (item) {
@@ -8675,22 +9285,22 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8675
9285
  return populatedItem;
8676
9286
  };
8677
9287
  const remove2 = async (key) => {
8678
- logger32.default("remove", { key });
9288
+ logger37.default("remove", { key });
8679
9289
  await cache.operations.remove(key);
8680
9290
  };
8681
9291
  const update2 = async (key, v) => {
8682
- logger32.default("update", { key, v });
9292
+ logger37.default("update", { key, v });
8683
9293
  const item = await cache.operations.update(key, v);
8684
9294
  const populatedItem = await populate(item);
8685
9295
  return populatedItem;
8686
9296
  };
8687
9297
  const facet2 = async (key, facet3) => {
8688
- logger32.default("facet", { key, facet: facet3 });
9298
+ logger37.default("facet", { key, facet: facet3 });
8689
9299
  const response = await cache.operations.facet(key, facet3);
8690
9300
  return response;
8691
9301
  };
8692
9302
  const find2 = async (finder, finderParams = {}, locations = [], findOptions) => {
8693
- logger32.default("find", { finder, finderParams, locations, findOptions });
9303
+ logger37.default("find", { finder, finderParams, locations, findOptions });
8694
9304
  const result = await cache.operations.find(finder, finderParams, locations, findOptions);
8695
9305
  const populatedItems = await Promise.all(result.items.map(async (item) => populate(item)));
8696
9306
  return {
@@ -8699,7 +9309,7 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8699
9309
  };
8700
9310
  };
8701
9311
  const findOne2 = async (finder, finderParams = {}, locations = []) => {
8702
- logger32.default("find", { finder, finderParams, locations });
9312
+ logger37.default("find", { finder, finderParams, locations });
8703
9313
  const item = await cache.operations.findOne(finder, finderParams, locations);
8704
9314
  if (!item) {
8705
9315
  return null;
@@ -8708,7 +9318,7 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8708
9318
  return populatedItem;
8709
9319
  };
8710
9320
  const set2 = async (key, v) => {
8711
- logger32.default("set", { key, v });
9321
+ logger37.default("set", { key, v });
8712
9322
  const item = await cache.operations.set(key, v);
8713
9323
  const populatedItem = await populate(item);
8714
9324
  return populatedItem;
@@ -8760,13 +9370,13 @@ var createAggregator = async (cache, { aggregates = {}, events = {} }) => {
8760
9370
  import {
8761
9371
  createRegistry as createBaseRegistry
8762
9372
  } from "@fjell/registry";
8763
- var logger33 = logger_default.get("Registry");
9373
+ var logger38 = logger_default.get("Registry");
8764
9374
  var createRegistryFactory = () => {
8765
9375
  return (type, registryHub) => {
8766
9376
  if (type !== "cache") {
8767
9377
  throw new Error(`Cache registry factory can only create 'cache' type registries, got: ${type}`);
8768
9378
  }
8769
- logger33.debug("Creating cache registry", { type, registryHub });
9379
+ logger38.debug("Creating cache registry", { type, registryHub });
8770
9380
  const baseRegistry = createBaseRegistry(type, registryHub);
8771
9381
  return baseRegistry;
8772
9382
  };