@gravito/stasis 3.1.1 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,261 @@
1
+ import { type CacheLock } from '../locks';
2
+ import type { CacheStore, TaggableStore } from '../store';
3
+ import { type CacheKey, type CacheTtl, type CacheValue } from '../types';
4
+ /**
5
+ * Configuration options for the `MemoryStore`.
6
+ *
7
+ * Used to define the behavior of the in-memory cache, such as eviction policies.
8
+ *
9
+ * @public
10
+ * @since 3.0.0
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const options: MemoryStoreOptions = { maxItems: 500 };
15
+ * ```
16
+ */
17
+ export type MemoryStoreOptions = {
18
+ /**
19
+ * Maximum number of items to keep in memory.
20
+ *
21
+ * When the limit is reached, the Least Recently Used (LRU) item is evicted.
22
+ * Set to 0 or undefined for unlimited capacity (not recommended for production).
23
+ */
24
+ maxItems?: number;
25
+ };
26
+ /**
27
+ * Performance and usage statistics for the `MemoryStore`.
28
+ *
29
+ * Provides insights into cache efficiency and capacity management.
30
+ *
31
+ * @public
32
+ * @since 3.0.0
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * const stats: MemoryCacheStats = {
37
+ * hits: 100,
38
+ * misses: 20,
39
+ * hitRate: 0.83,
40
+ * size: 500,
41
+ * evictions: 5
42
+ * };
43
+ * ```
44
+ */
45
+ export type MemoryCacheStats = {
46
+ /** Total number of successful cache lookups. */
47
+ hits: number;
48
+ /** Total number of failed cache lookups (key not found or expired). */
49
+ misses: number;
50
+ /**
51
+ * The efficiency ratio of the cache.
52
+ *
53
+ * Calculated as hits / (hits + misses). Ranges from 0.0 to 1.0.
54
+ */
55
+ hitRate: number;
56
+ /** Current number of active items stored in the cache. */
57
+ size: number;
58
+ /** Total number of items removed to make room for new entries. */
59
+ evictions: number;
60
+ };
61
+ /**
62
+ * Fast, non-persistent in-memory cache implementation.
63
+ *
64
+ * `MemoryStore` provides a high-performance backend for the `CacheStore` interface.
65
+ * It supports TTL-based expiration, LRU eviction, basic tagging for bulk invalidation,
66
+ * and local mutex locking for atomic operations.
67
+ *
68
+ * @public
69
+ * @since 3.0.0
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * const store = new MemoryStore({ maxItems: 1000 });
74
+ * await store.put('user:1', { name: 'Alice' }, 3600);
75
+ * const user = await store.get('user:1');
76
+ * ```
77
+ */
78
+ export declare class MemoryStore implements CacheStore, TaggableStore {
79
+ private entries;
80
+ private locks;
81
+ private stats;
82
+ private tagToKeys;
83
+ private keyToTags;
84
+ /**
85
+ * Creates a new MemoryStore instance.
86
+ *
87
+ * @param options - Configuration for capacity and eviction.
88
+ */
89
+ constructor(options?: MemoryStoreOptions);
90
+ /**
91
+ * Retrieves current performance metrics.
92
+ *
93
+ * @returns A snapshot of hits, misses, size, and eviction counts.
94
+ *
95
+ * @example
96
+ * ```typescript
97
+ * const stats = store.getStats();
98
+ * console.log(`Cache hit rate: ${stats.hitRate * 100}%`);
99
+ * ```
100
+ */
101
+ getStats(): MemoryCacheStats;
102
+ private cleanupExpired;
103
+ /**
104
+ * Retrieves an item from the cache by its key.
105
+ *
106
+ * If the item is expired, it will be automatically removed and `null` will be returned.
107
+ *
108
+ * @param key - The unique identifier for the cached item.
109
+ * @returns The cached value, or `null` if not found or expired.
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * const value = await store.get('my-key');
114
+ * ```
115
+ */
116
+ get<T = unknown>(key: CacheKey): Promise<CacheValue<T>>;
117
+ /**
118
+ * Stores an item in the cache with a specific TTL.
119
+ *
120
+ * If the key already exists, it will be overwritten.
121
+ *
122
+ * @param key - The unique identifier for the item.
123
+ * @param value - The data to store.
124
+ * @param ttl - Time-to-live in seconds, or a Date object for absolute expiration.
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * await store.put('settings', { theme: 'dark' }, 3600);
129
+ * ```
130
+ */
131
+ put(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<void>;
132
+ /**
133
+ * Stores an item only if it does not already exist in the cache.
134
+ *
135
+ * @param key - The unique identifier for the item.
136
+ * @param value - The data to store.
137
+ * @param ttl - Time-to-live in seconds or absolute expiration.
138
+ * @returns `true` if the item was added, `false` if it already existed.
139
+ *
140
+ * @example
141
+ * ```typescript
142
+ * const added = await store.add('unique-task', data, 60);
143
+ * ```
144
+ */
145
+ add(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<boolean>;
146
+ /**
147
+ * Removes an item from the cache.
148
+ *
149
+ * @param key - The unique identifier for the item to remove.
150
+ * @returns `true` if the item existed and was removed, `false` otherwise.
151
+ *
152
+ * @example
153
+ * ```typescript
154
+ * await store.forget('user:session');
155
+ * ```
156
+ */
157
+ forget(key: CacheKey): Promise<boolean>;
158
+ /**
159
+ * Removes all items from the cache and resets all internal indexes.
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * await store.flush();
164
+ * ```
165
+ */
166
+ flush(): Promise<void>;
167
+ /**
168
+ * Increments the value of an item in the cache.
169
+ *
170
+ * If the key does not exist, it starts from 0.
171
+ *
172
+ * @param key - The identifier for the numeric value.
173
+ * @param value - The amount to increment by (defaults to 1).
174
+ * @returns The new incremented value.
175
+ *
176
+ * @example
177
+ * ```typescript
178
+ * const count = await store.increment('page_views');
179
+ * ```
180
+ */
181
+ increment(key: CacheKey, value?: number): Promise<number>;
182
+ /**
183
+ * Decrements the value of an item in the cache.
184
+ *
185
+ * @param key - The identifier for the numeric value.
186
+ * @param value - The amount to decrement by (defaults to 1).
187
+ * @returns The new decremented value.
188
+ *
189
+ * @example
190
+ * ```typescript
191
+ * const remaining = await store.decrement('stock_count', 5);
192
+ * ```
193
+ */
194
+ decrement(key: CacheKey, value?: number): Promise<number>;
195
+ /**
196
+ * Gets the remaining time-to-live for a cached item.
197
+ *
198
+ * @param key - The identifier for the cached item.
199
+ * @returns Remaining seconds, or `null` if the item has no expiration or does not exist.
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * const secondsLeft = await store.ttl('token');
204
+ * ```
205
+ */
206
+ ttl(key: CacheKey): Promise<number | null>;
207
+ /**
208
+ * Creates a lock instance for managing exclusive access to a resource.
209
+ *
210
+ * @param name - The name of the lock.
211
+ * @param seconds - The duration the lock should be held (defaults to 10).
212
+ * @returns A `CacheLock` instance.
213
+ *
214
+ * @example
215
+ * ```typescript
216
+ * const lock = store.lock('process-report', 30);
217
+ * if (await lock.acquire()) {
218
+ * try {
219
+ * // Critical section
220
+ * } finally {
221
+ * await lock.release();
222
+ * }
223
+ * }
224
+ * ```
225
+ */
226
+ lock(name: string, seconds?: number): CacheLock;
227
+ /**
228
+ * Generates a tagged key for storage.
229
+ *
230
+ * Used internally to prefix keys with their associated tags.
231
+ *
232
+ * @param key - The original cache key.
233
+ * @param tags - List of tags to associate with the key.
234
+ * @returns A formatted string containing tags and the key.
235
+ */
236
+ tagKey(key: string, tags: readonly string[]): string;
237
+ /**
238
+ * Indexes a tagged key for bulk invalidation.
239
+ *
240
+ * @param tags - The tags to index.
241
+ * @param taggedKey - The full key (including tag prefix) to store.
242
+ */
243
+ tagIndexAdd(tags: readonly string[], taggedKey: string): void;
244
+ /**
245
+ * Removes a key from the tag indexes.
246
+ *
247
+ * @param taggedKey - The key to remove from all tag sets.
248
+ */
249
+ tagIndexRemove(taggedKey: string): void;
250
+ /**
251
+ * Invalidates all cache entries associated with any of the given tags.
252
+ *
253
+ * @param tags - The tags to flush.
254
+ *
255
+ * @example
256
+ * ```typescript
257
+ * await store.flushTags(['users', 'profiles']);
258
+ * ```
259
+ */
260
+ flushTags(tags: readonly string[]): Promise<void>;
261
+ }
@@ -0,0 +1,115 @@
1
+ import type { CacheStore } from '../store';
2
+ import type { CacheKey, CacheTtl, CacheValue } from '../types';
3
+ /**
4
+ * A "black-hole" cache implementation that discards all data.
5
+ *
6
+ * NullStore implements the `CacheStore` interface but performs no actual storage
7
+ * or retrieval operations. It is primarily used to disable caching globally
8
+ * without changing application logic, or as a mock in testing environments.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const store = new NullStore();
13
+ * await store.put('key', 'value', 60);
14
+ * const value = await store.get('key'); // always returns null
15
+ * ```
16
+ *
17
+ * @public
18
+ * @since 3.0.0
19
+ */
20
+ export declare class NullStore implements CacheStore {
21
+ /**
22
+ * Simulates a cache miss for any given key.
23
+ *
24
+ * @param _key - Identifier for the cached item.
25
+ * @returns Always `null` regardless of requested key.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const value = await store.get('my-key');
30
+ * ```
31
+ */
32
+ get<T = unknown>(_key: CacheKey): Promise<CacheValue<T>>;
33
+ /**
34
+ * Discards the provided value instead of storing it.
35
+ *
36
+ * @param _key - The identifier for the item.
37
+ * @param _value - The data to be cached.
38
+ * @param _ttl - Time-to-live in seconds.
39
+ * @returns Resolves immediately after discarding the data.
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * await store.put('user:1', { id: 1 }, 3600);
44
+ * ```
45
+ */
46
+ put(_key: CacheKey, _value: unknown, _ttl: CacheTtl): Promise<void>;
47
+ /**
48
+ * Simulates a failed attempt to add an item to the cache.
49
+ *
50
+ * Since NullStore does not store data, this method always indicates that
51
+ * the item was not added.
52
+ *
53
+ * @param _key - The identifier for the item.
54
+ * @param _value - The data to be cached.
55
+ * @param _ttl - Time-to-live in seconds.
56
+ * @returns Always returns `false`.
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const added = await store.add('key', 'value', 60); // false
61
+ * ```
62
+ */
63
+ add(_key: CacheKey, _value: unknown, _ttl: CacheTtl): Promise<boolean>;
64
+ /**
65
+ * Simulates a failed attempt to remove an item from the cache.
66
+ *
67
+ * Since no data is ever stored, there is nothing to remove.
68
+ *
69
+ * @param _key - The identifier for the item to remove.
70
+ * @returns Always returns `false`.
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * const forgotten = await store.forget('key'); // false
75
+ * ```
76
+ */
77
+ forget(_key: CacheKey): Promise<boolean>;
78
+ /**
79
+ * Performs a no-op flush operation.
80
+ *
81
+ * @returns Resolves immediately as there is no data to clear.
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * await store.flush();
86
+ * ```
87
+ */
88
+ flush(): Promise<void>;
89
+ /**
90
+ * Simulates an increment operation on a non-existent key.
91
+ *
92
+ * @param _key - The identifier for the numeric item.
93
+ * @param _value - The amount to increment by.
94
+ * @returns Always returns `0`.
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * const newValue = await store.increment('counter', 1); // 0
99
+ * ```
100
+ */
101
+ increment(_key: CacheKey, _value?: number): Promise<number>;
102
+ /**
103
+ * Simulates a decrement operation on a non-existent key.
104
+ *
105
+ * @param _key - The identifier for the numeric item.
106
+ * @param _value - The amount to decrement by.
107
+ * @returns Always returns `0`.
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * const newValue = await store.decrement('counter', 1); // 0
112
+ * ```
113
+ */
114
+ decrement(_key: CacheKey, _value?: number): Promise<number>;
115
+ }
@@ -0,0 +1,40 @@
1
+ import type { CacheLock } from '../locks';
2
+ import { type AccessPredictor } from '../prediction/AccessPredictor';
3
+ import type { CacheStore } from '../store';
4
+ import type { CacheKey, CacheTtl, CacheValue } from '../types';
5
+ /**
6
+ * A CacheStore wrapper that predicts usage patterns and prefetches data.
7
+ *
8
+ * This store observes access patterns (A -> B) and when A is requested,
9
+ * automatically attempts to 'touch' B in the underlying store.
10
+ *
11
+ * If the underlying store is a TieredStore, this effectively promotes B
12
+ * from the remote core (e.g. Redis) to the local cache (e.g. Memory)
13
+ * before it is explicitly requested, reducing latency.
14
+ *
15
+ * @public
16
+ * @since 3.2.0
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const store = new PredictiveStore(new TieredStore(l1, l2));
21
+ * // Accessing 'a' will prefetch 'b' if a -> b pattern is detected
22
+ * await store.get('a');
23
+ * ```
24
+ */
25
+ export declare class PredictiveStore implements CacheStore {
26
+ private store;
27
+ private predictor;
28
+ constructor(store: CacheStore, options?: {
29
+ predictor?: AccessPredictor;
30
+ });
31
+ get<T = unknown>(key: CacheKey): Promise<CacheValue<T>>;
32
+ put(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<void>;
33
+ add(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<boolean>;
34
+ forget(key: CacheKey): Promise<boolean>;
35
+ flush(): Promise<void>;
36
+ increment(key: CacheKey, value?: number): Promise<number>;
37
+ decrement(key: CacheKey, value?: number): Promise<number>;
38
+ lock(name: string, seconds?: number): CacheLock | undefined;
39
+ ttl(key: CacheKey): Promise<number | null>;
40
+ }
@@ -0,0 +1,83 @@
1
+ import { type CacheLock } from '../locks';
2
+ import type { CacheStore, TaggableStore } from '../store';
3
+ import { type CacheKey, type CacheTtl, type CacheValue } from '../types';
4
+ /**
5
+ * Options for configuring the `RedisStore`.
6
+ *
7
+ * @public
8
+ * @since 3.0.0
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const options: RedisStoreOptions = {
13
+ * connection: 'primary',
14
+ * prefix: 'cache:'
15
+ * };
16
+ * ```
17
+ */
18
+ export type RedisStoreOptions = {
19
+ /** The name of the Redis connection to use. */
20
+ connection?: string;
21
+ /** Optional Redis-level prefix for keys. */
22
+ prefix?: string;
23
+ };
24
+ /**
25
+ * RedisStore implements the `CacheStore` interface using Redis.
26
+ *
27
+ * It provides a distributed, persistent cache backend with support for
28
+ * atomic increments/decrements, tagging, and distributed locking.
29
+ *
30
+ * @public
31
+ * @since 3.0.0
32
+ */
33
+ export declare class RedisStore implements CacheStore, TaggableStore {
34
+ private connectionName?;
35
+ /**
36
+ * Initialize a new RedisStore instance.
37
+ *
38
+ * @param options - Redis connection and prefix settings.
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * const store = new RedisStore({ prefix: 'app:' });
43
+ * ```
44
+ */
45
+ constructor(options?: RedisStoreOptions);
46
+ private get client();
47
+ /**
48
+ * Retrieve an item from Redis.
49
+ *
50
+ * @param key - Unique cache key identifier.
51
+ * @returns Parsed JSON value or null if missing/expired.
52
+ * @throws {Error} If Redis connection fails or read errors occur.
53
+ */
54
+ get<T = unknown>(key: CacheKey): Promise<CacheValue<T>>;
55
+ /**
56
+ * Store an item in Redis.
57
+ *
58
+ * @param key - Unique cache key identifier.
59
+ * @param value - Value to serialize and store.
60
+ * @param ttl - Expiration duration.
61
+ * @throws {Error} If Redis connection fails or write errors occur.
62
+ */
63
+ put(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<void>;
64
+ add(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<boolean>;
65
+ forget(key: CacheKey): Promise<boolean>;
66
+ flush(): Promise<void>;
67
+ increment(key: CacheKey, value?: number): Promise<number>;
68
+ /**
69
+ * Decrement a numeric value in Redis.
70
+ *
71
+ * @param key - Unique cache key identifier.
72
+ * @param value - Amount to subtract.
73
+ * @returns Updated numeric value.
74
+ * @throws {Error} If key is not numeric or Redis errors occur.
75
+ */
76
+ decrement(key: CacheKey, value?: number): Promise<number>;
77
+ tagKey(key: string, _tags: readonly string[]): string;
78
+ tagIndexAdd(tags: readonly string[], taggedKey: string): Promise<void>;
79
+ tagIndexRemove(taggedKey: string): Promise<void>;
80
+ flushTags(tags: readonly string[]): Promise<void>;
81
+ ttl(key: CacheKey): Promise<number | null>;
82
+ lock(name: string, seconds?: number): CacheLock;
83
+ }
@@ -0,0 +1,37 @@
1
+ import type { CacheStore } from '../store';
2
+ import type { CacheKey, CacheTtl } from '../types';
3
+ /**
4
+ * A multi-level cache store that coordinates access between a fast local L1 cache
5
+ * and a persistent remote L2 cache.
6
+ *
7
+ * It implements the read-through and write-through patterns to ensure that the
8
+ * most frequently accessed data remains in the fastest storage tier.
9
+ *
10
+ * @public
11
+ * @since 3.2.0
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const store = new TieredStore(new MemoryStore(), new RedisStore());
16
+ * await store.put('key', 'value', 3600);
17
+ * ```
18
+ */
19
+ export declare class TieredStore implements CacheStore {
20
+ private readonly local;
21
+ private readonly remote;
22
+ /**
23
+ * Initializes a new TieredStore.
24
+ *
25
+ * @param local - The L1 cache store (usually MemoryStore).
26
+ * @param remote - The L2 cache store (usually RedisStore or FileStore).
27
+ */
28
+ constructor(local: CacheStore, remote: CacheStore);
29
+ get<T = unknown>(key: CacheKey): Promise<T | null>;
30
+ put(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<void>;
31
+ add(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<boolean>;
32
+ forget(key: CacheKey): Promise<boolean>;
33
+ flush(): Promise<void>;
34
+ increment(key: CacheKey, value?: number): Promise<number>;
35
+ decrement(key: CacheKey, value?: number): Promise<number>;
36
+ ttl(key: CacheKey): Promise<number | null>;
37
+ }
@@ -0,0 +1,29 @@
1
+ import type { CacheLock } from './locks';
2
+ import type { CacheStore } from './store';
3
+ import { type CacheKey, type CacheTtl } from './types';
4
+ /**
5
+ * A CacheStore wrapper that prefixes keys with tag-based namespacing.
6
+ *
7
+ * Used internally by CacheRepository.tags() to create isolated key spaces
8
+ * for collective cache operations (e.g., flushing all keys with a given tag).
9
+ *
10
+ * @internal
11
+ */
12
+ export declare class TaggedStore implements CacheStore {
13
+ private readonly store;
14
+ private readonly tags;
15
+ constructor(store: CacheStore & {
16
+ flushTags: (tags: readonly string[]) => Promise<void>;
17
+ tagKey: (key: string, tags: readonly string[]) => string;
18
+ tagIndexAdd: (tags: readonly string[], taggedKey: string) => void;
19
+ }, tags: readonly string[]);
20
+ private tagged;
21
+ get<T = unknown>(key: CacheKey): Promise<T>;
22
+ put(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<void>;
23
+ add(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<boolean>;
24
+ forget(key: CacheKey): Promise<boolean>;
25
+ flush(): Promise<void>;
26
+ increment(key: CacheKey, value?: number): Promise<number>;
27
+ decrement(key: CacheKey, value?: number): Promise<number>;
28
+ lock(name: string, seconds?: number): CacheLock | undefined;
29
+ }