@neezco/cache 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -0
- package/README.md +55 -0
- package/dist/browser/index.d.ts +276 -0
- package/dist/browser/index.js +782 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/node/index.cjs +1153 -0
- package/dist/node/index.cjs.map +1 -0
- package/dist/node/index.d.cts +276 -0
- package/dist/node/index.d.mts +276 -0
- package/dist/node/index.mjs +1124 -0
- package/dist/node/index.mjs.map +1 -0
- package/docs/.gitkeep +0 -0
- package/docs/api-reference.md +285 -0
- package/docs/configuration.md +175 -0
- package/docs/examples.md +145 -0
- package/docs/getting-started.md +86 -0
- package/package.json +93 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
//#region src/cache/delete.d.ts
|
|
2
|
+
declare const enum DELETE_REASON {
|
|
3
|
+
MANUAL = "manual",
|
|
4
|
+
EXPIRED = "expired",
|
|
5
|
+
STALE = "stale",
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/types.d.ts
|
|
9
|
+
/**
|
|
10
|
+
* Base configuration shared between CacheOptions and CacheState.
|
|
11
|
+
*/
|
|
12
|
+
interface CacheConfigBase {
|
|
13
|
+
/**
|
|
14
|
+
* Callback invoked when a key expires naturally.
|
|
15
|
+
* @param key - The expired key.
|
|
16
|
+
* @param value - The value associated with the expired key.
|
|
17
|
+
* @param reason - The reason for deletion ('expired', or 'stale').
|
|
18
|
+
*/
|
|
19
|
+
onExpire?: (key: string, value: unknown, reason: Exclude<DELETE_REASON, DELETE_REASON.MANUAL>) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Callback invoked when a key is deleted, either manually or due to expiration.
|
|
22
|
+
* @param key - The deleted key.
|
|
23
|
+
* @param value - The value of the deleted key.
|
|
24
|
+
* @param reason - The reason for deletion ('manual', 'expired', or 'stale').
|
|
25
|
+
*/
|
|
26
|
+
onDelete?: (key: string, value: unknown, reason: DELETE_REASON) => void;
|
|
27
|
+
/**
|
|
28
|
+
* Default TTL (Time-To-Live) in milliseconds for entries without explicit TTL.
|
|
29
|
+
* @default 1_800_000 (30 minutes)
|
|
30
|
+
*/
|
|
31
|
+
defaultTtl: number;
|
|
32
|
+
/**
|
|
33
|
+
* Default stale window in milliseconds for entries that do not
|
|
34
|
+
* specify their own `staleWindowMs`.
|
|
35
|
+
*
|
|
36
|
+
* This window determines how long an entry may continue to be
|
|
37
|
+
* served as stale after it reaches its expiration time.
|
|
38
|
+
*
|
|
39
|
+
* The window is always relative to the entry’s own expiration
|
|
40
|
+
* moment, regardless of whether that expiration comes from an
|
|
41
|
+
* explicit `ttl` or from the cache’s default TTL.
|
|
42
|
+
* @default null (No stale window)
|
|
43
|
+
*/
|
|
44
|
+
defaultStaleWindow: number;
|
|
45
|
+
/**
|
|
46
|
+
* Maximum number of entries the cache can hold.
|
|
47
|
+
* Beyond this limit, new entries are ignored.
|
|
48
|
+
* @default null (unlimited)
|
|
49
|
+
*/
|
|
50
|
+
maxSize?: number;
|
|
51
|
+
/**
|
|
52
|
+
* Controls how stale entries are handled when read from the cache.
|
|
53
|
+
*
|
|
54
|
+
* - true → stale entries are purged immediately after being returned.
|
|
55
|
+
* - false → stale entries are retained after being returned.
|
|
56
|
+
*
|
|
57
|
+
* @default false
|
|
58
|
+
*/
|
|
59
|
+
purgeStaleOnGet: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Controls how stale entries are handled during sweep operations.
|
|
62
|
+
*
|
|
63
|
+
* - true → stale entries are purged during sweeps.
|
|
64
|
+
* - false → stale entries are retained during sweeps.
|
|
65
|
+
*
|
|
66
|
+
* @default false
|
|
67
|
+
*/
|
|
68
|
+
purgeStaleOnSweep: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Whether to automatically start the sweep process when the cache is created.
|
|
71
|
+
*
|
|
72
|
+
* - true → sweep starts automatically.
|
|
73
|
+
* - false → sweep does not start automatically, allowing manual control.
|
|
74
|
+
*
|
|
75
|
+
* @internal
|
|
76
|
+
* @default true
|
|
77
|
+
*/
|
|
78
|
+
_autoStartSweep: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Allowed expired ratio for the cache instance.
|
|
81
|
+
*/
|
|
82
|
+
_maxAllowExpiredRatio: number;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Public configuration options for the TTL cache.
|
|
86
|
+
*/
|
|
87
|
+
type CacheOptions = Partial<CacheConfigBase>;
|
|
88
|
+
//#endregion
|
|
89
|
+
//#region src/index.d.ts
|
|
90
|
+
/**
|
|
91
|
+
* A TTL (Time-To-Live) cache implementation with support for expiration,
|
|
92
|
+
* stale windows, tag-based invalidation, and automatic sweeping.
|
|
93
|
+
*
|
|
94
|
+
* Provides O(1) constant-time operations for all core methods.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const cache = new LocalTtlCache();
|
|
99
|
+
* cache.set("user:123", { name: "Alice" }, { ttl: 5 * 60 * 1000 });
|
|
100
|
+
* const user = cache.get("user:123"); // { name: "Alice" }
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
declare class LocalTtlCache {
|
|
104
|
+
private state;
|
|
105
|
+
/**
|
|
106
|
+
* Creates a new cache instance.
|
|
107
|
+
*
|
|
108
|
+
* @param options - Configuration options for the cache (defaultTtl, defaultStaleWindow, maxSize, etc.)
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* const cache = new LocalTtlCache({
|
|
113
|
+
* defaultTtl: 30 * 60 * 1000, // 30 minutes
|
|
114
|
+
* defaultStaleWindow: 5 * 60 * 1000, // 5 minutes
|
|
115
|
+
* maxSize: 500_000, // Maximum 500_000 entries
|
|
116
|
+
* onExpire: (key, value) => console.log(`Expired: ${key}`),
|
|
117
|
+
* onDelete: (key, value, reason) => console.log(`Deleted: ${key}, reason: ${reason}`),
|
|
118
|
+
* });
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
constructor(options?: CacheOptions);
|
|
122
|
+
/**
|
|
123
|
+
* Gets the current number of entries tracked by the cache.
|
|
124
|
+
*
|
|
125
|
+
* This value may include entries that are already expired but have not yet been
|
|
126
|
+
* removed by the lazy cleanup system. Expired keys are cleaned only when it is
|
|
127
|
+
* efficient to do so, so the count can temporarily be higher than the number of
|
|
128
|
+
* actually valid (non‑expired) entries.
|
|
129
|
+
*
|
|
130
|
+
* @returns The number of entries currently stored (including entries pending cleanup)
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* console.log(cache.size); // e.g., 42
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
get size(): number;
|
|
138
|
+
/**
|
|
139
|
+
* Retrieves a value from the cache.
|
|
140
|
+
*
|
|
141
|
+
* Returns the value if it exists and is not fully expired. If an entry is in the
|
|
142
|
+
* stale window (expired but still within staleWindow), the stale value is returned.
|
|
143
|
+
*
|
|
144
|
+
|
|
145
|
+
* @param key - The key to retrieve
|
|
146
|
+
* @returns The cached value if valid, undefined otherwise
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```typescript
|
|
150
|
+
* const user = cache.get<{ name: string }>("user:123");
|
|
151
|
+
* ```
|
|
152
|
+
*
|
|
153
|
+
* @edge-cases
|
|
154
|
+
* - Returns `undefined` if the key doesn't exist
|
|
155
|
+
* - Returns `undefined` if the key has expired beyond the stale window
|
|
156
|
+
* - Returns the stale value if within the stale window
|
|
157
|
+
* - If `purgeStaleOnGet` is enabled, stale entries are deleted after being returned
|
|
158
|
+
*/
|
|
159
|
+
get<T = unknown>(key: string): T | undefined;
|
|
160
|
+
/**
|
|
161
|
+
* Sets or updates a value in the cache.
|
|
162
|
+
*
|
|
163
|
+
* If the key already exists, it will be completely replaced.
|
|
164
|
+
*
|
|
165
|
+
* @param key - The key under which to store the value
|
|
166
|
+
* @param value - The value to cache (any type)
|
|
167
|
+
* @param options - Optional configuration for this specific entry
|
|
168
|
+
* @param options.ttl - Time-To-Live in milliseconds. Defaults to `defaultTtl`
|
|
169
|
+
* @param options.staleWindow - How long to serve stale data after expiration (milliseconds)
|
|
170
|
+
* @param options.tags - One or more tags for group invalidation
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```typescript
|
|
174
|
+
* cache.set("user:123", { name: "Alice" }, {
|
|
175
|
+
* ttl: 5 * 60 * 1000,
|
|
176
|
+
* staleWindow: 1 * 60 * 1000,
|
|
177
|
+
* tags: "user:123",
|
|
178
|
+
* });
|
|
179
|
+
* ```
|
|
180
|
+
*
|
|
181
|
+
* @edge-cases
|
|
182
|
+
* - Overwriting an existing key replaces it completely
|
|
183
|
+
* - If `ttl` is 0 or Infinite, the entry never expires
|
|
184
|
+
* - If `staleWindow` is larger than `ttl`, the entry can be served as stale longer than it was fresh
|
|
185
|
+
* - Tags are optional; only necessary for group invalidation via `invalidateTag()`
|
|
186
|
+
*/
|
|
187
|
+
set(key: string, value: unknown, options?: {
|
|
188
|
+
ttl?: number;
|
|
189
|
+
staleWindow?: number;
|
|
190
|
+
tags?: string | string[];
|
|
191
|
+
}): void;
|
|
192
|
+
/**
|
|
193
|
+
* Deletes a specific key from the cache.
|
|
194
|
+
*
|
|
195
|
+
* @param key - The key to delete
|
|
196
|
+
* @returns True if the key was deleted, false if it didn't exist
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```typescript
|
|
200
|
+
* const wasDeleted = cache.delete("user:123");
|
|
201
|
+
* ```
|
|
202
|
+
*
|
|
203
|
+
* @edge-cases
|
|
204
|
+
* - Triggers the `onDelete` callback with reason `'manual'`
|
|
205
|
+
* - Does not trigger the `onExpire` callback
|
|
206
|
+
* - Returns `false` if the key was already expired
|
|
207
|
+
* - Deleting a non-existent key returns `false` without error
|
|
208
|
+
*/
|
|
209
|
+
delete(key: string): boolean;
|
|
210
|
+
/**
|
|
211
|
+
* Checks if a key exists in the cache and is not fully expired.
|
|
212
|
+
*
|
|
213
|
+
* Returns true if the key exists and is either fresh or within the stale window.
|
|
214
|
+
* Use this when you only need to check existence without retrieving the value.
|
|
215
|
+
*
|
|
216
|
+
* @param key - The key to check
|
|
217
|
+
* @returns True if the key exists and is valid, false otherwise
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```typescript
|
|
221
|
+
* if (cache.has("user:123")) {
|
|
222
|
+
* // Key exists (either fresh or stale)
|
|
223
|
+
* }
|
|
224
|
+
* ```
|
|
225
|
+
*
|
|
226
|
+
* @edge-cases
|
|
227
|
+
* - Returns `false` if the key doesn't exist
|
|
228
|
+
* - Returns `false` if the key has expired beyond the stale window
|
|
229
|
+
* - Returns `true` if the key is in the stale window (still being served)
|
|
230
|
+
* - Both `has()` and `get()` have O(1) complexity; prefer `get()` if you need the value
|
|
231
|
+
*/
|
|
232
|
+
has(key: string): boolean;
|
|
233
|
+
/**
|
|
234
|
+
* Removes all entries from the cache at once.
|
|
235
|
+
*
|
|
236
|
+
* This is useful for resetting the cache or freeing memory when needed.
|
|
237
|
+
* The `onDelete` callback is NOT invoked during clear (intentional optimization).
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```typescript
|
|
241
|
+
* cache.clear(); // cache.size is now 0
|
|
242
|
+
* ```
|
|
243
|
+
*
|
|
244
|
+
* @edge-cases
|
|
245
|
+
* - The `onDelete` callback is NOT triggered during clear
|
|
246
|
+
* - Clears both expired and fresh entries
|
|
247
|
+
* - Resets `cache.size` to 0
|
|
248
|
+
*/
|
|
249
|
+
clear(): void;
|
|
250
|
+
/**
|
|
251
|
+
* Marks all entries with one or more tags as expired (or stale, if requested).
|
|
252
|
+
*
|
|
253
|
+
* If an entry has multiple tags, invalidating ANY of those tags will invalidate the entry.
|
|
254
|
+
*
|
|
255
|
+
* @param tags - A single tag (string) or array of tags to invalidate
|
|
256
|
+
* @param asStale - If true, marks entries as stale instead of fully expired (still served from stale window)
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```typescript
|
|
260
|
+
* // Invalidate a single tag
|
|
261
|
+
* cache.invalidateTag("user:123");
|
|
262
|
+
*
|
|
263
|
+
* // Invalidate multiple tags
|
|
264
|
+
* cache.invalidateTag(["user:123", "posts:456"]);
|
|
265
|
+
* ```
|
|
266
|
+
*
|
|
267
|
+
* @edge-cases
|
|
268
|
+
* - Does not throw errors if a tag has no associated entries
|
|
269
|
+
* - Invalidating a tag doesn't prevent new entries from being tagged with it later
|
|
270
|
+
* - The `onDelete` callback is triggered with reason `'expired'` (even if `asStale` is true)
|
|
271
|
+
*/
|
|
272
|
+
invalidateTag(tags: string | string[], asStale?: boolean): void;
|
|
273
|
+
}
|
|
274
|
+
//#endregion
|
|
275
|
+
export { type CacheOptions, LocalTtlCache };
|
|
276
|
+
//# sourceMappingURL=index.d.mts.map
|