@fjell/cache 4.6.22 → 4.7.2

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 (62) hide show
  1. package/CACHE_EVENTS.md +306 -0
  2. package/CACHE_IMPLEMENTATIONS.md +315 -0
  3. package/CONFIGURATION_GUIDE.md +167 -0
  4. package/CRITICAL_FIXES.md +68 -0
  5. package/MEMORY_LEAK_FIXES.md +270 -0
  6. package/README.md +513 -2
  7. package/dist/Aggregator.d.ts +27 -16
  8. package/dist/Cache.d.ts +59 -1
  9. package/dist/CacheContext.d.ts +35 -0
  10. package/dist/CacheMap.d.ts +132 -14
  11. package/dist/CacheStats.d.ts +51 -0
  12. package/dist/Instance.d.ts +4 -2
  13. package/dist/InstanceFactory.d.ts +3 -2
  14. package/dist/Operations.d.ts +21 -17
  15. package/dist/Options.d.ts +98 -0
  16. package/dist/browser/AsyncIndexDBCacheMap.d.ts +38 -0
  17. package/dist/browser/IndexDBCacheMap.d.ts +69 -0
  18. package/dist/browser/LocalStorageCacheMap.d.ts +59 -0
  19. package/dist/browser/SessionStorageCacheMap.d.ts +51 -0
  20. package/dist/events/CacheEventEmitter.d.ts +82 -0
  21. package/dist/events/CacheEventFactory.d.ts +121 -0
  22. package/dist/events/CacheEventTypes.d.ts +122 -0
  23. package/dist/events/index.d.ts +3 -0
  24. package/dist/eviction/EvictionManager.d.ts +57 -0
  25. package/dist/eviction/EvictionStrategy.d.ts +142 -0
  26. package/dist/eviction/EvictionStrategyConfig.d.ts +97 -0
  27. package/dist/eviction/EvictionStrategyFactory.d.ts +12 -0
  28. package/dist/eviction/EvictionStrategyValidation.d.ts +36 -0
  29. package/dist/eviction/index.d.ts +10 -0
  30. package/dist/eviction/strategies/ARCEvictionStrategy.d.ts +73 -0
  31. package/dist/eviction/strategies/FIFOEvictionStrategy.d.ts +12 -0
  32. package/dist/eviction/strategies/LFUEvictionStrategy.d.ts +38 -0
  33. package/dist/eviction/strategies/LRUEvictionStrategy.d.ts +12 -0
  34. package/dist/eviction/strategies/MRUEvictionStrategy.d.ts +12 -0
  35. package/dist/eviction/strategies/RandomEvictionStrategy.d.ts +12 -0
  36. package/dist/eviction/strategies/TwoQueueEvictionStrategy.d.ts +54 -0
  37. package/dist/index.d.ts +29 -6
  38. package/dist/index.js +5764 -435
  39. package/dist/index.js.map +4 -4
  40. package/dist/memory/EnhancedMemoryCacheMap.d.ts +81 -0
  41. package/dist/memory/MemoryCacheMap.d.ts +48 -0
  42. package/dist/normalization.d.ts +19 -0
  43. package/dist/ops/action.d.ts +2 -3
  44. package/dist/ops/all.d.ts +2 -3
  45. package/dist/ops/allAction.d.ts +2 -3
  46. package/dist/ops/allFacet.d.ts +2 -3
  47. package/dist/ops/create.d.ts +2 -3
  48. package/dist/ops/facet.d.ts +2 -3
  49. package/dist/ops/find.d.ts +2 -3
  50. package/dist/ops/findOne.d.ts +2 -3
  51. package/dist/ops/get.d.ts +3 -3
  52. package/dist/ops/one.d.ts +2 -3
  53. package/dist/ops/remove.d.ts +2 -3
  54. package/dist/ops/reset.d.ts +2 -1
  55. package/dist/ops/retrieve.d.ts +2 -3
  56. package/dist/ops/set.d.ts +2 -2
  57. package/dist/ops/update.d.ts +2 -3
  58. package/dist/ttl/TTLManager.d.ts +100 -0
  59. package/dist/ttl/index.d.ts +2 -0
  60. package/dist/utils/CacheSize.d.ts +30 -0
  61. package/fix-async-tests.js +116 -0
  62. package/package.json +16 -13
