evicting-cache 3.0.1 → 3.0.3

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/CHANGELOG.md ADDED
@@ -0,0 +1,139 @@
1
+ ## [3.0.3](https://github.com/D1g1talEntr0py/evicting-cache/compare/v3.0.2...v3.0.3) (2026-03-16)
2
+
3
+ ### Bug Fixes
4
+
5
+ * **release:** I just want this to work... (6a8b4103f7720c00c502ca9cf50c4f262d35afb0)
6
+ * **release:** kill me now (f8d2196a740389ea0acec8b9deedf408a2784c42)
7
+
8
+ ## [3.0.2](https://github.com/D1g1talEntr0py/evicting-cache/compare/v3.0.1...v3.0.2) (2026-03-16)
9
+
10
+ ### Bug Fixes
11
+
12
+ * **ci:** Fix publishing to include a valid release (997fa6a8f56d9b3fe91f8cc2206b1169607ddb25)
13
+ * **ci:** fixed autoInstallPeers mismatch (c8778b682546bd9767a3664a858435776b59f1b3)
14
+ * **ci:** more fun with peer install conflicts (53fa74b13e0688059722ad8634c1bf8bfa596de5)
15
+ * **ci:** more GitHub actions nonsense (e211d1ad81397f4b720dc534e4f8cbe9f02ce44f)
16
+
17
+ ### Documentation
18
+
19
+ * fixed badges on README.md, again (b4996da990f80df4230abfe4fc929954931ba989)
20
+
21
+ ### Miscellaneous Chores
22
+
23
+ * **deps:** updated dev dependencies and fixed package.json (6ee9c740653667b6f7f2ba5d26cab7280ae61b40)
24
+
25
+ ## [3.0.1](https://github.com/D1g1talEntr0py/evicting-cache/compare/v3.0.0...v3.0.1) (2026-03-01)
26
+
27
+ ### Bug Fixes
28
+
29
+ * fixed invalid flag for type-check script (808b4d21b02c22a46aeaa4b39ff1103dc70f7bc9)
30
+
31
+ ### Continuous Integration
32
+
33
+ * added repository to package.json (1dc7b1b2e15432e1020752d740c99d31009336f1)
34
+
35
+ ## [3.0.0](https://github.com/D1g1talEntr0py/evicting-cache/compare/v2.2.1...v3.0.0) (2026-03-01)
36
+
37
+ ### ⚠ BREAKING CHANGES
38
+
39
+ * None - all changes are backward compatible
40
+
41
+ ### Features
42
+
43
+ * add batch operations, statistics tracking, and performance optimizations (3dd757608e71e1d4d736cc7d2306ad5bec3392d2)
44
+ Added new API methods:
45
+ - delete(key) - explicit item removal matching Map API
46
+ - forEach(callback, thisArg) - iteration with proper this binding
47
+ - putAll/getAll/deleteAll - batch operations for multiple keys
48
+ - getStats/resetStats - cache hit/miss statistics tracking
49
+
50
+ Performance improvements:
51
+ - Optimized evict() by removing unsafe type assertion
52
+ - Optimized putAndEvict() by eliminating redundant has() check
53
+
54
+ Other improvements:
55
+ - Enhanced getOrPut() error handling documentation
56
+ - Improved type safety using 'unknown' instead of 'any'
57
+ - Added comprehensive test suite maintaining 100% coverage
58
+
59
+
60
+ ### Documentation
61
+
62
+ * update badges on README.md (dfdde3bf8dd52f70035c376055fbcdfadd972f90)
63
+ * update README with comprehensive documentation (8476509c194e674cca5c033fa701a996e067c3dd)
64
+ - Add badges for npm version, downloads, license, TypeScript, and coverage
65
+ - Add detailed API reference and usage examples for all methods
66
+ - Add performance table showing O(1) operations
67
+ - Standardize code examples to 2-space indentation
68
+ - Fix import statement to use named export { EvictingCache }
69
+
70
+
71
+ ### Miscellaneous Chores
72
+
73
+ * **deps:** Updates pnpm lockfile to reflect dependency upgrades (eb9bb5e7d07fecc581977be618cf3d2b0efe2810)
74
+ Refreshes the lockfile to match bumped devDependencies and toolchain updates so installs are reproducible and CI uses the exact updated dependency tree.
75
+
76
+ * **githooks:** Adds commit-msg hook (deb5d8a158283312172a043ee2ceb2b11fea13b6)
77
+ Adds an executable hook that enforces Conventional Commits for all commit messages to keep commit history structured and machine-readable for release tooling and CI validation.
78
+
79
+ * **package:** Updates package exports and devDependencies (ad8e4685fc938aae48baaa2fb254dfc2510a688d)
80
+ Updates the package exports to point to built artifacts and bumps a set of development tooling versions to align with newer runtime and linting ecosystems; removes an inline tsbuild entry to rely on external build tooling.
81
+
82
+
83
+ ### Continuous Integration
84
+
85
+ * add packageManager to package.json file (49d43111e3a56f5a2fe34ac915089228b2ba7c90)
86
+ * Adds CI workflow (235caead19ce418229750e13b00ca768598916d5)
87
+ Adds a GitHub Actions CI pipeline that runs installs, linting, type checks, tests with coverage, and builds across a Node matrix to ensure quality and compatibility across supported Node versions.
88
+
89
+ * **release:** Adds release workflow & semantic-release config (0b8da372b6366b947d001a57e4415541e04105b7)
90
+ Automates releases on main by wiring a release workflow and configuring semantic-release so versioning and changelogs are generated from Conventional Commits and publishes artifacts accordingly.
91
+
92
+ # Changelog
93
+
94
+ All notable changes to this project will be documented in this file.
95
+
96
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
97
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
98
+
99
+ ## [2.3.1] - 2025-10-28
100
+
101
+ ### Changed
102
+ - Updated README with comprehensive documentation of all features
103
+ - Added badges for npm version, downloads, license, TypeScript version, and test coverage
104
+ - Improved code examples in README for clarity
105
+ - Added detailed usage examples for all API methods
106
+ - Added performance characteristics table
107
+ - Added complete API reference section
108
+ - Enhanced TypeScript usage examples
109
+
110
+ ### Fixed
111
+ - Fixed import statement in README to use named export `{ EvictingCache }` instead of default import
112
+
113
+ ## [2.3.0] - 2025-10-27
114
+
115
+ ### Added
116
+ - `delete(key)` method to explicitly remove items from the cache, matching standard Map API
117
+ - `forEach(callback, thisArg?)` method to iterate over cache entries with proper `this` binding support
118
+ - Batch operations for improved performance:
119
+ - `putAll(entries)` - Add multiple key-value pairs at once
120
+ - `getAll(keys)` - Retrieve multiple values (returns Map, excludes missing keys)
121
+ - `deleteAll(keys)` - Remove multiple keys (returns count of removed items)
122
+ - Cache statistics tracking:
123
+ - `getStats()` - Returns hit/miss counts and calculated hit rate
124
+ - `resetStats()` - Resets statistics counters to zero
125
+ - Statistics are automatically tracked on `get()` operations (hits and misses)
126
+ - Comprehensive test suite for all new features maintaining 100% code coverage
127
+
128
+ ### Changed
129
+ - Improved `getOrPut()` error handling with explicit documentation that cache state remains unchanged when producer function throws
130
+ - Enhanced `getOrPut()` implementation to be more explicit about error handling behavior
131
+
132
+ ### Fixed
133
+ - Performance optimization in `evict()` method - removed unsafe type assertion and simplified iterator usage
134
+ - Performance optimization in `putAndEvict()` method - removed redundant `has()` check, now leverages `delete()` return value
135
+
136
+ ### Security
137
+ - Replaced `any` type with `unknown` type in `forEach()` `thisArg` parameter for improved type safety
138
+
139
+ ## [2.2.1] - Previous Release
package/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # Evicting Cache
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/@d1g1tal/evicting-cache?color=blue)](https://www.npmjs.com/package/@d1g1tal/evicting-cache)
4
- [![npm downloads](https://img.shields.io/npm/dm/@d1g1tal/evicting-cache)](https://www.npmjs.com/package/@d1g1tal/evicting-cache)
3
+ [![npm version](https://img.shields.io/npm/v/evicting-cache?color=blue)](https://www.npmjs.com/package/evicting-cache)
4
+ [![npm downloads](https://img.shields.io/npm/dm/evicting-cache)](https://www.npmjs.com/package/evicting-cache)
5
5
  [![CI](https://github.com/D1g1talEntr0py/evicting-cache/actions/workflows/ci.yml/badge.svg)](https://github.com/D1g1talEntr0py/evicting-cache/actions/workflows/ci.yml)
6
6
  [![codecov](https://codecov.io/gh/D1g1talEntr0py/evicting-cache/graph/badge.svg)](https://codecov.io/gh/D1g1talEntr0py/evicting-cache)
7
- [![License: MIT](https://img.shields.io/github/license/D1g1talEntr0py/evicting-cache)](https://github.com/D1g1talEntr0py/evicting-cache/blob/main/LICENSE)
8
- [![Node.js](https://img.shields.io/node/v/@d1g1tal/evicting-cache)](https://nodejs.org)
7
+ [![License: ISC](https://img.shields.io/github/license/D1g1talEntr0py/evicting-cache)](https://github.com/D1g1talEntr0py/evicting-cache/blob/main/LICENSE)
8
+ [![Node.js](https://img.shields.io/node/v/evicting-cache)](https://nodejs.org)
9
9
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
10
10
 
11
11
  A lightweight, high-performance TypeScript implementation of an LRU (Least Recently Used) cache with automatic eviction.
@@ -0,0 +1,181 @@
1
+ type CacheStats = {
2
+ hits: number;
3
+ misses: number;
4
+ hitRate: number;
5
+ };
6
+ /** JavaScript implementation of a Least Recently Used(LRU) Cache using a Map. */
7
+ declare class EvictingCache<K, V> {
8
+ private readonly _capacity;
9
+ private readonly cache;
10
+ private hits;
11
+ private misses;
12
+ /**
13
+ * Creates a new Evicting Cache with the given capacity.
14
+ *
15
+ * @param {number} [capacity=100] The maximum number of key-value pairs the cache can hold.
16
+ */
17
+ constructor(capacity?: number);
18
+ /**
19
+ * Returns the value associated with the given key from the cache and updates the LRU order.
20
+ *
21
+ * @param {K} key The key to get the value for.
22
+ * @returns {V | null} The associated value if the key is in the cache, or null otherwise.
23
+ */
24
+ get(key: K): V | null;
25
+ /**
26
+ * Returns true if the given key is in the cache, false otherwise.
27
+ *
28
+ * @param {K} key The key to check.
29
+ * @returns {boolean} True if the key is in the cache, false otherwise.
30
+ */
31
+ has(key: K): boolean;
32
+ /**
33
+ * Adds a new key-value pair to the cache and updates the LRU order.
34
+ * If adding the new pair will exceed the capacity, removes the least recently used pair from the cache.
35
+ *
36
+ * @param {K} key The key to add.
37
+ * @param {V} value The value to add.
38
+ * @returns {void}
39
+ */
40
+ put(key: K, value: V): void;
41
+ /**
42
+ * Removes the specified key from the cache.
43
+ *
44
+ * @param {K} key The key to remove.
45
+ * @returns {boolean} True if the key was in the cache and was removed, false otherwise.
46
+ */
47
+ delete(key: K): boolean;
48
+ /**
49
+ * Returns the value associated with the given key from the cache without updating the LRU order.
50
+ *
51
+ * @param {K} key The key to get the value for.
52
+ * @returns {V | null} The associated value if the key is in the cache, or null otherwise.
53
+ */
54
+ peek(key: K): V | null;
55
+ /**
56
+ * Returns the value for the key if it exists in the cache. If not, put the key-value pair into the cache and return the value.
57
+ * If the producer function throws an error, the cache state is not modified.
58
+ *
59
+ * @param {K} key The key.
60
+ * @param {function(): V} producer The value to put if the key does not exist in the cache.
61
+ * @returns {V} The value corresponding to the key.
62
+ */
63
+ getOrPut(key: K, producer: () => V): V;
64
+ /**
65
+ * Removes the least recently used key-value pair from the cache.
66
+ * @returns {boolean} True if an item was removed, false otherwise.
67
+ */
68
+ evict(): boolean;
69
+ /**
70
+ * Clears the cache and the LRU list.
71
+ * @returns {void}
72
+ */
73
+ clear(): void;
74
+ /**
75
+ * Executes a provided function once per each key/value pair in the cache, in insertion order.
76
+ * @param {(value: V, key: K, cache: EvictingCache<K, V>) => void} callbackfn Function to execute for each element.
77
+ * @param {unknown} [thisArg] Value to use as `this` when executing callback.
78
+ * @returns {void}
79
+ */
80
+ forEach(callbackfn: (value: V, key: K, cache: EvictingCache<K, V>) => void, thisArg?: unknown): void;
81
+ /**
82
+ * Adds multiple key-value pairs to the cache.
83
+ * Each pair is added individually, following the same LRU eviction rules as put().
84
+ * @param {Iterable<[K, V]>} entries The entries to add.
85
+ * @returns {void}
86
+ */
87
+ putAll(entries: Iterable<[K, V]>): void;
88
+ /**
89
+ * Gets multiple values from the cache.
90
+ * Each get updates the LRU order for that key.
91
+ *
92
+ * @param {Iterable<K>} keys The keys to get values for.
93
+ * @returns {Map<K, V>} A map of keys to their values (excludes missing keys).
94
+ */
95
+ getAll(keys: Iterable<K>): Map<K, V>;
96
+ /**
97
+ * Removes multiple keys from the cache.
98
+ *
99
+ * @param {Iterable<K>} keys The keys to remove.
100
+ * @returns {number} The number of keys that were removed.
101
+ */
102
+ deleteAll(keys: Iterable<K>): number;
103
+ /**
104
+ * Gets cache statistics including hit/miss counts and hit rate.
105
+ *
106
+ * @returns {CacheStats} Cache statistics.
107
+ */
108
+ getStats(): CacheStats;
109
+ /**
110
+ * Resets cache statistics to zero.
111
+ *
112
+ * @returns {void}
113
+ */
114
+ resetStats(): void;
115
+ /**
116
+ * Gets the capacity of the cache.
117
+ * This is the maximum number of key-value pairs the cache can hold.
118
+ * This is not the number of key-value pairs in the cache.
119
+ *
120
+ * @readonly
121
+ * @returns {number} The capacity of the cache.
122
+ */
123
+ get capacity(): number;
124
+ /**
125
+ * Gets the size of the cache.
126
+ * This is the number of key-value pairs in the cache.
127
+ * This is not the capacity of the cache.
128
+ * The capacity is the maximum number of key-value pairs the cache can hold.
129
+ * The size is the number of key-value pairs currently in the cache.
130
+ * The size will be less than or equal to the capacity.
131
+ *
132
+ * @returns {number} The size of the cache.
133
+ */
134
+ get size(): number;
135
+ /**
136
+ * Returns an iterator over the keys in the cache.
137
+ * The keys are returned in the order of least recently used to most recently used.
138
+ *
139
+ * @returns {IterableIterator<K>} An iterator over the keys in the cache.
140
+ */
141
+ keys(): IterableIterator<K>;
142
+ /**
143
+ * Returns an iterator over the values in the cache.
144
+ * The values are returned in the order of least recently used to most recently used.
145
+ *
146
+ * @returns {IterableIterator<V>} An iterator over the values in the cache.
147
+ */
148
+ values(): IterableIterator<V>;
149
+ /**
150
+ * Returns an iterator over the entries in the cache.
151
+ * The entries are returned in the order of least recently used to most recently used.
152
+ *
153
+ * @returns {IterableIterator<[K, V]>} An iterator over the entries in the cache.
154
+ */
155
+ entries(): IterableIterator<[K, V]>;
156
+ /**
157
+ * Returns an iterator over the entries in the cache.
158
+ * The entries are returned in the order of least recently used to most recently used.
159
+ *
160
+ * @returns {IterableIterator<[K, V]>} An iterator over the entries in the cache.
161
+ */
162
+ [Symbol.iterator](): IterableIterator<[K, V]>;
163
+ /**
164
+ * Gets the description of the object.
165
+ *
166
+ * @override
167
+ * @returns {string} The description of the object.
168
+ */
169
+ get [Symbol.toStringTag](): string;
170
+ /**
171
+ * Puts a key-value pair into the cache and evicts the least recently used item if necessary.
172
+ * If the key already exists, the item is removed and re-added to update its position.
173
+ * If the cache is full, the least recently used item is evicted and the new item is added.
174
+ * @param {K} key The key to put.
175
+ * @param {V} value The value to put.
176
+ * @returns {V} The value that was put.
177
+ */
178
+ private putAndEvict;
179
+ }
180
+
181
+ export { EvictingCache };
@@ -0,0 +1,2 @@
1
+ var r=class{_capacity;cache;hits=0;misses=0;constructor(e=100){if(e<1)throw new RangeError("capacity must be greater than 0");if(!Number.isInteger(e))throw new RangeError("capacity must be an integer");this._capacity=e,this.cache=new Map}get(e){let t=this.cache.get(e);return t===void 0?(this.misses++,null):(this.hits++,this.cache.delete(e),this.cache.set(e,t),t)}has(e){return this.cache.has(e)}put(e,t){this.putAndEvict(e,t)}delete(e){return this.cache.delete(e)}peek(e){return this.cache.get(e)??null}getOrPut(e,t){let s=this.get(e);if(s!==null)return s;let i=t();return this.putAndEvict(e,i)}evict(){let e=this.cache.keys().next();return e.done?!1:this.cache.delete(e.value)}clear(){this.cache.clear()}forEach(e,t){let s=t!==void 0?e.bind(t):e;this.cache.forEach((i,a)=>s(i,a,this))}putAll(e){for(let[t,s]of e)this.put(t,s)}getAll(e){let t=new Map;for(let s of e){let i=this.get(s);i!==null&&t.set(s,i)}return t}deleteAll(e){let t=0;for(let s of e)this.cache.delete(s)&&t++;return t}getStats(){let e=this.hits+this.misses;return{hits:this.hits,misses:this.misses,hitRate:e===0?0:this.hits/e}}resetStats(){this.hits=0,this.misses=0}get capacity(){return this._capacity}get size(){return this.cache.size}keys(){return this.cache.keys()}values(){return this.cache.values()}entries(){return this.cache.entries()}[Symbol.iterator](){return this.entries()}get[Symbol.toStringTag](){return"EvictingCache"}putAndEvict(e,t){return!this.cache.delete(e)&&this._capacity<=this.cache.size&&this.evict(),this.cache.set(e,t),t}};export{r as EvictingCache};
2
+ //# sourceMappingURL=evicting-cache.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/evicting-cache.ts"],
4
+ "sourcesContent": ["type CacheStats = {\n\thits: number;\n\tmisses: number;\n\thitRate: number;\n};\n\n/** JavaScript implementation of a Least Recently Used(LRU) Cache using a Map. */\nexport class EvictingCache<K, V> {\n\tprivate readonly _capacity: number;\n\tprivate readonly cache: Map<K, V>;\n\tprivate hits = 0;\n\tprivate misses = 0;\n\n\t/**\n\t * Creates a new Evicting Cache with the given capacity.\n\t *\n\t * @param {number} [capacity=100] The maximum number of key-value pairs the cache can hold.\n\t */\n\tconstructor(capacity: number = 100) {\n\t\tif (capacity < 1) { throw new RangeError('capacity must be greater than 0') }\n\t\tif (!Number.isInteger(capacity)) { throw new RangeError('capacity must be an integer') }\n\n\t\tthis._capacity = capacity;\n\t\tthis.cache = new Map();\n\t}\n\n\t/**\n\t * Returns the value associated with the given key from the cache and updates the LRU order.\n\t *\n\t * @param {K} key The key to get the value for.\n\t * @returns {V | null} The associated value if the key is in the cache, or null otherwise.\n\t */\n\tget(key: K): V | null {\n\t\tconst value = this.cache.get(key);\n\t\tif (value === undefined) {\n\t\t\tthis.misses++;\n\t\t\treturn null;\n\t\t}\n\n\t\tthis.hits++;\n\t\tthis.cache.delete(key);\n\t\t// Move the accessed item to the end (most recently used)\n\t\tthis.cache.set(key, value);\n\n\t\treturn value;\n\t}\n\n\t/**\n\t * Returns true if the given key is in the cache, false otherwise.\n\t *\n\t * @param {K} key The key to check.\n\t * @returns {boolean} True if the key is in the cache, false otherwise.\n\t */\n\thas(key: K): boolean {\n\t\treturn this.cache.has(key);\n\t}\n\n\t/**\n\t * Adds a new key-value pair to the cache and updates the LRU order.\n\t * If adding the new pair will exceed the capacity, removes the least recently used pair from the cache.\n\t *\n\t * @param {K} key The key to add.\n\t * @param {V} value The value to add.\n\t * @returns {void}\n\t */\n\tput(key: K, value: V): void {\n\t\tthis.putAndEvict(key, value);\n\t}\n\n\t/**\n\t * Removes the specified key from the cache.\n\t *\n\t * @param {K} key The key to remove.\n\t * @returns {boolean} True if the key was in the cache and was removed, false otherwise.\n\t */\n\tdelete(key: K): boolean {\n\t\treturn this.cache.delete(key);\n\t}\n\n\t/**\n\t * Returns the value associated with the given key from the cache without updating the LRU order.\n\t *\n\t * @param {K} key The key to get the value for.\n\t * @returns {V | null} The associated value if the key is in the cache, or null otherwise.\n\t */\n\tpeek(key: K): V | null {\n\t\treturn this.cache.get(key) ?? null;\n\t}\n\n\t/**\n\t * Returns the value for the key if it exists in the cache. If not, put the key-value pair into the cache and return the value.\n\t * If the producer function throws an error, the cache state is not modified.\n\t *\n\t * @param {K} key The key.\n\t * @param {function(): V} producer The value to put if the key does not exist in the cache.\n\t * @returns {V} The value corresponding to the key.\n\t */\n\tgetOrPut(key: K, producer: () => V): V {\n\t\tconst existing = this.get(key);\n\t\tif (existing !== null) { return existing }\n\n\t\t// If producer throws, cache state remains unchanged\n\t\tconst value = producer();\n\t\treturn this.putAndEvict(key, value);\n\t}\n\n\t/**\n\t * Removes the least recently used key-value pair from the cache.\n\t * @returns {boolean} True if an item was removed, false otherwise.\n\t */\n\tevict(): boolean {\n\t\tconst firstEntry = this.cache.keys().next();\n\t\tif (firstEntry.done) { return false }\n\n\t\treturn this.cache.delete(firstEntry.value);\n\t}\n\n\t/**\n\t * Clears the cache and the LRU list.\n\t * @returns {void}\n\t */\n\tclear(): void {\n\t\tthis.cache.clear();\n\t}\n\n\t/**\n\t * Executes a provided function once per each key/value pair in the cache, in insertion order.\n\t * @param {(value: V, key: K, cache: EvictingCache<K, V>) => void} callbackfn Function to execute for each element.\n\t * @param {unknown} [thisArg] Value to use as `this` when executing callback.\n\t * @returns {void}\n\t */\n\tforEach(callbackfn: (value: V, key: K, cache: EvictingCache<K, V>) => void, thisArg?: unknown): void {\n\t\tconst boundCallback = thisArg !== undefined ? callbackfn.bind(thisArg) : callbackfn;\n\t\tthis.cache.forEach((value, key) => boundCallback(value, key, this));\n\t}\n\n\t/**\n\t * Adds multiple key-value pairs to the cache.\n\t * Each pair is added individually, following the same LRU eviction rules as put().\n\t * @param {Iterable<[K, V]>} entries The entries to add.\n\t * @returns {void}\n\t */\n\tputAll(entries: Iterable<[K, V]>): void {\n\t\tfor (const [key, value] of entries) { this.put(key, value) }\n\t}\n\n\t/**\n\t * Gets multiple values from the cache.\n\t * Each get updates the LRU order for that key.\n\t *\n\t * @param {Iterable<K>} keys The keys to get values for.\n\t * @returns {Map<K, V>} A map of keys to their values (excludes missing keys).\n\t */\n\tgetAll(keys: Iterable<K>): Map<K, V> {\n\t\tconst result = new Map<K, V>();\n\t\tfor (const key of keys) {\n\t\t\tconst value = this.get(key);\n\t\t\tif (value !== null) { result.set(key, value) }\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Removes multiple keys from the cache.\n\t *\n\t * @param {Iterable<K>} keys The keys to remove.\n\t * @returns {number} The number of keys that were removed.\n\t */\n\tdeleteAll(keys: Iterable<K>): number {\n\t\tlet count = 0;\n\t\tfor (const key of keys) {\n\t\t\tif (this.cache.delete(key)) { count++ }\n\t\t}\n\n\t\treturn count;\n\t}\n\n\t/**\n\t * Gets cache statistics including hit/miss counts and hit rate.\n\t *\n\t * @returns {CacheStats} Cache statistics.\n\t */\n\tgetStats(): CacheStats {\n\t\tconst total = this.hits + this.misses;\n\n\t\treturn { hits: this.hits, misses: this.misses, hitRate: total === 0 ? 0 : this.hits / total };\n\t}\n\n\t/**\n\t * Resets cache statistics to zero.\n\t *\n\t * @returns {void}\n\t */\n\tresetStats(): void {\n\t\tthis.hits = 0;\n\t\tthis.misses = 0;\n\t}\n\n\t/**\n\t * Gets the capacity of the cache.\n\t * This is the maximum number of key-value pairs the cache can hold.\n\t * This is not the number of key-value pairs in the cache.\n\t *\n\t * @readonly\n\t * @returns {number} The capacity of the cache.\n\t */\n\tget capacity(): number {\n\t\treturn this._capacity;\n\t}\n\n\t/**\n\t * Gets the size of the cache.\n\t * This is the number of key-value pairs in the cache.\n\t * This is not the capacity of the cache.\n\t * The capacity is the maximum number of key-value pairs the cache can hold.\n\t * The size is the number of key-value pairs currently in the cache.\n\t * The size will be less than or equal to the capacity.\n\t *\n\t * @returns {number} The size of the cache.\n\t */\n\tget size(): number {\n\t\treturn this.cache.size;\n\t}\n\n\t/**\n\t * Returns an iterator over the keys in the cache.\n\t * The keys are returned in the order of least recently used to most recently used.\n\t *\n\t * @returns {IterableIterator<K>} An iterator over the keys in the cache.\n\t */\n\tkeys(): IterableIterator<K> {\n\t\treturn this.cache.keys();\n\t}\n\n\t/**\n\t * Returns an iterator over the values in the cache.\n\t * The values are returned in the order of least recently used to most recently used.\n\t *\n\t * @returns {IterableIterator<V>} An iterator over the values in the cache.\n\t */\n\tvalues(): IterableIterator<V> {\n\t\treturn this.cache.values();\n\t}\n\n\t/**\n\t * Returns an iterator over the entries in the cache.\n\t * The entries are returned in the order of least recently used to most recently used.\n\t *\n\t * @returns {IterableIterator<[K, V]>} An iterator over the entries in the cache.\n\t */\n\tentries(): IterableIterator<[K, V]> {\n\t\treturn this.cache.entries();\n\t}\n\n\t/**\n\t * Returns an iterator over the entries in the cache.\n\t * The entries are returned in the order of least recently used to most recently used.\n\t *\n\t * @returns {IterableIterator<[K, V]>} An iterator over the entries in the cache.\n\t */\n\t[Symbol.iterator](): IterableIterator<[K, V]> {\n\t\treturn this.entries();\n\t}\n\n\t/**\n\t * Gets the description of the object.\n\t *\n\t * @override\n\t * @returns {string} The description of the object.\n\t */\n\tget [Symbol.toStringTag](): string {\n\t\treturn 'EvictingCache';\n\t}\n\n\t/**\n\t * Puts a key-value pair into the cache and evicts the least recently used item if necessary.\n\t * If the key already exists, the item is removed and re-added to update its position.\n\t * If the cache is full, the least recently used item is evicted and the new item is added.\n\t * @param {K} key The key to put.\n\t * @param {V} value The value to put.\n\t * @returns {V} The value that was put.\n\t */\n\tprivate putAndEvict(key: K, value: V): V {\n\t\tconst existed = this.cache.delete(key);\n\t\tif (!existed && this._capacity <= this.cache.size) { this.evict() }\n\n\t\tthis.cache.set(key, value);\n\n\t\treturn value;\n\t}\n}"],
5
+ "mappings": "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",
6
+ "names": ["EvictingCache", "capacity", "key", "value", "producer", "existing", "firstEntry", "callbackfn", "thisArg", "boundCallback", "entries", "keys", "result", "count", "total"]
7
+ }
package/package.json CHANGED
@@ -1,14 +1,30 @@
1
1
  {
2
2
  "name": "evicting-cache",
3
3
  "author": "D1g1talEntr0py",
4
- "version": "3.0.1",
5
- "packageManager": "pnpm@10.30.3",
4
+ "version": "3.0.3",
6
5
  "license": "ISC",
7
6
  "description": "Cache implementation with an LRU evicting policy",
7
+ "homepage": "https://github.com/D1g1talEntr0py/evicting-cache#readme",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/D1g1talEntr0py/evicting-cache"
11
11
  },
12
+ "bugs": {
13
+ "url": "https://github.com/D1g1talEntr0py/evicting-cache/issues"
14
+ },
15
+ "maintainers": [
16
+ {
17
+ "name": "D1g1talEntr0py",
18
+ "email": "jason.dimeo@gmail.com"
19
+ }
20
+ ],
21
+ "engines": {
22
+ "node": ">=20.16.0"
23
+ },
24
+ "publishConfig": {
25
+ "registry": "https://registry.npmjs.org",
26
+ "access": "public"
27
+ },
12
28
  "type": "module",
13
29
  "exports": {
14
30
  ".": {
@@ -18,47 +34,47 @@
18
34
  },
19
35
  "files": [
20
36
  "dist/",
21
- "src/"
22
- ],
23
- "scripts": {
24
- "build": "tsbuild",
25
- "build:watch": "tsbuild --watch",
26
- "type-check": "tsbuild --noEmit",
27
- "lint": "eslint",
28
- "test": "vitest run",
29
- "test:coverage": "vitest run --coverage",
30
- "test:watch": "vitest",
31
- "prepublish": "pnpm lint && pnpm test && pnpm -s build --minify --force",
32
- "preversion": "pnpm lint && pnpm test",
33
- "version": "node -e \"const fs=require('fs');const d=new Date().toISOString().split('T')[0];const v=require('./package.json').version;let c=fs.readFileSync('CHANGELOG.md','utf8');c=c.replace('## [Unreleased]','## ['+v+'] - '+d);fs.writeFileSync('CHANGELOG.md',c);\" && git add CHANGELOG.md"
34
- },
35
- "keywords": [
36
- "cache",
37
- "evicting-cache",
38
- "lru",
39
- "lru-cache",
40
- "evicting-lru-cache"
37
+ "src/",
38
+ "README.md",
39
+ "CHANGELOG.md",
40
+ "LICENSE"
41
41
  ],
42
42
  "devDependencies": {
43
- "@d1g1tal/tsbuild": "^1.3.2",
44
- "@eslint/compat": "^2.0.2",
43
+ "@d1g1tal/tsbuild": "^1.6.0",
44
+ "@eslint/compat": "^2.0.3",
45
45
  "@eslint/js": "^10.0.1",
46
46
  "@types/eslint": "^9.6.1",
47
- "@types/node": "^25.3.3",
48
- "@typescript-eslint/eslint-plugin": "^8.56.1",
49
- "@typescript-eslint/parser": "^8.56.1",
50
- "@vitest/coverage-v8": "^4.0.18",
51
- "eslint": "^10.0.2",
52
- "eslint-plugin-compat": "^7.0.0",
53
- "eslint-plugin-jsdoc": "^62.7.1",
47
+ "@types/node": "^25.5.0",
48
+ "@typescript-eslint/eslint-plugin": "^8.57.1",
49
+ "@typescript-eslint/parser": "^8.57.1",
50
+ "@vitest/coverage-v8": "^4.1.0",
51
+ "eslint": "^10.0.3",
52
+ "eslint-plugin-compat": "^7.0.1",
53
+ "eslint-plugin-jsdoc": "^62.8.0",
54
54
  "globals": "^17.4.0",
55
55
  "typescript": "^5.9.3",
56
- "typescript-eslint": "^8.56.1",
57
- "vitest": "^4.0.18"
56
+ "typescript-eslint": "^8.57.1",
57
+ "vitest": "^4.1.0"
58
58
  },
59
59
  "browserslist": [
60
60
  "defaults",
61
61
  "not ios_saf < 15",
62
62
  "not op_mini all"
63
- ]
64
- }
63
+ ],
64
+ "keywords": [
65
+ "cache",
66
+ "evicting-cache",
67
+ "lru",
68
+ "lru-cache",
69
+ "evicting-lru-cache"
70
+ ],
71
+ "scripts": {
72
+ "build": "tsbuild",
73
+ "build:watch": "tsbuild --watch",
74
+ "type-check": "tsbuild --noEmit",
75
+ "lint": "eslint ./src",
76
+ "test": "vitest run",
77
+ "test:coverage": "vitest run --coverage",
78
+ "test:watch": "vitest"
79
+ }
80
+ }