@isaacs/ttlcache 1.4.1 → 2.0.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.
package/LICENSE.md ADDED
@@ -0,0 +1,55 @@
1
+ # Blue Oak Model License
2
+
3
+ Version 1.0.0
4
+
5
+ ## Purpose
6
+
7
+ This license gives everyone as much permission to work with
8
+ this software as possible, while protecting contributors
9
+ from liability.
10
+
11
+ ## Acceptance
12
+
13
+ In order to receive this license, you must agree to its
14
+ rules. The rules of this license are both obligations
15
+ under that agreement and conditions to your license.
16
+ You must not do anything with this software that triggers
17
+ a rule that you cannot or will not follow.
18
+
19
+ ## Copyright
20
+
21
+ Each contributor licenses you to do everything with this
22
+ software that would otherwise infringe that contributor's
23
+ copyright in it.
24
+
25
+ ## Notices
26
+
27
+ You must ensure that everyone who gets a copy of
28
+ any part of this software from you, with or without
29
+ changes, also gets the text of this license or a link to
30
+ <https://blueoakcouncil.org/license/1.0.0>.
31
+
32
+ ## Excuse
33
+
34
+ If anyone notifies you in writing that you have not
35
+ complied with [Notices](#notices), you can keep your
36
+ license by taking all practical steps to comply within 30
37
+ days after the notice. If you do not do so, your license
38
+ ends immediately.
39
+
40
+ ## Patent
41
+
42
+ Each contributor licenses you to do everything with this
43
+ software that would otherwise infringe any patent claims
44
+ they can license or become able to license.
45
+
46
+ ## Reliability
47
+
48
+ No contributor can revoke this license.
49
+
50
+ ## No Liability
51
+
52
+ ***As far as the law allows, this software comes as is,
53
+ without any warranty or condition, and no contributor
54
+ will be liable to anyone for any damages related to this
55
+ software or this license, under any kind of legal claim.***
package/README.md CHANGED
@@ -7,7 +7,7 @@ The time-based use-recency-unaware cousin of
7
7
 
8
8
  Essentially, this is the same API as
9
9
  [`lru-cache`](http://npm.im/lru-cache), but it does not do LRU tracking,
10
- and is bound primarily by time, rather than space. Since entries are not
10
+ and is bound primarily by time, rather than space. Since entries are not
11
11
  purged based on recency of use, it can save a lot of extra work managing
12
12
  linked lists, mapping keys to pointers, and so on.
13
13
 
@@ -25,7 +25,7 @@ capacity.
25
25
  A TTL _must_ be set for every entry, which can be defaulted in the
26
26
  constructor.
27
27
 
28
- Custom size calculation is not supported. Max capacity is simply the count
28
+ Custom size calculation is not supported. Max capacity is simply the count
29
29
  of items in the cache.
30
30
 
31
31
  ```js
@@ -48,7 +48,7 @@ cache.has(1) // returns false
48
48
 
49
49
  On Node.js, this module uses the `Timeout.unref()` method to
50
50
  prevent its internal `setTimeout` calls from keeping the process
51
- running indefinitely. However, on other systems such as Deno,
51
+ running indefinitely. However, on other systems such as Deno,
52
52
  where the `setTimeout` method does not return an object with an
53
53
  `unref()` method, the process will stay open as long as any
54
54
  unexpired entry exists in the cache.
@@ -67,41 +67,40 @@ Default export is the `TTLCache` class.
67
67
 
68
68
  Create a new `TTLCache` object.
69
69
 
70
- * `max` The max number of items to keep in the cache. Must be
70
+ - `max` The max number of items to keep in the cache. Must be
71
71
  positive integer or `Infinity`, defaults to `Infinity` (ie,
72
72
  limited only by TTL, not by item count).
73
- * `ttl` The max time in ms to store items. Overridable on the `set()`
74
- method. Must be a positive integer or `Infinity` (see note
75
- below about immortality hazards). If `undefined` in
73
+ - `ttl` The max time in ms to store items. Overridable on the `set()`
74
+ method. Must be a positive integer or `Infinity` (see note
75
+ below about immortality hazards). If `undefined` in
76
76
  constructor, then a TTL _must_ be provided in each `set()`
77
77
  call.
78
- * `updateAgeOnGet` Should the age of an item be updated when it is
79
- retrieved? Defaults to `false`. Overridable on the `get()` method.
80
- * `checkAgeOnGet` Check the TTL whenever an item is retrieved
78
+ - `updateAgeOnGet` Should the age of an item be updated when it is
79
+ retrieved? Defaults to `false`. Overridable on the `get()` method.
80
+ - `checkAgeOnGet` Check the TTL whenever an item is retrieved
81
81
  with `get()`. If the item is past its ttl, but the timer has
82
82
  not yet fired, then delete it and return undefined. By default,
83
83
  the cache will return a value if it has one, even if it is
84
84
  technically beyond its TTL.
85
- * `noUpdateTTL` Should setting a new value for an existing key leave the
86
- TTL unchanged? Defaults to `false`. Overridable on the `set()` method.
85
+ - `noUpdateTTL` Should setting a new value for an existing key leave the
86
+ TTL unchanged? Defaults to `false`. Overridable on the `set()` method.
87
87
  (Note that TTL is _always_ updated if the item is expired, since that is
88
88
  treated as a new `set()` and the old item is no longer relevant.)
89
- * `dispose` Method called with `(value, key, reason)` when an item is
90
- removed from the cache. Called once item is fully removed from cache.
89
+ - `dispose` Method called with `(value, key, reason)` when an item is
90
+ removed from the cache. Called once item is fully removed from cache.
91
91
  It is safe to re-add at this point, but note that adding when `reason` is
92
92
  `'set'` can result in infinite recursion if `noDisponseOnSet` is not
93
93
  specified.
94
94
 
95
- Disposal reasons:
95
+ Disposal reasons:
96
+ - `'stale'` TTL expired.
97
+ - `'set'` Overwritten with a new different value.
98
+ - `'evict'` Removed from the cache to stay within capacity limit.
99
+ - `'delete'` Explicitly deleted with `cache.delete()` or
100
+ `cache.clear()`
96
101
 
97
- * `'stale'` TTL expired.
98
- * `'set'` Overwritten with a new different value.
99
- * `'evict'` Removed from the cache to stay within capacity limit.
100
- * `'delete'` Explicitly deleted with `cache.delete()` or
101
- `cache.clear()`
102
-
103
- * `noDisposeOnSet` Do not call `dispose()` method when overwriting a key
104
- with a new value. Defaults to `false`. Overridable on `set()` method.
102
+ - `noDisposeOnSet` Do not call `dispose()` method when overwriting a key
103
+ with a new value. Defaults to `false`. Overridable on `set()` method.
105
104
 
106
105
  When used as an iterator, like `for (const [key, value] of cache)` or
107
106
  `[...cache]`, the cache yields the same results as the `entries()` method.
@@ -120,11 +119,11 @@ Returns the cache object.
120
119
 
121
120
  ### `cache.get(key, {updateAgeOnGet, checkAgeOnGet, ttl} = {})`
122
121
 
123
- Get an item stored in the cache. Returns `undefined` if the item is not in
122
+ Get an item stored in the cache. Returns `undefined` if the item is not in
124
123
  the cache (including if it has expired and been purged).
125
124
 
126
125
  If `updateAgeOnGet` is `true`, then re-add the item into the
127
- cache with the updated `ttl` value. All options default to the
126
+ cache with the updated `ttl` value. All options default to the
128
127
  settings on the constructor.
129
128
 
130
129
  If `checkAgeOnGet`, then an item will be deleted if it is found
@@ -133,14 +132,14 @@ has not yet fired to trigger its expiration.
133
132
 
134
133
  Note that using `updateAgeOnGet` _can_ effectively simulate a
135
134
  "least-recently-used" type of algorithm, by repeatedly updating
136
- the TTL of items as they are used. However, if you find yourself
135
+ the TTL of items as they are used. However, if you find yourself
137
136
  doing this, consider using
138
137
  [`lru-cache`](http://npm.im/lru-cache), as it is much more
139
138
  optimized for an LRU use case.
140
139
 
141
140
  ### `cache.getRemainingTTL(key)`
142
141
 
143
- Return the remaining time before an item expires. Returns `0` if the item
142
+ Return the remaining time before an item expires. Returns `0` if the item
144
143
  is not found in the cache or is already expired.
145
144
 
146
145
  ### `cache.has(key)`
@@ -158,7 +157,7 @@ Delete all items from the cache.
158
157
  ### `cache.entries()`
159
158
 
160
159
  Return an iterator that walks through each `[key, value]` from soonest
161
- expiring to latest expiring. (Items expiring at the same time are walked
160
+ expiring to latest expiring. (Items expiring at the same time are walked
162
161
  in insertion order.)
163
162
 
164
163
  Default iteration method for the cache object.
@@ -189,20 +188,20 @@ You should not ever call these, they are managed automatically.
189
188
 
190
189
  **Internal**
191
190
 
192
- Removes items which have expired. Called automatically.
191
+ Removes items which have expired. Called automatically.
193
192
 
194
193
  ### `purgeToCapacity`
195
194
 
196
195
  **Internal**
197
196
 
198
- Removes soonest-expiring items when the capacity limit is reached. Called
197
+ Removes soonest-expiring items when the capacity limit is reached. Called
199
198
  automatically.
200
199
 
201
200
  ### `dispose`
202
201
 
203
202
  **Internal**
204
203
 
205
- Called when an item is removed from the cache and should be disposed. Set
204
+ Called when an item is removed from the cache and should be disposed. Set
206
205
  this on the constructor options.
207
206
 
208
207
  ### `setTimer`
@@ -214,8 +213,8 @@ is setup at once. Called automatically.
214
213
 
215
214
  ## Algorithm
216
215
 
217
- The cache uses two `Map` objects. The first maps item keys to their
218
- expiration time, and the second maps item keys to their values. Then, a
216
+ The cache uses two `Map` objects. The first maps item keys to their
217
+ expiration time, and the second maps item keys to their values. Then, a
219
218
  null-prototype object uses the expiration time as keys, with the value
220
219
  being an array of all the keys expiring at that time.
221
220
 
@@ -226,7 +225,7 @@ fairly good performance:
226
225
  arbitrary keys.
227
226
  - Objects with solely integer-numeric keys are iterated in sorted numeric
228
227
  order rather than insertion order, and insertions in the middle of the
229
- key ordering are still very fast. This is true of all modern JS engines
228
+ key ordering are still very fast. This is true of all modern JS engines
230
229
  tested at the time of this module's creation, but most particularly V8
231
230
  (the engine in Node.js).
232
231
 
@@ -235,19 +234,19 @@ iteration order, deleting items until we come to the first key greater than
235
234
  the current time.
236
235
 
237
236
  Thus, the `start` time doesn't need to be tracked, only the expiration
238
- time. When an item age is updated (either explicitly on `get()`, or by
237
+ time. When an item age is updated (either explicitly on `get()`, or by
239
238
  setting to a new value), it is deleted and re-inserted.
240
239
 
241
240
  ## Immortality Hazards
242
241
 
243
242
  It is possible to set a TTL of `Infinity`, in which case an item
244
- will never expire. As it does not expire, its TTL is not
243
+ will never expire. As it does not expire, its TTL is not
245
244
  tracked, and `getRemainingTTL()` will return `Infinity` for that
246
245
  key.
247
246
 
248
- If you do this, then the item will never be purged. Create
247
+ If you do this, then the item will never be purged. Create
249
248
  enough immortal values, and the cache will grow to consume all
250
- available memory. If find yourself doing this, it's _probably_
249
+ available memory. If find yourself doing this, it's _probably_
251
250
  better to use a different data structure, such as a `Map` or
252
251
  plain old object to store values, as it will have better
253
252
  performance and the hazards will be more obvious.
@@ -0,0 +1,46 @@
1
+ export type DisposeReason = 'set' | 'delete' | 'stale' | 'evict';
2
+ export type DisposeFunction<K, V> = (val: V, key: K, reason: DisposeReason) => unknown;
3
+ export type TTLCacheOptions<K, V> = {
4
+ max?: number;
5
+ ttl?: number;
6
+ updateAgeOnGet?: boolean;
7
+ checkAgeOnGet?: boolean;
8
+ noUpdateTTL?: boolean;
9
+ dispose?: DisposeFunction<K, V>;
10
+ noDisposeOnSet?: boolean;
11
+ };
12
+ export type SetOptions<K, V> = Pick<TTLCacheOptions<K, V>, 'ttl' | 'noUpdateTTL' | 'noDisposeOnSet'>;
13
+ export type GetOptions<K, V> = Pick<TTLCacheOptions<K, V>, 'updateAgeOnGet' | 'ttl' | 'checkAgeOnGet'>;
14
+ export declare class TTLCache<K = unknown, V = unknown> {
15
+ expirations: Record<number, K[]>;
16
+ data: Map<K, V>;
17
+ expirationMap: Map<K, number>;
18
+ ttl?: number;
19
+ max: number;
20
+ updateAgeOnGet: boolean;
21
+ noUpdateTTL: boolean;
22
+ noDisposeOnSet: boolean;
23
+ checkAgeOnGet: boolean;
24
+ dispose: DisposeFunction<K, V>;
25
+ timer?: ReturnType<typeof setTimeout>;
26
+ timerExpiration?: number;
27
+ constructor({ max, ttl, updateAgeOnGet, checkAgeOnGet, noUpdateTTL, dispose, noDisposeOnSet, }?: TTLCacheOptions<K, V>);
28
+ setTimer(expiration: number, ttl: number): void;
29
+ cancelTimer(): void;
30
+ cancelTimers(): void;
31
+ clear(): void;
32
+ setTTL(key: K, ttl?: number | undefined): void;
33
+ set(key: K, val: V, { ttl, noUpdateTTL, noDisposeOnSet, }?: SetOptions<K, V>): this;
34
+ has(key: K): boolean;
35
+ getRemainingTTL(key: K): number;
36
+ get(key: K, { updateAgeOnGet, ttl, checkAgeOnGet, }?: GetOptions<K, V>): V | undefined;
37
+ delete(key: K): boolean;
38
+ purgeToCapacity(): void;
39
+ get size(): number;
40
+ purgeStale(): void;
41
+ entries(): Generator<[K, V], void, unknown>;
42
+ keys(): Generator<K, void, unknown>;
43
+ values(): Generator<V, void, unknown>;
44
+ [Symbol.iterator](): Generator<[K, V], void, unknown>;
45
+ }
46
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAoBA,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAA;AAEhE,MAAM,MAAM,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAClC,GAAG,EAAE,CAAC,EACN,GAAG,EAAE,CAAC,EACN,MAAM,EAAE,aAAa,KAClB,OAAO,CAAA;AAEZ,MAAM,MAAM,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI;IAClC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC/B,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,UAAU,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CACjC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,EACrB,KAAK,GAAG,aAAa,GAAG,gBAAgB,CACzC,CAAA;AACD,MAAM,MAAM,UAAU,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CACjC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,EACrB,gBAAgB,GAAG,KAAK,GAAG,eAAe,CAC3C,CAAA;AAED,qBAAa,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO;IAC5C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAsB;IACtD,IAAI,YAAkB;IACtB,aAAa,iBAAuB;IACpC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,cAAc,EAAE,OAAO,CAAA;IACvB,WAAW,EAAE,OAAO,CAAA;IACpB,cAAc,EAAE,OAAO,CAAA;IACvB,aAAa,EAAE,OAAO,CAAA;IACtB,OAAO,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC9B,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA;IACrC,eAAe,CAAC,EAAE,MAAM,CAAA;gBAEZ,EACV,GAAc,EACd,GAAG,EACH,cAAsB,EACtB,aAAqB,EACrB,WAAmB,EACnB,OAAO,EACP,cAAsB,GACvB,GAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAM;IA4B7B,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;IA+BxC,WAAW;IASX,YAAY;IAUZ,KAAK;IAaL,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,qBAAW;IAyB7B,GAAG,CACD,GAAG,EAAE,CAAC,EACN,GAAG,EAAE,CAAC,EACN,EACE,GAAc,EACd,WAA8B,EAC9B,cAAoC,GACrC,GAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAM;IA6B1B,GAAG,CAAC,GAAG,EAAE,CAAC;IAIV,eAAe,CAAC,GAAG,EAAE,CAAC;IAStB,GAAG,CACD,GAAG,EAAE,CAAC,EACN,EACE,cAAoC,EACpC,GAAc,EACd,aAAkC,GACnC,GAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAM;IAa1B,MAAM,CAAC,GAAG,EAAE,CAAC;IAuBb,eAAe;IA8Bf,IAAI,IAAI,WAEP;IAED,UAAU;IA4BT,OAAO;IAOP,IAAI;IAOJ,MAAM;IAOP,CAAC,MAAM,CAAC,QAAQ,CAAC;CAGlB"}
@@ -0,0 +1,290 @@
1
+ "use strict";
2
+ // A simple TTL cache with max capacity option, ms resolution,
3
+ // autopurge, and reasonably optimized performance
4
+ // Relies on the fact that integer Object keys are kept sorted,
5
+ // and managed very efficiently by V8.
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.TTLCache = void 0;
8
+ /* c8 ignore start */
9
+ const perf = typeof performance === 'object' &&
10
+ performance &&
11
+ typeof performance.now === 'function'
12
+ ? performance
13
+ : Date;
14
+ /* c8 ignore stop */
15
+ const now = () => perf.now();
16
+ const isPosInt = (n) => !!n && n === Math.floor(n) && n > 0 && isFinite(n);
17
+ const isPosIntOrInf = (n) => n === Infinity || isPosInt(n);
18
+ class TTLCache {
19
+ expirations = Object.create(null);
20
+ data = new Map();
21
+ expirationMap = new Map();
22
+ ttl;
23
+ max;
24
+ updateAgeOnGet;
25
+ noUpdateTTL;
26
+ noDisposeOnSet;
27
+ checkAgeOnGet;
28
+ dispose;
29
+ timer;
30
+ timerExpiration;
31
+ constructor({ max = Infinity, ttl, updateAgeOnGet = false, checkAgeOnGet = false, noUpdateTTL = false, dispose, noDisposeOnSet = false, } = {}) {
32
+ if (ttl !== undefined && !isPosIntOrInf(ttl)) {
33
+ throw new TypeError('ttl must be positive integer or Infinity if set');
34
+ }
35
+ if (!isPosIntOrInf(max)) {
36
+ throw new TypeError('max must be positive integer or Infinity');
37
+ }
38
+ this.ttl = ttl;
39
+ this.max = max;
40
+ this.updateAgeOnGet = !!updateAgeOnGet;
41
+ this.checkAgeOnGet = !!checkAgeOnGet;
42
+ this.noUpdateTTL = !!noUpdateTTL;
43
+ this.noDisposeOnSet = !!noDisposeOnSet;
44
+ if (dispose !== undefined) {
45
+ if (typeof dispose !== 'function') {
46
+ throw new TypeError('dispose must be function if set');
47
+ }
48
+ this.dispose = dispose;
49
+ }
50
+ else {
51
+ this.dispose = (_, __, ___) => { };
52
+ }
53
+ this.timer = undefined;
54
+ this.timerExpiration = undefined;
55
+ }
56
+ setTimer(expiration, ttl) {
57
+ if (this.timerExpiration && this.timerExpiration < expiration) {
58
+ return;
59
+ }
60
+ if (this.timer) {
61
+ clearTimeout(this.timer);
62
+ }
63
+ const t = setTimeout(() => {
64
+ this.timer = undefined;
65
+ this.timerExpiration = undefined;
66
+ this.purgeStale();
67
+ for (const exp in this.expirations) {
68
+ const e = Number(exp);
69
+ this.setTimer(e, e - now());
70
+ break;
71
+ }
72
+ }, ttl);
73
+ /* c8 ignore start - affordance for non-node envs */
74
+ if (t.unref)
75
+ t.unref();
76
+ /* c8 ignore stop */
77
+ this.timerExpiration = expiration;
78
+ this.timer = t;
79
+ }
80
+ // hang onto the timer so we can clearTimeout if all items
81
+ // are deleted. Deno doesn't have Timer.unref(), so it
82
+ // hangs otherwise.
83
+ cancelTimer() {
84
+ if (this.timer) {
85
+ clearTimeout(this.timer);
86
+ this.timerExpiration = undefined;
87
+ this.timer = undefined;
88
+ }
89
+ }
90
+ /* c8 ignore start */
91
+ cancelTimers() {
92
+ process.emitWarning('TTLCache.cancelTimers has been renamed to ' +
93
+ 'TTLCache.cancelTimer (no "s"), and will be removed in the next ' +
94
+ 'major version update');
95
+ return this.cancelTimer();
96
+ }
97
+ /* c8 ignore stop */
98
+ clear() {
99
+ const entries = this.dispose !== TTLCache.prototype.dispose ? [...this] : [];
100
+ this.data.clear();
101
+ this.expirationMap.clear();
102
+ // no need for any purging now
103
+ this.cancelTimer();
104
+ this.expirations = Object.create(null);
105
+ for (const [key, val] of entries) {
106
+ this.dispose(val, key, 'delete');
107
+ }
108
+ }
109
+ setTTL(key, ttl = this.ttl) {
110
+ const current = this.expirationMap.get(key);
111
+ if (current !== undefined) {
112
+ // remove from the expirations list, so it isn't purged
113
+ const exp = this.expirations[current];
114
+ if (!exp || exp.length <= 1) {
115
+ delete this.expirations[current];
116
+ }
117
+ else {
118
+ this.expirations[current] = exp.filter(k => k !== key);
119
+ }
120
+ }
121
+ if (ttl && ttl !== Infinity) {
122
+ const expiration = Math.floor(now() + ttl);
123
+ this.expirationMap.set(key, expiration);
124
+ if (!this.expirations[expiration]) {
125
+ this.expirations[expiration] = [];
126
+ this.setTimer(expiration, ttl);
127
+ }
128
+ this.expirations[expiration].push(key);
129
+ }
130
+ else {
131
+ this.expirationMap.set(key, Infinity);
132
+ }
133
+ }
134
+ set(key, val, { ttl = this.ttl, noUpdateTTL = this.noUpdateTTL, noDisposeOnSet = this.noDisposeOnSet, } = {}) {
135
+ if (!isPosIntOrInf(ttl)) {
136
+ throw new TypeError('ttl must be positive integer or Infinity');
137
+ }
138
+ if (this.expirationMap.has(key)) {
139
+ if (!noUpdateTTL) {
140
+ this.setTTL(key, ttl);
141
+ }
142
+ // has old value
143
+ const oldValue = this.data.get(key);
144
+ if (oldValue !== undefined && oldValue !== val) {
145
+ this.data.set(key, val);
146
+ if (!noDisposeOnSet) {
147
+ this.dispose(oldValue, key, 'set');
148
+ }
149
+ }
150
+ }
151
+ else {
152
+ this.setTTL(key, ttl);
153
+ this.data.set(key, val);
154
+ }
155
+ while (this.size > this.max) {
156
+ this.purgeToCapacity();
157
+ }
158
+ return this;
159
+ }
160
+ has(key) {
161
+ return this.data.has(key);
162
+ }
163
+ getRemainingTTL(key) {
164
+ const expiration = this.expirationMap.get(key);
165
+ return expiration === Infinity
166
+ ? expiration
167
+ : expiration !== undefined
168
+ ? Math.max(0, Math.ceil(expiration - now()))
169
+ : 0;
170
+ }
171
+ get(key, { updateAgeOnGet = this.updateAgeOnGet, ttl = this.ttl, checkAgeOnGet = this.checkAgeOnGet, } = {}) {
172
+ const val = this.data.get(key);
173
+ if (checkAgeOnGet && this.getRemainingTTL(key) === 0) {
174
+ this.delete(key);
175
+ return undefined;
176
+ }
177
+ if (updateAgeOnGet) {
178
+ this.setTTL(key, ttl);
179
+ }
180
+ return val;
181
+ }
182
+ delete(key) {
183
+ const current = this.expirationMap.get(key);
184
+ if (current !== undefined) {
185
+ const value = this.data.get(key);
186
+ this.data.delete(key);
187
+ this.expirationMap.delete(key);
188
+ const exp = this.expirations[current];
189
+ if (exp) {
190
+ if (exp.length <= 1) {
191
+ delete this.expirations[current];
192
+ }
193
+ else {
194
+ this.expirations[current] = exp.filter(k => k !== key);
195
+ }
196
+ }
197
+ this.dispose(value, key, 'delete');
198
+ if (this.size === 0) {
199
+ this.cancelTimer();
200
+ }
201
+ return true;
202
+ }
203
+ return false;
204
+ }
205
+ purgeToCapacity() {
206
+ for (const exp in this.expirations) {
207
+ const keys = this.expirations[exp];
208
+ if (this.size - keys.length >= this.max) {
209
+ delete this.expirations[exp];
210
+ const entries = [];
211
+ for (const key of keys) {
212
+ entries.push([key, this.data.get(key)]);
213
+ this.data.delete(key);
214
+ this.expirationMap.delete(key);
215
+ }
216
+ for (const [key, val] of entries) {
217
+ this.dispose(val, key, 'evict');
218
+ }
219
+ }
220
+ else {
221
+ const s = this.size - this.max;
222
+ const entries = [];
223
+ for (const key of keys.splice(0, s)) {
224
+ entries.push([key, this.data.get(key)]);
225
+ this.data.delete(key);
226
+ this.expirationMap.delete(key);
227
+ }
228
+ for (const [key, val] of entries) {
229
+ this.dispose(val, key, 'evict');
230
+ }
231
+ return;
232
+ }
233
+ }
234
+ }
235
+ get size() {
236
+ return this.data.size;
237
+ }
238
+ purgeStale() {
239
+ const n = Math.ceil(now());
240
+ for (const exp in this.expirations) {
241
+ if (exp === 'Infinity' || Number(exp) > n) {
242
+ return;
243
+ }
244
+ /* c8 ignore start
245
+ * mysterious need for a guard here?
246
+ * https://github.com/isaacs/ttlcache/issues/26 */
247
+ const keys = [...(this.expirations[exp] || [])];
248
+ /* c8 ignore stop */
249
+ const entries = [];
250
+ delete this.expirations[exp];
251
+ for (const key of keys) {
252
+ entries.push([key, this.data.get(key)]);
253
+ this.data.delete(key);
254
+ this.expirationMap.delete(key);
255
+ }
256
+ for (const [key, val] of entries) {
257
+ this.dispose(val, key, 'stale');
258
+ }
259
+ }
260
+ if (this.size === 0) {
261
+ this.cancelTimer();
262
+ }
263
+ }
264
+ *entries() {
265
+ for (const exp in this.expirations) {
266
+ for (const key of this.expirations[exp]) {
267
+ yield [key, this.data.get(key)];
268
+ }
269
+ }
270
+ }
271
+ *keys() {
272
+ for (const exp in this.expirations) {
273
+ for (const key of this.expirations[exp]) {
274
+ yield key;
275
+ }
276
+ }
277
+ }
278
+ *values() {
279
+ for (const exp in this.expirations) {
280
+ for (const key of this.expirations[exp]) {
281
+ yield this.data.get(key);
282
+ }
283
+ }
284
+ }
285
+ [Symbol.iterator]() {
286
+ return this.entries();
287
+ }
288
+ }
289
+ exports.TTLCache = TTLCache;
290
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["// A simple TTL cache with max capacity option, ms resolution,\n// autopurge, and reasonably optimized performance\n// Relies on the fact that integer Object keys are kept sorted,\n// and managed very efficiently by V8.\n\n/* c8 ignore start */\nconst perf =\n typeof performance === 'object' &&\n performance &&\n typeof performance.now === 'function'\n ? performance\n : Date\n/* c8 ignore stop */\n\nconst now = () => perf.now()\nconst isPosInt = (n: any): n is number =>\n !!n && n === Math.floor(n) && n > 0 && isFinite(n)\nconst isPosIntOrInf = (n: any): n is number =>\n n === Infinity || isPosInt(n)\n\nexport type DisposeReason = 'set' | 'delete' | 'stale' | 'evict'\n\nexport type DisposeFunction<K, V> = (\n val: V,\n key: K,\n reason: DisposeReason,\n) => unknown\n\nexport type TTLCacheOptions<K, V> = {\n max?: number\n ttl?: number\n updateAgeOnGet?: boolean\n checkAgeOnGet?: boolean\n noUpdateTTL?: boolean\n dispose?: DisposeFunction<K, V>\n noDisposeOnSet?: boolean\n}\n\nexport type SetOptions<K, V> = Pick<\n TTLCacheOptions<K, V>,\n 'ttl' | 'noUpdateTTL' | 'noDisposeOnSet'\n>\nexport type GetOptions<K, V> = Pick<\n TTLCacheOptions<K, V>,\n 'updateAgeOnGet' | 'ttl' | 'checkAgeOnGet'\n>\n\nexport class TTLCache<K = unknown, V = unknown> {\n expirations: Record<number, K[]> = Object.create(null)\n data = new Map<K, V>()\n expirationMap = new Map<K, number>()\n ttl?: number\n max: number\n updateAgeOnGet: boolean\n noUpdateTTL: boolean\n noDisposeOnSet: boolean\n checkAgeOnGet: boolean\n dispose: DisposeFunction<K, V>\n timer?: ReturnType<typeof setTimeout>\n timerExpiration?: number\n\n constructor({\n max = Infinity,\n ttl,\n updateAgeOnGet = false,\n checkAgeOnGet = false,\n noUpdateTTL = false,\n dispose,\n noDisposeOnSet = false,\n }: TTLCacheOptions<K, V> = {}) {\n if (ttl !== undefined && !isPosIntOrInf(ttl)) {\n throw new TypeError(\n 'ttl must be positive integer or Infinity if set',\n )\n }\n if (!isPosIntOrInf(max)) {\n throw new TypeError('max must be positive integer or Infinity')\n }\n this.ttl = ttl\n this.max = max\n this.updateAgeOnGet = !!updateAgeOnGet\n this.checkAgeOnGet = !!checkAgeOnGet\n this.noUpdateTTL = !!noUpdateTTL\n this.noDisposeOnSet = !!noDisposeOnSet\n if (dispose !== undefined) {\n if (typeof dispose !== 'function') {\n throw new TypeError('dispose must be function if set')\n }\n this.dispose = dispose\n } else {\n this.dispose = (_, __, ___) => {}\n }\n\n this.timer = undefined\n this.timerExpiration = undefined\n }\n\n setTimer(expiration: number, ttl: number) {\n if (this.timerExpiration && this.timerExpiration < expiration) {\n return\n }\n\n if (this.timer) {\n clearTimeout(this.timer)\n }\n\n const t = setTimeout(() => {\n this.timer = undefined\n this.timerExpiration = undefined\n this.purgeStale()\n for (const exp in this.expirations) {\n const e = Number(exp)\n this.setTimer(e, e - now())\n break\n }\n }, ttl)\n\n /* c8 ignore start - affordance for non-node envs */\n if (t.unref) t.unref()\n /* c8 ignore stop */\n\n this.timerExpiration = expiration\n this.timer = t\n }\n\n // hang onto the timer so we can clearTimeout if all items\n // are deleted. Deno doesn't have Timer.unref(), so it\n // hangs otherwise.\n cancelTimer() {\n if (this.timer) {\n clearTimeout(this.timer)\n this.timerExpiration = undefined\n this.timer = undefined\n }\n }\n\n /* c8 ignore start */\n cancelTimers() {\n process.emitWarning(\n 'TTLCache.cancelTimers has been renamed to ' +\n 'TTLCache.cancelTimer (no \"s\"), and will be removed in the next ' +\n 'major version update',\n )\n return this.cancelTimer()\n }\n /* c8 ignore stop */\n\n clear() {\n const entries =\n this.dispose !== TTLCache.prototype.dispose ? [...this] : []\n this.data.clear()\n this.expirationMap.clear()\n // no need for any purging now\n this.cancelTimer()\n this.expirations = Object.create(null)\n for (const [key, val] of entries as [K, V][]) {\n this.dispose(val, key, 'delete')\n }\n }\n\n setTTL(key: K, ttl = this.ttl) {\n const current = this.expirationMap.get(key)\n if (current !== undefined) {\n // remove from the expirations list, so it isn't purged\n const exp = this.expirations[current]\n if (!exp || exp.length <= 1) {\n delete this.expirations[current]\n } else {\n this.expirations[current] = exp.filter(k => k !== key)\n }\n }\n\n if (ttl && ttl !== Infinity) {\n const expiration = Math.floor(now() + ttl)\n this.expirationMap.set(key, expiration)\n if (!this.expirations[expiration]) {\n this.expirations[expiration] = []\n this.setTimer(expiration, ttl)\n }\n this.expirations[expiration].push(key)\n } else {\n this.expirationMap.set(key, Infinity)\n }\n }\n\n set(\n key: K,\n val: V,\n {\n ttl = this.ttl,\n noUpdateTTL = this.noUpdateTTL,\n noDisposeOnSet = this.noDisposeOnSet,\n }: SetOptions<K, V> = {},\n ) {\n if (!isPosIntOrInf(ttl)) {\n throw new TypeError('ttl must be positive integer or Infinity')\n }\n if (this.expirationMap.has(key)) {\n if (!noUpdateTTL) {\n this.setTTL(key, ttl)\n }\n // has old value\n const oldValue = this.data.get(key)\n if (oldValue !== undefined && oldValue !== val) {\n this.data.set(key, val)\n if (!noDisposeOnSet) {\n this.dispose(oldValue, key, 'set')\n }\n }\n } else {\n this.setTTL(key, ttl)\n this.data.set(key, val)\n }\n\n while (this.size > this.max) {\n this.purgeToCapacity()\n }\n\n return this\n }\n\n has(key: K) {\n return this.data.has(key)\n }\n\n getRemainingTTL(key: K) {\n const expiration = this.expirationMap.get(key)\n return expiration === Infinity\n ? expiration\n : expiration !== undefined\n ? Math.max(0, Math.ceil(expiration - now()))\n : 0\n }\n\n get(\n key: K,\n {\n updateAgeOnGet = this.updateAgeOnGet,\n ttl = this.ttl,\n checkAgeOnGet = this.checkAgeOnGet,\n }: GetOptions<K, V> = {},\n ) {\n const val = this.data.get(key)\n if (checkAgeOnGet && this.getRemainingTTL(key) === 0) {\n this.delete(key)\n return undefined\n }\n if (updateAgeOnGet) {\n this.setTTL(key, ttl)\n }\n return val\n }\n\n delete(key: K) {\n const current = this.expirationMap.get(key)\n if (current !== undefined) {\n const value = this.data.get(key) as V\n this.data.delete(key)\n this.expirationMap.delete(key)\n const exp = this.expirations[current]\n if (exp) {\n if (exp.length <= 1) {\n delete this.expirations[current]\n } else {\n this.expirations[current] = exp.filter(k => k !== key)\n }\n }\n this.dispose(value, key, 'delete')\n if (this.size === 0) {\n this.cancelTimer()\n }\n return true\n }\n return false\n }\n\n purgeToCapacity() {\n for (const exp in this.expirations) {\n const keys = this.expirations[exp] as K[]\n if (this.size - keys.length >= this.max) {\n delete this.expirations[exp]\n const entries: [K, V][] = []\n for (const key of keys) {\n entries.push([key, this.data.get(key) as V])\n this.data.delete(key)\n this.expirationMap.delete(key)\n }\n for (const [key, val] of entries) {\n this.dispose(val, key, 'evict')\n }\n } else {\n const s = this.size - this.max\n const entries: [K, V][] = []\n for (const key of keys.splice(0, s)) {\n entries.push([key, this.data.get(key) as V])\n this.data.delete(key)\n this.expirationMap.delete(key)\n }\n for (const [key, val] of entries) {\n this.dispose(val, key, 'evict')\n }\n return\n }\n }\n }\n\n get size() {\n return this.data.size\n }\n\n purgeStale() {\n const n = Math.ceil(now())\n for (const exp in this.expirations) {\n if (exp === 'Infinity' || Number(exp) > n) {\n return\n }\n\n /* c8 ignore start\n * mysterious need for a guard here?\n * https://github.com/isaacs/ttlcache/issues/26 */\n const keys = [...(this.expirations[exp] || [])]\n /* c8 ignore stop */\n const entries: [K, V][] = []\n delete this.expirations[exp]\n for (const key of keys) {\n entries.push([key, this.data.get(key) as V])\n this.data.delete(key)\n this.expirationMap.delete(key)\n }\n for (const [key, val] of entries) {\n this.dispose(val, key, 'stale')\n }\n }\n if (this.size === 0) {\n this.cancelTimer()\n }\n }\n\n *entries() {\n for (const exp in this.expirations) {\n for (const key of this.expirations[exp] as K[]) {\n yield [key, this.data.get(key)] as [K, V]\n }\n }\n }\n *keys() {\n for (const exp in this.expirations) {\n for (const key of this.expirations[exp] as K[]) {\n yield key\n }\n }\n }\n *values() {\n for (const exp in this.expirations) {\n for (const key of this.expirations[exp] as K[]) {\n yield this.data.get(key) as V\n }\n }\n }\n [Symbol.iterator]() {\n return this.entries()\n }\n}\n"]}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }