@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 ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2023 github.com/DanhezCode
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,55 @@
1
+ ## đźš§ Project Status
2
+
3
+ > **⚠️ Under active development**
4
+ > This library has not yet reached its first stable release.
5
+ > The API is still evolving, and **breaking changes** may occur at any time.
6
+ > Production use is **not recommended** until a stable version is published.
7
+
8
+ # Short-Live 🚀
9
+
10
+ **A smart, lightweight caching library that helps you store data temporarily with automatic cleanup.**
11
+
12
+ ## Why Short-Live?
13
+
14
+ ### đź§ą **Automatic Cleanup**
15
+
16
+ Expired data is cleaned up automatically in the background without your intervention.
17
+
18
+ ### 📊 **Scales Well**
19
+
20
+ Whether caching 10 items or millions, Short-Live is designed to stay fast and efficient.
21
+
22
+ ### 🏷️ **Tag-Based Invalidation**
23
+
24
+ Group related data and clear it all with a single command.
25
+
26
+ ### 🎯 **Smart Memory Management**
27
+
28
+ Intelligently prioritizes what to clean up based on usage patterns and memory constraints.
29
+
30
+ ### ⚡ **CPU Efficient**
31
+
32
+ All core operations are O(1) with minimal CPU overhead. Background cleanup runs intelligently without blocking your application. Perfect for resource-constrained environments and high-throughput scenarios.
33
+
34
+ ---
35
+
36
+ ## Documentation
37
+
38
+ - **[Getting Started](./docs/getting-started.md)** - Installation and basic usage
39
+ - **[Examples](./docs/examples.md)** - Real-world use cases (API caching, sessions, database queries, etc.)
40
+ - **[API Reference](./docs/api-reference.md)** - Complete API documentation with edge cases
41
+ - **[Configuration](./docs/configuration.md)** - All configuration options explained
42
+
43
+ ---
44
+
45
+ ## License
46
+
47
+ MIT © [Daniel Hernández Ochoa](https://github.com/DanhezCode)
48
+
49
+ ---
50
+
51
+ ## Contributing
52
+
53
+ We'd love your help! Check out [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
54
+
55
+ **Questions? Found a bug?** [Open an issue](https://github.com/neezco/cache/issues) on GitHub.
@@ -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.ts.map