@@ -0,0 +1,35 @@
1
+ import { Item } from "@fjell/core";
2
+ import { ClientApi } from "@fjell/client-api";
3
+ import { CacheMap } from "./CacheMap";
4
+ import { Options } from "./Options";
5
+ import { CacheEventEmitter } from "./events/CacheEventEmitter";
6
+ import { TTLManager } from "./ttl/TTLManager";
7
+ import { EvictionManager } from "./eviction/EvictionManager";
8
+ import { CacheStatsManager } from "./CacheStats";
9
+ /**
10
+ * Context object that consolidates all cache-related parameters
11
+ * passed to cache operations. This prevents cache concerns from
12
+ * polluting operation signatures.
13
+ */
14
+ export interface CacheContext<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> {
15
+ /** The client API for making requests */
16
+ api: ClientApi<V, S, L1, L2, L3, L4, L5>;
17
+ /** The cache map for storing and retrieving cached items */
18
+ cacheMap: CacheMap<V, S, L1, L2, L3, L4, L5>;
19
+ /** The primary key type */
20
+ pkType: S;
21
+ /** Cache options including TTL configuration */
22
+ options: Options<V, S, L1, L2, L3, L4, L5>;
23
+ /** Event emitter for cache events */
24
+ eventEmitter: CacheEventEmitter<V, S, L1, L2, L3, L4, L5>;
25
+ /** TTL manager for handling time-to-live independently of storage */
26
+ ttlManager: TTLManager;
27
+ /** Eviction manager for handling cache eviction independently of storage */
28
+ evictionManager: EvictionManager;
29
+ /** Statistics manager for tracking cache metrics */
30
+ statsManager: CacheStatsManager;
31
+ }
32
+ /**
33
+ * Creates a CacheContext from the individual cache-related parameters
34
+ */
35
+ export declare const createCacheContext: <V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(api: ClientApi<V, S, L1, L2, L3, L4, L5>, cacheMap: CacheMap<V, S, L1, L2, L3, L4, L5>, pkType: S, options: Options<V, S, L1, L2, L3, L4, L5>, eventEmitter: CacheEventEmitter<V, S, L1, L2, L3, L4, L5>, ttlManager: TTLManager, evictionManager: EvictionManager, statsManager: CacheStatsManager) => CacheContext<V, S, L1, L2, L3, L4, L5>;
@@ -1,15 +1,133 @@
1
- import { AllItemTypeArrays, ComKey, Dictionary, Item, ItemQuery, LocKeyArray, PriKey } from "@fjell/core";
2
- export declare class CacheMap<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> extends Dictionary<ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, V> {
3
- private types;
4
- private normalizedHashFunction;
5
- constructor(types: AllItemTypeArrays<S, L1, L2, L3, L4, L5>, map?: {
6
- [key: string]: V;
7
- });
8
- get(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): V | null;
9
- includesKey(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): boolean;
10
- delete(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): void;
11
- allIn(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): V[];
12
- contains(query: ItemQuery, locations: LocKeyArray<L1, L2, L3, L4, L5> | []): boolean;
13
- queryIn(query: ItemQuery, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): V[];
14
- clone(): CacheMap<V, S, L1, L2, L3, L4, L5>;
1
+ import { AllItemTypeArrays, ComKey, Item, ItemQuery, LocKeyArray, PriKey } from "@fjell/core";
2
+ import { CacheItemMetadata, CacheMapMetadataProvider } from "./eviction/EvictionStrategy";
3
+ /**
4
+ * Abstract base interface for cache map implementations.
5
+ * Defines the contract that all cache map implementations must follow.
6
+ *
7
+ * @template V - The type of the data model item, extending Item
8
+ * @template S - The string literal type representing the model's key type
9
+ * @template L1-L5 - Optional string literal types for location hierarchy levels
10
+ */
11
+ export declare abstract class CacheMap<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> implements CacheMapMetadataProvider {
12
+ protected types: AllItemTypeArrays<S, L1, L2, L3, L4, L5>;
13
+ /**
14
+ * The implementation type identifier in the format "<category>/<implementation>"
15
+ * Examples: "memory/memory", "memory/enhanced", "browser/localStorage"
16
+ */
17
+ abstract readonly implementationType: string;
18
+ constructor(types: AllItemTypeArrays<S, L1, L2, L3, L4, L5>);
19
+ /**
20
+ * Retrieve an item by its key
21
+ */
22
+ abstract get(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<V | null>;
23
+ /**
24
+ * Store an item with its key
25
+ */
26
+ abstract set(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, value: V): void;
27
+ /**
28
+ * Check if a key exists in the cache
29
+ */
30
+ abstract includesKey(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<boolean>;
31
+ /**
32
+ * Delete an item by its key
33
+ */
34
+ abstract delete(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): void;
35
+ /**
36
+ * Get all items in the specified locations
37
+ */
38
+ abstract allIn(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
39
+ /**
40
+ * Check if any items match the query in the specified locations
41
+ */
42
+ abstract contains(query: ItemQuery, locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<boolean>;
43
+ /**
44
+ * Get all items that match the query in the specified locations
45
+ */
46
+ abstract queryIn(query: ItemQuery, locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
47
+ /**
48
+ * Create a clone of this cache map
49
+ */
50
+ abstract clone(): Promise<CacheMap<V, S, L1, L2, L3, L4, L5>>;
51
+ /**
52
+ * Get all keys in the cache
53
+ */
54
+ abstract keys(): (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[];
55
+ /**
56
+ * Get all values in the cache
57
+ */
58
+ abstract values(): Promise<V[]>;
59
+ /**
60
+ * Clear all items from the cache
61
+ */
62
+ abstract clear(): void;
63
+ /**
64
+ * Set a query result as a collection of item keys
65
+ */
66
+ abstract setQueryResult(queryHash: string, itemKeys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]): void;
67
+ /**
68
+ * Get a query result as a collection of item keys
69
+ */
70
+ abstract getQueryResult(queryHash: string): Promise<(ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[] | null>;
71
+ /**
72
+ * Check if a query result exists in cache
73
+ */
74
+ abstract hasQueryResult(queryHash: string): boolean;
75
+ /**
76
+ * Delete a specific query result
77
+ */
78
+ abstract deleteQueryResult(queryHash: string): void;
79
+ /**
80
+ * Invalidate all cached items by their keys
81
+ */
82
+ abstract invalidateItemKeys(keys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]): void;
83
+ /**
84
+ * Invalidate all items in specified locations and clear related query results
85
+ */
86
+ abstract invalidateLocation(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<void>;
87
+ /**
88
+ * Clear all query result cache entries
89
+ */
90
+ abstract clearQueryResults(): void;
91
+ /**
92
+ * Get metadata for a specific item
93
+ * @param key - Item key
94
+ * @returns Metadata if exists, null otherwise
95
+ */
96
+ abstract getMetadata(key: string): CacheItemMetadata | null;
97
+ /**
98
+ * Set metadata for a specific item
99
+ * @param key - Item key
100
+ * @param metadata - Metadata to store
101
+ */
102
+ abstract setMetadata(key: string, metadata: CacheItemMetadata): void;
103
+ /**
104
+ * Delete metadata for a specific item
105
+ * @param key - Item key
106
+ */
107
+ abstract deleteMetadata(key: string): void;
108
+ /**
109
+ * Get all metadata entries
110
+ * @returns Map of all metadata entries
111
+ */
112
+ abstract getAllMetadata(): Map<string, CacheItemMetadata>;
113
+ /**
114
+ * Clear all metadata
115
+ */
116
+ abstract clearMetadata(): void;
117
+ /**
118
+ * Get current cache size information
119
+ * @returns Object with current size metrics
120
+ */
121
+ abstract getCurrentSize(): {
122
+ itemCount: number;
123
+ sizeBytes: number;
124
+ };
125
+ /**
126
+ * Get cache size limits
127
+ * @returns Object with size limits (null means unlimited)
128
+ */
129
+ abstract getSizeLimits(): {
130
+ maxItems: number | null;
131
+ maxSizeBytes: number | null;
132
+ };
15
133
  }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Cache statistics tracking interface
3
+ */
4
+ export interface CacheStats {
5
+ /** Total number of cache requests (get/retrieve operations) */
6
+ numRequests: number;
7
+ /** Total number of cache misses (items not found in cache) */
8
+ numMisses: number;
9
+ /** Total number of cache hits (items found in cache) */
10
+ numHits: number;
11
+ /** Total number of subscription requests */
12
+ numSubscriptions: number;
13
+ /** Total number of unsubscription requests */
14
+ numUnsubscriptions: number;
15
+ /** Current number of active subscriptions */
16
+ activeSubscriptions: number;
17
+ }
18
+ /**
19
+ * Cache statistics manager that tracks various cache metrics
20
+ */
21
+ export declare class CacheStatsManager {
22
+ private stats;
23
+ /**
24
+ * Increment the request counter
25
+ */
26
+ incrementRequests(): void;
27
+ /**
28
+ * Increment the cache hit counter
29
+ */
30
+ incrementHits(): void;
31
+ /**
32
+ * Increment the cache miss counter
33
+ */
34
+ incrementMisses(): void;
35
+ /**
36
+ * Increment the subscription counter
37
+ */
38
+ incrementSubscriptions(): void;
39
+ /**
40
+ * Increment the unsubscription counter
41
+ */
42
+ incrementUnsubscriptions(): void;
43
+ /**
44
+ * Get a copy of the current statistics
45
+ */
46
+ getStats(): CacheStats;
47
+ /**
48
+ * Reset all statistics to zero
49
+ */
50
+ reset(): void;
51
+ }
@@ -6,12 +6,14 @@ import { Cache } from "./Cache";
6
6
  * The Cache Instance interface represents a cache model instance that extends the base Instance
7
7
  * from @fjell/registry and adds cache operations for interacting with cached data.
8
8
  *
9
- * This is an alias for the Cache interface since Cache now extends Instance directly.
9
+ * This is a type alias for the Cache interface. Both Cache and Instance refer to the same
10
+ * cache interface - Instance exists for backward compatibility and consistency with other
11
+ * Fjell packages that export Instance types.
10
12
  *
11
13
  * @template V - The type of the data model item, extending Item
12
14
  * @template S - The string literal type representing the model's key type
13
15
  * @template L1-L5 - Optional string literal types for location hierarchy levels
14
16
  */
15
17
  export type Instance<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> = Cache<V, S, L1, L2, L3, L4, L5>;
16
- export declare const createInstance: <V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(registry: Registry, coordinate: Coordinate<S, L1, L2, L3, L4, L5>, api: ClientApi<V, S, L1, L2, L3, L4, L5>) => Instance<V, S, L1, L2, L3, L4, L5>;
18
+ export declare const createInstance: <V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(registry: Registry, coordinate: Coordinate<S, L1, L2, L3, L4, L5>, api: ClientApi<V, S, L1, L2, L3, L4, L5>, options?: Partial<import("./Options").Options<V, S, L1, L2, L3, L4, L5>>) => Instance<V, S, L1, L2, L3, L4, L5>;
17
19
  export declare const isInstance: (instance: any) => instance is Instance<any, any, any, any, any, any, any>;
@@ -1,8 +1,9 @@
1
1
  import { Item } from "@fjell/core";
2
2
  import { ClientApi } from "@fjell/client-api";
3
3
  import { InstanceFactory as BaseInstanceFactory } from "@fjell/registry";
4
- export type InstanceFactory<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> = (api: ClientApi<V, S, L1, L2, L3, L4, L5>) => BaseInstanceFactory<S, L1, L2, L3, L4, L5>;
4
+ import { Options } from "./Options";
5
+ export type InstanceFactory<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> = (api: ClientApi<V, S, L1, L2, L3, L4, L5>, options?: Partial<Options<V, S, L1, L2, L3, L4, L5>>) => BaseInstanceFactory<S, L1, L2, L3, L4, L5>;
5
6
  /**
6
7
  * Factory function for creating cache instances
7
8
  */
8
- export declare const createInstanceFactory: <V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(api: ClientApi<V, S, L1, L2, L3, L4, L5>) => BaseInstanceFactory<S, L1, L2, L3, L4, L5>;
9
+ export declare const createInstanceFactory: <V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(api: ClientApi<V, S, L1, L2, L3, L4, L5>, options?: Partial<Options<V, S, L1, L2, L3, L4, L5>>) => BaseInstanceFactory<S, L1, L2, L3, L4, L5>;
@@ -2,69 +2,73 @@ import { ComKey, Item, ItemQuery, LocKeyArray, PriKey } from "@fjell/core";
2
2
  import { ClientApi } from "@fjell/client-api";
3
3
  import { Coordinate } from "@fjell/registry";
4
4
  import { CacheMap } from "./CacheMap";
5
+ import { CacheEventEmitter } from "./events/CacheEventEmitter";
6
+ import { Options } from "./Options";
7
+ import { TTLManager } from "./ttl/TTLManager";
8
+ import { EvictionManager } from "./eviction/EvictionManager";
9
+ import { CacheStatsManager } from "./CacheStats";
5
10
  export interface Operations<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> {
6
11
  /**
7
12
  * Retrieves all the items that match the query from cache or API.
8
13
  * Items are cached automatically after retrieval.
9
14
  */
10
- all(query?: ItemQuery, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V[]]>;
15
+ all(query?: ItemQuery, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
11
16
  /**
12
17
  * Retrieves the first item that matches the query from cache or API.
13
18
  * Item is cached automatically after retrieval.
14
19
  */
15
- one(query?: ItemQuery, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V | null]>;
20
+ one(query?: ItemQuery, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V | null>;
16
21
  /**
17
22
  * Creates a new item via API and caches it.
18
23
  */
19
- create(item: Partial<Item<S, L1, L2, L3, L4, L5>>, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]>;
24
+ create(item: Partial<Item<S, L1, L2, L3, L4, L5>>, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V>;
20
25
  /**
21
26
  * Gets an item by key from cache or API and caches it.
22
27
  */
23
- get(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V | null]>;
28
+ get(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<V | null>;
24
29
  /**
25
30
  * Retrieves an item from cache if available, otherwise from API.
26
- * Returns null as first element if item was already in cache.
27
31
  */
28
- retrieve(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5> | null, V | null]>;
32
+ retrieve(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<V | null>;
29
33
  /**
30
34
  * Removes an item via API and from cache.
31
35
  */
32
- remove(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<CacheMap<V, S, L1, L2, L3, L4, L5>>;
36
+ remove(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<void>;
33
37
  /**
34
38
  * Updates an item via API and caches the result.
35
39
  */
36
- update(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, item: Partial<Item<S, L1, L2, L3, L4, L5>>): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]>;
40
+ update(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, item: Partial<Item<S, L1, L2, L3, L4, L5>>): Promise<V>;
37
41
  /**
38
42
  * Executes an action on an item via API and caches the result.
39
43
  */
40
- action(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, action: string, body?: any): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]>;
44
+ action(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, action: string, body?: any): Promise<V>;
41
45
  /**
42
46
  * Executes an action on all items matching criteria via API and caches results.
43
47
  */
44
- allAction(action: string, body?: any, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V[]]>;
48
+ allAction(action: string, body?: any, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
45
49
  /**
46
50
  * Executes a facet query on an item via API (pass-through, no caching).
47
51
  */
48
- facet(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, facet: string, params?: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, any]>;
52
+ facet(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, facet: string, params?: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>): Promise<any>;
49
53
  /**
50
54
  * Executes a facet query on all items matching criteria via API (pass-through, no caching).
51
55
  */
52
- allFacet(facet: string, params?: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, any]>;
56
+ allFacet(facet: string, params?: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<any>;
53
57
  /**
54
58
  * Finds items using a finder method via API and caches results.
55
59
  */
56
- find(finder: string, params?: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V[]]>;
60
+ find(finder: string, params?: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
57
61
  /**
58
62
  * Finds a single item using a finder method via API and caches result.
59
63
  */
60
- findOne(finder: string, params?: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]>;
64
+ findOne(finder: string, params?: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V>;
61
65
  /**
62
66
  * Sets an item directly in cache without API call.
63
67
  */
64
- set(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, item: Item<S, L1, L2, L3, L4, L5>): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]>;
68
+ set(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, item: Item<S, L1, L2, L3, L4, L5>): Promise<V>;
65
69
  /**
66
70
  * Resets the cache, clearing all cached items.
67
71
  */
68
- reset(): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>]>;
72
+ reset(): Promise<void>;
69
73
  }
70
- export declare const createOperations: <V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(api: ClientApi<V, S, L1, L2, L3, L4, L5>, coordinate: Coordinate<S, L1, L2, L3, L4, L5>, cacheMap: CacheMap<V, S, L1, L2, L3, L4, L5>, pkType: S) => Operations<V, S, L1, L2, L3, L4, L5>;
74
+ export declare const createOperations: <V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(api: ClientApi<V, S, L1, L2, L3, L4, L5>, coordinate: Coordinate<S, L1, L2, L3, L4, L5>, cacheMap: CacheMap<V, S, L1, L2, L3, L4, L5>, pkType: S, options: Options<V, S, L1, L2, L3, L4, L5>, eventEmitter: CacheEventEmitter<V, S, L1, L2, L3, L4, L5>, ttlManager: TTLManager, evictionManager: EvictionManager, statsManager: CacheStatsManager) => Operations<V, S, L1, L2, L3, L4, L5>;
@@ -0,0 +1,98 @@
1
+ import { Item } from '@fjell/core';
2
+ import { CacheMap } from './CacheMap';
3
+ import { EvictionStrategyConfigs } from './eviction/EvictionStrategyConfig';
4
+ /**
5
+ * Available cache types for the cache instance
6
+ */
7
+ export type CacheType = 'memory' | 'localStorage' | 'sessionStorage' | 'indexedDB' | 'asyncIndexedDB' | 'custom';
8
+ /**
9
+ * Cache eviction policies for when cache size limits are reached
10
+ */
11
+ export type EvictionPolicy = 'lru' | 'lfu' | 'fifo' | 'mru' | 'random' | 'arc' | '2q';
12
+ /**
13
+ * Cache size configuration supporting bytes and item count limits
14
+ */
15
+ export interface CacheSizeConfig {
16
+ /** Maximum cache size in bytes (e.g., '100', '5KB', '10MB', '2GB', '1KiB', '512MiB') */
17
+ maxSizeBytes?: string;
18
+ /** Maximum number of items in cache */
19
+ maxItems?: number;
20
+ /** @deprecated Eviction policy is now handled by Cache-level EvictionManager via evictionConfig */
21
+ evictionPolicy?: EvictionPolicy;
22
+ }
23
+ /**
24
+ * Configuration for IndexedDB-based cache maps
25
+ */
26
+ export interface IndexedDBConfig {
27
+ /** Database name (default: 'fjell-cache') */
28
+ dbName?: string;
29
+ /** Database version (default: 1) */
30
+ version?: number;
31
+ /** Object store name (default: 'cache') */
32
+ storeName?: string;
33
+ /** Size configuration for IndexedDB cache */
34
+ size?: CacheSizeConfig;
35
+ }
36
+ /**
37
+ * Configuration for localStorage/sessionStorage-based cache maps
38
+ */
39
+ export interface WebStorageConfig {
40
+ /** Key prefix for storage items (default: 'fjell-cache:') */
41
+ keyPrefix?: string;
42
+ /** Whether to compress stored data (default: false) */
43
+ compress?: boolean;
44
+ /** Size configuration for web storage cache */
45
+ size?: CacheSizeConfig;
46
+ }
47
+ /**
48
+ * Configuration for memory-based cache maps
49
+ */
50
+ export interface MemoryConfig {
51
+ /** Maximum number of items to keep in memory (default: unlimited) */
52
+ maxItems?: number;
53
+ /** Size configuration for memory cache */
54
+ size?: CacheSizeConfig;
55
+ }
56
+ /**
57
+ * Factory function for creating custom cache map instances
58
+ */
59
+ export type CacheMapFactory<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> = (kta: [S, ...string[]]) => CacheMap<V, S, L1, L2, L3, L4, L5>;
60
+ /**
61
+ * Cache options interface for configuring cache instances
62
+ */
63
+ export interface Options<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> {
64
+ /** The type of cache to use */
65
+ cacheType: CacheType;
66
+ /** Configuration for IndexedDB cache types */
67
+ indexedDBConfig?: IndexedDBConfig;
68
+ /** Configuration for web storage cache types */
69
+ webStorageConfig?: WebStorageConfig;
70
+ /** Configuration for memory cache type */
71
+ memoryConfig?: MemoryConfig;
72
+ /** Custom cache map factory for 'custom' cache type */
73
+ customCacheMapFactory?: CacheMapFactory<V, S, L1, L2, L3, L4, L5>;
74
+ /** Eviction strategy configuration - independent of cache implementation */
75
+ evictionConfig?: EvictionStrategyConfigs;
76
+ /** Whether to enable debug logging for cache operations */
77
+ enableDebugLogging?: boolean;
78
+ /** Whether to automatically sync with the API on cache misses */
79
+ autoSync?: boolean;
80
+ /** Cache expiration time in milliseconds (default: unlimited) */
81
+ ttl?: number;
82
+ /** Maximum number of retry attempts for failed operations */
83
+ maxRetries?: number;
84
+ /** Delay between retry attempts in milliseconds */
85
+ retryDelay?: number;
86
+ }
87
+ /**
88
+ * Create cache options with defaults
89
+ */
90
+ export declare const createOptions: <V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(cacheOptions?: Partial<Options<V, S, L1, L2, L3, L4, L5>>) => Options<V, S, L1, L2, L3, L4, L5>;
91
+ /**
92
+ * Create a cache map instance based on the provided options
93
+ */
94
+ export declare const createCacheMap: <V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(kta: [S, ...string[]], options: Options<V, S, L1, L2, L3, L4, L5>) => CacheMap<V, S, L1, L2, L3, L4, L5>;
95
+ /**
96
+ * Validate cache options
97
+ */
98
+ export declare const validateOptions: <V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(options: Options<V, S, L1, L2, L3, L4, L5>) => void;
@@ -0,0 +1,38 @@
1
+ import { AllItemTypeArrays, ComKey, Item, ItemQuery, LocKeyArray, PriKey } from "@fjell/core";
2
+ /**
3
+ * IndexedDB implementation of CacheMap for browser environments.
4
+ * Data persists long-term with much larger storage limits than localStorage/sessionStorage.
5
+ *
6
+ * Note: IndexedDB is asynchronous and can store structured data.
7
+ * Storage limit is hundreds of MB or more depending on browser and user.
8
+ * This implementation uses promises for all operations.
9
+ */
10
+ export declare class AsyncIndexDBCacheMap<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> {
11
+ protected types: AllItemTypeArrays<S, L1, L2, L3, L4, L5>;
12
+ private dbName;
13
+ private storeName;
14
+ private version;
15
+ private normalizedHashFunction;
16
+ private dbPromise;
17
+ constructor(types: AllItemTypeArrays<S, L1, L2, L3, L4, L5>, dbName?: string, storeName?: string, version?: number);
18
+ private getDB;
19
+ private getStorageKey;
20
+ get(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<V | null>;
21
+ set(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, value: V): Promise<void>;
22
+ includesKey(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<boolean>;
23
+ delete(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<void>;
24
+ allIn(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
25
+ contains(query: ItemQuery, locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<boolean>;
26
+ queryIn(query: ItemQuery, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
27
+ clone(): AsyncIndexDBCacheMap<V, S, L1, L2, L3, L4, L5>;
28
+ keys(): Promise<(ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]>;
29
+ values(): Promise<V[]>;
30
+ clear(): Promise<void>;
31
+ setQueryResult(queryHash: string, itemKeys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]): Promise<void>;
32
+ getQueryResult(queryHash: string): Promise<(ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[] | null>;
33
+ hasQueryResult(queryHash: string): Promise<boolean>;
34
+ deleteQueryResult(queryHash: string): Promise<void>;
35
+ invalidateItemKeys(keys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]): Promise<void>;
36
+ invalidateLocation(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<void>;
37
+ clearQueryResults(): Promise<void>;
38
+ }
@@ -0,0 +1,69 @@
1
+ import { AllItemTypeArrays, ComKey, Item, ItemQuery, LocKeyArray, PriKey } from "@fjell/core";
2
+ import { CacheMap } from "../CacheMap";
3
+ import { AsyncIndexDBCacheMap } from "./AsyncIndexDBCacheMap";
4
+ import { CacheItemMetadata } from "../eviction/EvictionStrategy";
5
+ /**
6
+ * Synchronous wrapper for IndexedDB CacheMap implementation.
7
+ *
8
+ * This implementation provides a synchronous interface over IndexedDB
9
+ * by maintaining an in-memory cache that is periodically synchronized
10
+ * with IndexedDB storage. For full async capabilities, use AsyncIndexDBCacheMap.
11
+ *
12
+ * Note: This class maintains synchronous compatibility while providing
13
+ * persistent storage benefits of IndexedDB.
14
+ */
15
+ export declare class IndexDBCacheMap<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> extends CacheMap<V, S, L1, L2, L3, L4, L5> {
16
+ readonly implementationType = "browser/indexedDB";
17
+ asyncCache: AsyncIndexDBCacheMap<V, S, L1, L2, L3, L4, L5>;
18
+ private memoryCache;
19
+ private syncInterval;
20
+ private readonly SYNC_INTERVAL_MS;
21
+ private pendingSyncOperations;
22
+ private initializationPromise;
23
+ private isInitialized;
24
+ private readonly MAX_RETRY_ATTEMPTS;
25
+ private operationSequence;
26
+ constructor(types: AllItemTypeArrays<S, L1, L2, L3, L4, L5>, dbName?: string, storeName?: string, version?: number);
27
+ private initializeFromIndexedDB;
28
+ private startPeriodicSync;
29
+ private syncToIndexedDB;
30
+ private processPendingOperations;
31
+ private queueForSync;
32
+ private queueDeleteForSync;
33
+ private queueClearForSync;
34
+ get(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<V | null>;
35
+ set(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, value: V): void;
36
+ includesKey(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<boolean>;
37
+ delete(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): void;
38
+ allIn(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
39
+ contains(query: ItemQuery, locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<boolean>;
40
+ queryIn(query: ItemQuery, locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
41
+ clone(): Promise<IndexDBCacheMap<V, S, L1, L2, L3, L4, L5>>;
42
+ keys(): (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[];
43
+ values(): Promise<V[]>;
44
+ clear(): void;
45
+ setQueryResult(queryHash: string, itemKeys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]): void;
46
+ getQueryResult(queryHash: string): Promise<(ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[] | null>;
47
+ hasQueryResult(queryHash: string): boolean;
48
+ deleteQueryResult(queryHash: string): void;
49
+ invalidateItemKeys(keys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]): void;
50
+ invalidateLocation(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<void>;
51
+ clearQueryResults(): void;
52
+ /**
53
+ * Clean up resources when the cache is no longer needed
54
+ */
55
+ destroy(): void;
56
+ getMetadata(key: string): CacheItemMetadata | null;
57
+ setMetadata(key: string, metadata: CacheItemMetadata): void;
58
+ deleteMetadata(key: string): void;
59
+ getAllMetadata(): Map<string, CacheItemMetadata>;
60
+ clearMetadata(): void;
61
+ getCurrentSize(): {
62
+ itemCount: number;
63
+ sizeBytes: number;
64
+ };
65
+ getSizeLimits(): {
66
+ maxItems: number | null;
67
+ maxSizeBytes: number | null;
68
+ };
69
+ }
@@ -0,0 +1,59 @@
1
+ import { AllItemTypeArrays, ComKey, Item, ItemQuery, LocKeyArray, PriKey } from "@fjell/core";
2
+ import { CacheMap } from "../CacheMap";
3
+ import { CacheItemMetadata } from "../eviction/EvictionStrategy";
4
+ /**
5
+ * LocalStorage implementation of CacheMap for browser environments.
6
+ * Data persists across browser sessions and page reloads.
7
+ *
8
+ * Note: LocalStorage has a ~5-10MB limit and stores strings only.
9
+ * Data is synchronous and survives browser restarts.
10
+ * Will throw errors if storage quota is exceeded, though it attempts
11
+ * to clean up old entries first.
12
+ */
13
+ export declare class LocalStorageCacheMap<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> extends CacheMap<V, S, L1, L2, L3, L4, L5> {
14
+ readonly implementationType = "browser/localStorage";
15
+ private keyPrefix;
16
+ private normalizedHashFunction;
17
+ private readonly MAX_RETRY_ATTEMPTS;
18
+ private readonly AGGRESSIVE_CLEANUP_PERCENTAGE;
19
+ constructor(types: AllItemTypeArrays<S, L1, L2, L3, L4, L5>, keyPrefix?: string);
20
+ private getStorageKey;
21
+ private isQuotaExceededError;
22
+ private getAllKeysStartingWith;
23
+ private tryCleanupOldEntries;
24
+ private collectCacheEntries;
25
+ private removeOldestEntries;
26
+ private getAllStorageKeys;
27
+ get(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<V | null>;
28
+ set(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, value: V): void;
29
+ includesKey(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<boolean>;
30
+ delete(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): void;
31
+ allIn(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
32
+ contains(query: ItemQuery, locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<boolean>;
33
+ queryIn(query: ItemQuery, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
34
+ clone(): Promise<LocalStorageCacheMap<V, S, L1, L2, L3, L4, L5>>;
35
+ private parseStorageEntry;
36
+ keys(): (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[];
37
+ values(): Promise<V[]>;
38
+ clear(): void;
39
+ setQueryResult(queryHash: string, itemKeys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]): void;
40
+ getQueryResult(queryHash: string): Promise<(ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[] | null>;
41
+ hasQueryResult(queryHash: string): boolean;
42
+ deleteQueryResult(queryHash: string): void;
43
+ invalidateItemKeys(keys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]): void;
44
+ invalidateLocation(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<void>;
45
+ clearQueryResults(): void;
46
+ getMetadata(key: string): CacheItemMetadata | null;
47
+ setMetadata(key: string, metadata: CacheItemMetadata): void;
48
+ deleteMetadata(key: string): void;
49
+ getAllMetadata(): Map<string, CacheItemMetadata>;
50
+ clearMetadata(): void;
51
+ getCurrentSize(): {
52
+ itemCount: number;
53
+ sizeBytes: number;
54
+ };
55
+ getSizeLimits(): {
56
+ maxItems: number | null;
57
+ maxSizeBytes: number | null;
58
+ };
59
+ }