@nxtedition/cache 1.0.7 → 1.0.10
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/README.md +26 -12
- package/lib/index.d.ts +7 -12
- package/lib/index.js +78 -49
- package/lib/memory.d.ts +21 -0
- package/lib/memory.js +103 -0
- package/package.json +6 -9
package/README.md
CHANGED
|
@@ -54,21 +54,35 @@ if (result.async) {
|
|
|
54
54
|
|
|
55
55
|
#### Options
|
|
56
56
|
|
|
57
|
-
| Option
|
|
58
|
-
|
|
|
59
|
-
| `ttl`
|
|
60
|
-
| `stale`
|
|
61
|
-
| `
|
|
62
|
-
| `
|
|
57
|
+
| Option | Type | Default | Description |
|
|
58
|
+
| ---------- | ---------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------- |
|
|
59
|
+
| `ttl` | `number \| (value, key) => number` | `MAX_SAFE_INTEGER` | Time-to-live in milliseconds. After this, the entry is stale. |
|
|
60
|
+
| `stale` | `number \| (value, key) => number` | `MAX_SAFE_INTEGER` | Stale-while-revalidate window in milliseconds. After `ttl + stale`, the entry is purged. |
|
|
61
|
+
| `memory` | `MemoryOptions \| false \| null` | `{ maxSize: 16MB, maxCount: 16384 }` | In-memory cache options, or `false`/`null` to disable in-memory caching. |
|
|
62
|
+
| `database` | `DatabaseOptions \| false \| null` | `{ timeout: 20, maxSize: 256MB }` | SQLite options, or `false`/`null` to disable persistence. |
|
|
63
|
+
|
|
64
|
+
#### `MemoryOptions`
|
|
65
|
+
|
|
66
|
+
| Option | Type | Default | Description |
|
|
67
|
+
| ---------- | -------- | -------------------------- | ---------------------------------------------- |
|
|
68
|
+
| `maxSize` | `number` | `16 * 1024 * 1024` (16 MB) | Maximum total size in bytes of cached entries. |
|
|
69
|
+
| `maxCount` | `number` | `16 * 1024` (16384) | Maximum number of entries in memory. |
|
|
70
|
+
|
|
71
|
+
#### `DatabaseOptions`
|
|
72
|
+
|
|
73
|
+
| Option | Type | Default | Description |
|
|
74
|
+
| --------- | -------- | ---------------------------- | ----------------------------------------------------------------- |
|
|
75
|
+
| `timeout` | `number` | `20` | SQLite busy timeout in milliseconds. |
|
|
76
|
+
| `maxSize` | `number` | `256 * 1024 * 1024` (256 MB) | Maximum database file size. Oldest entries are evicted when full. |
|
|
63
77
|
|
|
64
78
|
### `CacheResult<V>`
|
|
65
79
|
|
|
66
80
|
Both `get()` and `peek()` return a `CacheResult<V>`, a discriminated union on the `async` property:
|
|
67
81
|
|
|
68
|
-
| `async` | `value`
|
|
69
|
-
| ------- |
|
|
70
|
-
| `false` | `V`
|
|
71
|
-
| `true` | `Promise<V
|
|
82
|
+
| `async` | `value` | Meaning |
|
|
83
|
+
| ------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
84
|
+
| `false` | `V \| undefined` | Cache hit — the value is available synchronously. Also returned for stale entries (a background refresh is triggered automatically). `undefined` when `peek()` has no cached entry. |
|
|
85
|
+
| `true` | `Promise<V>` | Cache miss — `value` is a `Promise` that resolves when the `valueSelector` completes. |
|
|
72
86
|
|
|
73
87
|
```ts
|
|
74
88
|
const result = cache.get('key')
|
|
@@ -90,7 +104,7 @@ Returns a cached value or triggers a fetch on cache miss.
|
|
|
90
104
|
|
|
91
105
|
#### `cache.peek(...args): CacheResult<V>`
|
|
92
106
|
|
|
93
|
-
Same as `get()` but does **not** trigger a refresh on cache miss. Returns `{ value: undefined, async:
|
|
107
|
+
Same as `get()` but does **not** trigger a refresh on cache miss. Returns `{ value: undefined, async: false }` for missing entries.
|
|
94
108
|
|
|
95
109
|
#### `cache.refresh(...args): Promise<V>`
|
|
96
110
|
|
|
@@ -102,7 +116,7 @@ Remove an entry from the cache. The cache key is derived from `args` via the `ke
|
|
|
102
116
|
|
|
103
117
|
#### `cache.purgeStale(): void`
|
|
104
118
|
|
|
105
|
-
Remove all expired entries from both the
|
|
119
|
+
Remove all expired entries from both the in-memory cache and SQLite.
|
|
106
120
|
|
|
107
121
|
#### `cache.close(): void`
|
|
108
122
|
|
package/lib/index.d.ts
CHANGED
|
@@ -1,24 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
stale: number;
|
|
5
|
-
value: V;
|
|
6
|
-
}
|
|
7
|
-
export interface AsyncCacheDbOptions {
|
|
1
|
+
import { type MemoryOptions } from './memory.ts';
|
|
2
|
+
export type { MemoryOptions } from './memory.ts';
|
|
3
|
+
export interface DatabaseOptions {
|
|
8
4
|
timeout?: number;
|
|
9
5
|
maxSize?: number;
|
|
10
6
|
}
|
|
11
7
|
export interface AsyncCacheOptions<V> {
|
|
12
8
|
ttl?: number | ((value: V, key: string) => number);
|
|
13
9
|
stale?: number | ((value: V, key: string) => number);
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
memory?: MemoryOptions | false | null;
|
|
11
|
+
database?: DatabaseOptions | false | null;
|
|
16
12
|
}
|
|
17
13
|
export type CacheResult<V> = {
|
|
18
|
-
value: V;
|
|
14
|
+
value: V | undefined;
|
|
19
15
|
async: false;
|
|
20
16
|
} | {
|
|
21
|
-
value: Promise<V
|
|
17
|
+
value: Promise<V>;
|
|
22
18
|
async: true;
|
|
23
19
|
};
|
|
24
20
|
export declare class AsyncCache<V = unknown, A extends unknown[] = unknown[]> {
|
|
@@ -31,4 +27,3 @@ export declare class AsyncCache<V = unknown, A extends unknown[] = unknown[]> {
|
|
|
31
27
|
delete(...args: A): void;
|
|
32
28
|
purgeStale(): void;
|
|
33
29
|
}
|
|
34
|
-
export {};
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { DatabaseSync, } from 'node:sqlite'
|
|
2
|
-
import {
|
|
2
|
+
import { MemoryCache, } from "./memory.js"
|
|
3
|
+
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
let fastNowTime = 0
|
|
5
7
|
|
|
@@ -37,13 +39,13 @@ const dbs = new Set ()
|
|
|
37
39
|
|
|
38
40
|
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
|
|
41
43
|
|
|
42
44
|
|
|
43
45
|
|
|
44
46
|
|
|
45
47
|
|
|
46
|
-
|
|
48
|
+
|
|
47
49
|
|
|
48
50
|
|
|
49
51
|
|
|
@@ -51,27 +53,28 @@ const dbs = new Set ()
|
|
|
51
53
|
|
|
52
54
|
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
|
|
57
|
+
|
|
56
58
|
|
|
57
59
|
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
|
|
62
|
+
|
|
61
63
|
|
|
62
64
|
const VERSION = 2
|
|
63
65
|
const MAX_DURATION = 365000000e3
|
|
64
66
|
|
|
65
67
|
export class AsyncCache {
|
|
66
|
-
#
|
|
68
|
+
#memory
|
|
69
|
+
#dedupe = new Map ()
|
|
70
|
+
|
|
67
71
|
#valueSelector
|
|
68
72
|
#keySelector
|
|
69
|
-
#dedupe = new Map ()
|
|
70
73
|
|
|
71
74
|
#ttl
|
|
72
75
|
#stale
|
|
73
76
|
|
|
74
|
-
#
|
|
77
|
+
#database = null
|
|
75
78
|
#getQuery = null
|
|
76
79
|
#setQuery = null
|
|
77
80
|
#delQuery = null
|
|
@@ -116,15 +119,17 @@ export class AsyncCache {
|
|
|
116
119
|
throw new TypeError('stale must be a undefined, number or a function')
|
|
117
120
|
}
|
|
118
121
|
|
|
119
|
-
this.#
|
|
120
|
-
opts?.
|
|
122
|
+
this.#memory =
|
|
123
|
+
opts?.memory === false || opts?.memory === null ? null : new MemoryCache(opts?.memory)
|
|
121
124
|
|
|
122
|
-
for (let n = 0; opts?.
|
|
125
|
+
for (let n = 0; opts?.database !== null && opts?.database !== false; n++) {
|
|
123
126
|
try {
|
|
124
|
-
const
|
|
125
|
-
|
|
127
|
+
const maxSize = opts?.database?.maxSize ?? 256 * 1024 * 1024
|
|
128
|
+
const timeout = opts?.database?.timeout ?? 20
|
|
129
|
+
|
|
130
|
+
this.#database ??= new DatabaseSync(location, { timeout })
|
|
126
131
|
|
|
127
|
-
this.#
|
|
132
|
+
this.#database.exec(`
|
|
128
133
|
PRAGMA journal_mode = WAL;
|
|
129
134
|
PRAGMA synchronous = NORMAL;
|
|
130
135
|
PRAGMA temp_store = memory;
|
|
@@ -139,26 +144,30 @@ export class AsyncCache {
|
|
|
139
144
|
`)
|
|
140
145
|
|
|
141
146
|
{
|
|
142
|
-
const { page_size } = this.#
|
|
143
|
-
|
|
147
|
+
const { page_size } = this.#database.prepare('PRAGMA page_size').get()
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
this.#database.exec(`PRAGMA max_page_count = ${Math.ceil(maxSize / page_size)}`)
|
|
144
151
|
}
|
|
145
152
|
|
|
146
|
-
this.#getQuery = this.#
|
|
153
|
+
this.#getQuery = this.#database.prepare(
|
|
147
154
|
`SELECT val, ttl, stale FROM cache_v${VERSION} WHERE key = ? AND stale > ?`,
|
|
148
155
|
)
|
|
149
|
-
this.#setQuery = this.#
|
|
156
|
+
this.#setQuery = this.#database.prepare(
|
|
150
157
|
`INSERT OR REPLACE INTO cache_v${VERSION} (key, val, ttl, stale) VALUES (?, ?, ?, ?)`,
|
|
151
158
|
)
|
|
152
|
-
this.#delQuery = this.#
|
|
153
|
-
this.#purgeStaleQuery = this.#
|
|
154
|
-
|
|
159
|
+
this.#delQuery = this.#database.prepare(`DELETE FROM cache_v${VERSION} WHERE key = ?`)
|
|
160
|
+
this.#purgeStaleQuery = this.#database.prepare(
|
|
161
|
+
`DELETE FROM cache_v${VERSION} WHERE stale <= ?`,
|
|
162
|
+
)
|
|
163
|
+
this.#evictQuery = this.#database.prepare(
|
|
155
164
|
`DELETE FROM cache_v${VERSION} WHERE key IN (SELECT key FROM cache_v${VERSION} ORDER BY stale ASC LIMIT ?)`,
|
|
156
165
|
)
|
|
157
166
|
break
|
|
158
167
|
} catch (err) {
|
|
159
|
-
if (n >=
|
|
160
|
-
this.#
|
|
161
|
-
this.#
|
|
168
|
+
if (n >= 16) {
|
|
169
|
+
this.#database?.close()
|
|
170
|
+
this.#database = null
|
|
162
171
|
|
|
163
172
|
this.#getQuery = null
|
|
164
173
|
this.#setQuery = null
|
|
@@ -180,8 +189,8 @@ export class AsyncCache {
|
|
|
180
189
|
this.#delQuery = null
|
|
181
190
|
this.#purgeStaleQuery = null
|
|
182
191
|
this.#evictQuery = null
|
|
183
|
-
this.#
|
|
184
|
-
this.#
|
|
192
|
+
this.#database?.close()
|
|
193
|
+
this.#database = null
|
|
185
194
|
}
|
|
186
195
|
|
|
187
196
|
get(...args ) {
|
|
@@ -197,12 +206,12 @@ export class AsyncCache {
|
|
|
197
206
|
}
|
|
198
207
|
|
|
199
208
|
delete(...args ) {
|
|
200
|
-
this.#delete(args)
|
|
209
|
+
this.#delete(this.#keySelector(...args))
|
|
201
210
|
}
|
|
202
211
|
|
|
203
212
|
purgeStale() {
|
|
204
213
|
try {
|
|
205
|
-
this.#
|
|
214
|
+
this.#memory?.purgeStale(fastNow())
|
|
206
215
|
this.#purgeStaleQuery?.run(fastNow())
|
|
207
216
|
} catch {}
|
|
208
217
|
}
|
|
@@ -216,13 +225,13 @@ export class AsyncCache {
|
|
|
216
225
|
|
|
217
226
|
const now = fastNow()
|
|
218
227
|
|
|
219
|
-
let cached = this.#
|
|
228
|
+
let cached = this.#memory?.get(key)
|
|
220
229
|
|
|
221
230
|
if (cached === undefined) {
|
|
222
231
|
try {
|
|
223
|
-
const row = this.#getQuery?.get(key, now)
|
|
232
|
+
const row = this.#getQuery?.get(key, now)
|
|
224
233
|
if (row !== undefined) {
|
|
225
|
-
|
|
234
|
+
const entry = {
|
|
226
235
|
ttl: row.ttl,
|
|
227
236
|
stale: row.stale,
|
|
228
237
|
value: ArrayBuffer.isView(row.val)
|
|
@@ -232,11 +241,15 @@ export class AsyncCache {
|
|
|
232
241
|
row.val.byteLength,
|
|
233
242
|
) )
|
|
234
243
|
: JSON.parse(row.val),
|
|
244
|
+
key,
|
|
245
|
+
size:
|
|
246
|
+
(ArrayBuffer.isView(row.val) ? row.val.byteLength : row.val.length) + key.length + 64,
|
|
247
|
+
index: -1,
|
|
248
|
+
counter: -1,
|
|
235
249
|
}
|
|
236
|
-
|
|
250
|
+
this.#memory?.set(key, entry)
|
|
237
251
|
|
|
238
|
-
|
|
239
|
-
this.#lru?.set(key, cached)
|
|
252
|
+
cached = entry
|
|
240
253
|
}
|
|
241
254
|
} catch (err) {
|
|
242
255
|
process.emitWarning(err )
|
|
@@ -250,7 +263,7 @@ export class AsyncCache {
|
|
|
250
263
|
|
|
251
264
|
if (now > cached.stale) {
|
|
252
265
|
// stale-while-revalidate has expired, purge cached value.
|
|
253
|
-
this.#
|
|
266
|
+
this.#memory?.delete(key)
|
|
254
267
|
try {
|
|
255
268
|
this.#delQuery?.run(key)
|
|
256
269
|
} catch {
|
|
@@ -263,9 +276,15 @@ export class AsyncCache {
|
|
|
263
276
|
|
|
264
277
|
const promise = refresh ? this.#refresh(args, key) : undefined
|
|
265
278
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
279
|
+
if (cached !== undefined) {
|
|
280
|
+
return { value: cached.value, async: false }
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (promise !== undefined) {
|
|
284
|
+
return { value: promise, async: true }
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return { value: undefined, async: false }
|
|
269
288
|
}
|
|
270
289
|
|
|
271
290
|
#refresh(args , key = this.#keySelector(...args)) {
|
|
@@ -284,7 +303,11 @@ export class AsyncCache {
|
|
|
284
303
|
(value) => {
|
|
285
304
|
if (this.#dedupe.get(key) === promise) {
|
|
286
305
|
this.#dedupe.delete(key)
|
|
287
|
-
|
|
306
|
+
if (value === undefined) {
|
|
307
|
+
this.#delete(key)
|
|
308
|
+
} else {
|
|
309
|
+
this.#set(key, value)
|
|
310
|
+
}
|
|
288
311
|
}
|
|
289
312
|
return value
|
|
290
313
|
},
|
|
@@ -324,16 +347,22 @@ export class AsyncCache {
|
|
|
324
347
|
return
|
|
325
348
|
}
|
|
326
349
|
|
|
327
|
-
const storedValue = ArrayBuffer.isView(value)
|
|
328
|
-
? (Buffer.from(value.buffer, value.byteOffset, value.byteLength) )
|
|
329
|
-
: value
|
|
330
|
-
|
|
331
|
-
this.#lru?.set(key, { ttl, stale, value: storedValue })
|
|
332
|
-
|
|
333
350
|
const data = ArrayBuffer.isView(value)
|
|
334
351
|
? value
|
|
335
352
|
: JSON.stringify(value )
|
|
336
353
|
|
|
354
|
+
this.#memory?.set(key, {
|
|
355
|
+
ttl,
|
|
356
|
+
stale,
|
|
357
|
+
value: ArrayBuffer.isView(value)
|
|
358
|
+
? (Buffer.from(value.buffer, value.byteOffset, value.byteLength) )
|
|
359
|
+
: value,
|
|
360
|
+
key,
|
|
361
|
+
size: (ArrayBuffer.isView(data) ? data.byteLength : data.length) + key.length + 64,
|
|
362
|
+
index: -1,
|
|
363
|
+
counter: -1,
|
|
364
|
+
})
|
|
365
|
+
|
|
337
366
|
try {
|
|
338
367
|
this.#setQuery?.run(key, data , ttl, stale)
|
|
339
368
|
} catch (err) {
|
|
@@ -350,13 +379,13 @@ export class AsyncCache {
|
|
|
350
379
|
}
|
|
351
380
|
}
|
|
352
381
|
|
|
353
|
-
#delete(
|
|
382
|
+
#delete(key ) {
|
|
354
383
|
if (typeof key !== 'string' || key.length === 0) {
|
|
355
384
|
throw new TypeError('key must be a non-empty string')
|
|
356
385
|
}
|
|
357
386
|
|
|
358
387
|
this.#dedupe.delete(key)
|
|
359
|
-
this.#
|
|
388
|
+
this.#memory?.delete(key)
|
|
360
389
|
try {
|
|
361
390
|
this.#delQuery?.run(key)
|
|
362
391
|
} catch (err) {
|
package/lib/memory.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface MemoryOptions {
|
|
2
|
+
maxSize?: number;
|
|
3
|
+
maxCount?: number;
|
|
4
|
+
}
|
|
5
|
+
export interface MemoryCacheEntry<V> {
|
|
6
|
+
ttl: number;
|
|
7
|
+
stale: number;
|
|
8
|
+
value: V;
|
|
9
|
+
key: string;
|
|
10
|
+
index: number;
|
|
11
|
+
size: number;
|
|
12
|
+
counter: number;
|
|
13
|
+
}
|
|
14
|
+
export declare class MemoryCache<V> {
|
|
15
|
+
#private;
|
|
16
|
+
constructor(opts?: MemoryOptions);
|
|
17
|
+
set(key: string, entry: MemoryCacheEntry<V>): void;
|
|
18
|
+
get(key: string): MemoryCacheEntry<V> | undefined;
|
|
19
|
+
delete(key: string): void;
|
|
20
|
+
purgeStale(now: number): void;
|
|
21
|
+
}
|
package/lib/memory.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export class MemoryCache {
|
|
17
|
+
#map = new Map()
|
|
18
|
+
#arr = []
|
|
19
|
+
|
|
20
|
+
#maxSize
|
|
21
|
+
#maxCount
|
|
22
|
+
|
|
23
|
+
#size = 0
|
|
24
|
+
#count = 0
|
|
25
|
+
|
|
26
|
+
#counter = 0
|
|
27
|
+
|
|
28
|
+
constructor(opts ) {
|
|
29
|
+
if (opts?.maxSize != null && (!Number.isInteger(opts.maxSize) || opts.maxSize < 1)) {
|
|
30
|
+
throw new Error('maxSize must be a positive integer')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (opts?.maxCount != null && (!Number.isInteger(opts.maxCount) || opts.maxCount < 1)) {
|
|
34
|
+
throw new Error('maxCount must be a positive integer')
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
this.#maxSize = opts?.maxSize ?? 16 * 1024 * 1024
|
|
38
|
+
this.#maxCount = opts?.maxCount ?? 16 * 1024
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
set(key , entry ) {
|
|
42
|
+
const existing = this.#map.get(key)
|
|
43
|
+
if (existing != null) {
|
|
44
|
+
this.#delete(existing)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
this.#map.set(key, entry)
|
|
48
|
+
entry.key = key
|
|
49
|
+
entry.index = this.#arr.push(entry) - 1
|
|
50
|
+
entry.counter = this.#counter++
|
|
51
|
+
|
|
52
|
+
this.#size += entry.size ?? 0
|
|
53
|
+
this.#count += 1
|
|
54
|
+
|
|
55
|
+
this.#prune()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get(key ) {
|
|
59
|
+
const entry = this.#map.get(key)
|
|
60
|
+
if (entry != null) {
|
|
61
|
+
entry.counter = this.#counter++
|
|
62
|
+
}
|
|
63
|
+
return entry
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
delete(key ) {
|
|
67
|
+
const entry = this.#map.get(key)
|
|
68
|
+
if (entry != null) {
|
|
69
|
+
this.#delete(entry)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
#delete(entry ) {
|
|
74
|
+
this.#map.delete(entry.key)
|
|
75
|
+
|
|
76
|
+
this.#size -= entry.size
|
|
77
|
+
this.#count -= 1
|
|
78
|
+
|
|
79
|
+
const tmp = this.#arr.pop()
|
|
80
|
+
if (tmp !== entry) {
|
|
81
|
+
this.#arr[entry.index] = tmp
|
|
82
|
+
this.#arr[entry.index].index = entry.index
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
purgeStale(now ) {
|
|
87
|
+
for (let i = this.#arr.length - 1; i >= 0; i--) {
|
|
88
|
+
const entry = this.#arr[i]
|
|
89
|
+
if (now > entry.stale) {
|
|
90
|
+
this.#delete(entry)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
#prune() {
|
|
96
|
+
while (this.#size > this.#maxSize || this.#count > this.#maxCount) {
|
|
97
|
+
const e1 = this.#arr[(Math.random() * this.#arr.length) | 0]
|
|
98
|
+
const e2 = this.#arr[(Math.random() * this.#arr.length) | 0]
|
|
99
|
+
const e = e2.counter > e1.counter ? e1 : e2
|
|
100
|
+
this.#delete(e)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxtedition/cache",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
"access": "public"
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
|
-
"build": "rimraf lib && tsc && amaroc ./src/index.ts && mv src/index.js lib/",
|
|
17
|
+
"build": "rimraf lib && tsc && amaroc ./src/index.ts && mv src/index.js lib/ && amaroc ./src/memory.ts && mv src/memory.js lib/",
|
|
18
18
|
"prepublishOnly": "yarn build",
|
|
19
19
|
"typecheck": "tsc --noEmit",
|
|
20
|
-
"test": "node --test",
|
|
21
|
-
"test:ci": "node --test",
|
|
22
|
-
"test:coverage": "node --test --experimental-test-coverage --test-coverage-include=src/index.ts --test-coverage-lines=90 --test-coverage-branches=90 --test-coverage-functions=100"
|
|
20
|
+
"test": "node --test && yarn build",
|
|
21
|
+
"test:ci": "node --test && yarn build",
|
|
22
|
+
"test:coverage": "node --test --experimental-test-coverage --test-coverage-include=src/index.ts --test-coverage-include=src/memory.ts --test-coverage-lines=90 --test-coverage-branches=90 --test-coverage-functions=100"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@types/node": "^25.2.3",
|
|
@@ -28,8 +28,5 @@
|
|
|
28
28
|
"rimraf": "^6.1.2",
|
|
29
29
|
"typescript": "^5.9.3"
|
|
30
30
|
},
|
|
31
|
-
"
|
|
32
|
-
"lru-cache": "^11.2.6"
|
|
33
|
-
},
|
|
34
|
-
"gitHead": "a113680af7f36b0262a5de692bbf57409a51b86b"
|
|
31
|
+
"gitHead": "17807cefcac092e20ebf99befddf0e742e5fc0e2"
|
|
35
32
|
}
|