express-memorize 1.3.0 → 2.0.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +204 -66
  3. package/dist/MemorizeStore.d.ts +29 -7
  4. package/dist/MemorizeStore.d.ts.map +1 -1
  5. package/dist/MemorizeStore.js +78 -7
  6. package/dist/MemorizeStore.js.map +1 -1
  7. package/dist/adapters/express.d.ts +25 -0
  8. package/dist/adapters/express.d.ts.map +1 -0
  9. package/dist/adapters/express.js +62 -0
  10. package/dist/adapters/express.js.map +1 -0
  11. package/dist/adapters/fetch.d.ts +45 -0
  12. package/dist/adapters/fetch.d.ts.map +1 -0
  13. package/dist/adapters/fetch.js +72 -0
  14. package/dist/adapters/fetch.js.map +1 -0
  15. package/dist/adapters/hono.d.ts +34 -0
  16. package/dist/adapters/hono.d.ts.map +1 -0
  17. package/dist/adapters/hono.js +63 -0
  18. package/dist/adapters/hono.js.map +1 -0
  19. package/dist/adapters/nestjs.d.ts +84 -0
  20. package/dist/adapters/nestjs.d.ts.map +1 -0
  21. package/dist/adapters/nestjs.js +194 -0
  22. package/dist/adapters/nestjs.js.map +1 -0
  23. package/dist/domain/CacheEntry.d.ts +4 -0
  24. package/dist/domain/CacheEntry.d.ts.map +1 -1
  25. package/dist/domain/Memorize.d.ts +99 -4
  26. package/dist/domain/Memorize.d.ts.map +1 -1
  27. package/dist/domain/MemorizeCallOptions.d.ts +2 -2
  28. package/dist/domain/MemorizeEvent.d.ts +2 -1
  29. package/dist/domain/MemorizeEvent.d.ts.map +1 -1
  30. package/dist/domain/MemorizeEventType.d.ts +3 -1
  31. package/dist/domain/MemorizeEventType.d.ts.map +1 -1
  32. package/dist/domain/MemorizeEventType.js +2 -0
  33. package/dist/domain/MemorizeEventType.js.map +1 -1
  34. package/dist/domain/MemorizeEvictEvent.d.ts +18 -0
  35. package/dist/domain/MemorizeEvictEvent.d.ts.map +1 -0
  36. package/dist/domain/MemorizeEvictEvent.js +3 -0
  37. package/dist/domain/MemorizeEvictEvent.js.map +1 -0
  38. package/dist/domain/MemorizeOptions.d.ts +12 -0
  39. package/dist/domain/MemorizeOptions.d.ts.map +1 -1
  40. package/dist/domain/MemorizeSetEvent.d.ts +2 -0
  41. package/dist/domain/MemorizeSetEvent.d.ts.map +1 -1
  42. package/dist/domain/MemorizeStats.d.ts +12 -0
  43. package/dist/domain/MemorizeStats.d.ts.map +1 -0
  44. package/dist/domain/MemorizeStats.js +3 -0
  45. package/dist/domain/MemorizeStats.js.map +1 -0
  46. package/dist/domain/index.d.ts +2 -0
  47. package/dist/domain/index.d.ts.map +1 -1
  48. package/dist/index.d.ts +1 -1
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/memorize.d.ts +19 -16
  51. package/dist/memorize.d.ts.map +1 -1
  52. package/dist/memorize.js +51 -45
  53. package/dist/memorize.js.map +1 -1
  54. package/package.json +46 -12
package/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  This file is automatically updated by [release-please](https://github.com/googleapis/release-please) based on [Conventional Commits](https://www.conventionalcommits.org/).
6
6
 
7
+ ## [1.4.0](https://github.com/ElJijuna/express-memorize/compare/v1.3.0...v1.4.0) (2026-03-31)
8
+
9
+
10
+ ### Features
11
+
12
+ * add hits counter to track cache key consumption ([8104029](https://github.com/ElJijuna/express-memorize/commit/81040296354c8a6de78542d6cc6c3fdc18e21e04))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * add header X-Cache: BYPASS value when set noCache: true in middleware config to override. ([cab3c85](https://github.com/ElJijuna/express-memorize/commit/cab3c85f53885ff287e569248a402632363f31fd))
18
+
7
19
  ## [1.3.0](https://github.com/ElJijuna/express-memorize/compare/v1.2.0...v1.3.0) (2026-03-26)
8
20
 
9
21
 
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  </p>
10
10
 
11
11
  <p align="center">
12
- In-memory cache middleware for <strong>Express.js</strong>.<br/>
12
+ In-memory HTTP cache for <strong>Express, NestJS, Hono, Fetch API</strong>, and more.<br/>
13
13
  Caches <code>GET</code> responses with optional TTL — zero dependencies, fully typed.
14
14
  </p>
15
15
 
@@ -18,12 +18,16 @@
18
18
  ## Features
19
19
 
20
20
  - Caches `GET` responses automatically when status code is `2xx`
21
- - Per-route TTL override
22
- - Event hooks: `set`, `delete`, `expire`
23
- - Cache inspection and invalidation API
24
- - `X-Cache: HIT | MISS` response header
25
- - Zero runtime dependencies
26
- - Full TypeScript support
21
+ - Works with **Express**, **NestJS**, **Hono**, **Fetch API / serverless**, and direct service-level usage
22
+ - Per-route TTL override and `noCache` bypass
23
+ - **`maxEntries` cap with LRU eviction** to bound memory usage
24
+ - **Size metrics**: `size()`, `byteSize()`, `getStats()`
25
+ - **Service-level cache**: `remember()`, `set()`, `getValue()`
26
+ - Event hooks: `set`, `delete`, `expire`, `evict`
27
+ - Cache inspection and invalidation API (`get`, `getAll`, `delete`, `deleteMatching`, `clear`)
28
+ - Hit counter per cache entry
29
+ - `X-Cache: HIT | MISS | BYPASS` response header
30
+ - Zero runtime dependencies, fully typed
27
31
 
28
32
  ## Installation
29
33
 
@@ -31,14 +35,23 @@
31
35
  npm install express-memorize
32
36
  ```
33
37
 
38
+ Adapters for non-Express runtimes are optional — install only what you need:
39
+
40
+ ```bash
41
+ npm install hono # only if using the Hono adapter
42
+ npm install @nestjs/common @nestjs/core rxjs # only if using the NestJS adapter
43
+ ```
44
+
34
45
  ## Quick Start
35
46
 
47
+ ### Express
48
+
36
49
  ```typescript
37
50
  import express from 'express';
38
51
  import { memorize } from 'express-memorize';
39
52
 
40
53
  const app = express();
41
- const cache = memorize({ ttl: 30_000 }); // 30 seconds global TTL
54
+ const cache = memorize({ ttl: 30_000 });
42
55
 
43
56
  app.get('/users', cache(), async (req, res) => {
44
57
  const users = await db.getUsers();
@@ -48,32 +61,92 @@ app.get('/users', cache(), async (req, res) => {
48
61
  app.listen(3000);
49
62
  ```
50
63
 
51
- The first request computes the response normally. Every subsequent `GET /users` is served from memory until the TTL expires.
64
+ ### Hono
52
65
 
53
- ## Usage
66
+ ```typescript
67
+ import { Hono } from 'hono';
68
+ import { memorize } from 'express-memorize';
69
+ import { createHonoMiddleware } from 'express-memorize/hono';
70
+
71
+ const app = new Hono();
72
+ const cache = memorize({ ttl: 30_000 });
73
+
74
+ app.get('/users', createHonoMiddleware(cache), async (c) => {
75
+ return c.json(await usersService.findAll());
76
+ });
77
+ ```
78
+
79
+ ### NestJS
80
+
81
+ ```typescript
82
+ import { Module } from '@nestjs/common';
83
+ import { APP_INTERCEPTOR } from '@nestjs/core';
84
+ import {
85
+ MemorizeCacheKey,
86
+ MemorizeInterceptor,
87
+ MemorizeModule,
88
+ MemorizeTtl,
89
+ } from 'express-memorize/nestjs';
90
+
91
+ @Module({
92
+ imports: [MemorizeModule.forRoot({ ttl: 30_000 })],
93
+ providers: [
94
+ {
95
+ provide: APP_INTERCEPTOR,
96
+ useExisting: MemorizeInterceptor,
97
+ },
98
+ ],
99
+ })
100
+ export class AppModule {}
101
+
102
+ export class UsersController {
103
+ @MemorizeCacheKey('users:list')
104
+ @MemorizeTtl(10_000)
105
+ findAll() {
106
+ return usersService.findAll();
107
+ }
108
+ }
109
+ ```
110
+
111
+ ### Fetch API / Serverless
112
+
113
+ ```typescript
114
+ import { memorize } from 'express-memorize';
115
+ import { cacheFetchHandler } from 'express-memorize/fetch';
116
+
117
+ const cache = memorize({ ttl: 30_000 });
118
+
119
+ export default cacheFetchHandler(cache, async (request) => {
120
+ const users = await usersService.findAll();
121
+ return Response.json(users);
122
+ });
123
+ ```
54
124
 
55
- ### Global middleware
125
+ ### Service-level caching
56
126
 
57
- Apply the cache to the entire application with `app.use()`. Every `GET` route is cached automatically non-`GET` requests are bypassed without any extra configuration.
127
+ Cache arbitrary values directlyno HTTP layer required.
58
128
 
59
129
  ```typescript
60
130
  const cache = memorize({ ttl: 60_000 });
61
131
 
62
- app.use(cache()); // applies to all GET routes
132
+ // Compute-and-cache pattern
133
+ const users = await cache.remember('users:list', () => usersService.findAll());
63
134
 
64
- app.get('/users', (req, res) => { res.json({ data: users }) });
65
- app.get('/products', (req, res) => { res.json({ data: products }) });
66
- // POST, PUT, PATCH, DELETE routes are unaffected
135
+ // Explicit set/get
136
+ cache.set('config', appConfig);
137
+ const config = cache.getValue<AppConfig>('config');
67
138
  ```
68
139
 
69
- ### Per-route cache
140
+ ---
141
+
142
+ ## Usage
143
+
144
+ ### Global middleware (Express)
70
145
 
71
146
  ```typescript
72
147
  const cache = memorize({ ttl: 60_000 });
73
148
 
74
- app.get('/products', cache(), (req, res) => {
75
- res.json({ data: products });
76
- });
149
+ app.use(cache()); // applies to all GET routes
77
150
  ```
78
151
 
79
152
  ### Per-route TTL override
@@ -82,39 +155,69 @@ app.get('/products', cache(), (req, res) => {
82
155
  const cache = memorize({ ttl: 60_000 }); // global: 60s
83
156
 
84
157
  app.get('/users', cache(), handler); // 60s
85
- app.get('/products', cache({ ttl: 10_000 }), handler); // override: 10s
158
+ app.get('/products', cache({ ttl: 10_000 }), handler); // 10s
86
159
  app.get('/config', cache({ ttl: 0 }), handler); // no expiry
87
160
  ```
88
161
 
89
- ### Cache invalidation
162
+ ### noCache bypass
90
163
 
91
164
  ```typescript
92
- const cache = memorize({ ttl: 30_000 });
165
+ app.get('/live-feed', cache({ noCache: true }), handler);
166
+ // Sets X-Cache: BYPASS, never reads or writes the cache
167
+ ```
93
168
 
94
- app.get('/users', cache(), (req, res) => {
95
- res.json({ data: users });
96
- });
169
+ ### NestJS decorators
170
+
171
+ Use `MemorizeInterceptor` on a controller or globally, then configure caching at the controller or method level.
172
+
173
+ ```typescript
174
+ import { Controller, Get, UseInterceptors } from '@nestjs/common';
175
+ import {
176
+ MemorizeCacheKey,
177
+ MemorizeInterceptor,
178
+ MemorizeNoCache,
179
+ MemorizeTtl,
180
+ } from 'express-memorize/nestjs';
181
+
182
+ @Controller('users')
183
+ @UseInterceptors(MemorizeInterceptor)
184
+ @MemorizeTtl(30_000)
185
+ export class UsersController {
186
+ @Get()
187
+ @MemorizeCacheKey('users:list')
188
+ findAll() {
189
+ return usersService.findAll();
190
+ }
191
+
192
+ @Get('live')
193
+ @MemorizeNoCache()
194
+ live() {
195
+ return usersService.live();
196
+ }
197
+ }
198
+ ```
97
199
 
200
+ For global usage, import `MemorizeModule.forRoot()` and register `APP_INTERCEPTOR` with `useExisting: MemorizeInterceptor` so the interceptor receives the module's shared cache instance.
201
+
202
+ ### Cache invalidation
203
+
204
+ ```typescript
98
205
  app.post('/users', (req, res) => {
99
206
  users.push(req.body);
100
- cache.delete('/users'); // invalidate after mutation
101
- res.status(201).json({ data: req.body });
207
+ cache.delete('/users');
208
+ res.status(201).json(req.body);
102
209
  });
103
210
  ```
104
211
 
105
212
  ### Pattern-based invalidation
106
213
 
107
- Use `cache.deleteMatching(pattern)` to remove all cache entries whose keys match a glob pattern. This is useful when you don't know the exact key — for example, when a URL may have different query strings.
214
+ Use `cache.deleteMatching(pattern)` to remove entries by glob pattern.
108
215
 
109
216
  ```typescript
110
- // Cached keys: /api/users/abc123, /api/users/abc123?lang=es, /api/users/abc123?page=1
111
217
  app.put('/users/:id', (req, res) => {
112
218
  users.update(req.params.id, req.body);
113
-
114
- // Remove all cached variants of this user, regardless of query params
115
219
  const deleted = cache.deleteMatching(`**/users/${req.params.id}*`);
116
- console.log(`${deleted} cache entries removed`);
117
-
220
+ console.log(`${deleted} entries removed`);
118
221
  res.json({ ok: true });
119
222
  });
120
223
  ```
@@ -123,35 +226,33 @@ app.put('/users/:id', (req, res) => {
123
226
 
124
227
  | Pattern | Behaviour |
125
228
  |---------|-----------|
126
- | `*` | Matches any sequence of characters **within** a single path segment (does not cross `/`) |
127
- | `**` | Matches any sequence of characters **across** path segments (crosses `/`) |
229
+ | `*` | Matches any sequence within a single path segment (does not cross `/`) |
230
+ | `**` | Matches any sequence across path segments (crosses `/`) |
128
231
  | `?` | Matches any single character except `/` |
129
232
 
130
- `deleteMatching` returns the number of entries removed and emits a `delete` event for each one.
233
+ ### Bounding memory with `maxEntries`
131
234
 
132
- ### Event hooks
235
+ Prevent unbounded growth by setting a maximum number of entries. When the limit is reached, the **least-recently-used (LRU)** entry is evicted before the new one is stored.
133
236
 
134
237
  ```typescript
135
- const cache = memorize({ ttl: 30_000 });
136
-
137
- cache.on('set', (e) => {
138
- console.log(`[cache] stored ${e.key} — expires in ${e.expiresAt ? e.expiresAt - Date.now() : '∞'}ms`);
139
- });
238
+ const cache = memorize({ ttl: 30_000, maxEntries: 1_000 });
239
+ ```
140
240
 
141
- cache.on('delete', (e) => {
142
- console.log(`[cache] deleted ${e.key}`);
143
- });
241
+ ### Size metrics
144
242
 
145
- cache.on('expire', (e) => {
146
- console.log(`[cache] expired ${e.key}`);
147
- });
243
+ ```typescript
244
+ cache.size(); // number of active entries
245
+ cache.byteSize(); // approximate total body size in bytes
246
+ cache.getStats(); // { entries, maxEntries, byteSize }
148
247
  ```
149
248
 
249
+ > `byteSize()` is an estimate based on UTF-8 encoding for strings and `byteLength` for buffers. It may not reflect actual VM memory usage.
250
+
150
251
  ### Inspect the cache
151
252
 
152
253
  ```typescript
153
- cache.get('/users'); // CacheInfo | null — single entry
154
- cache.getAll(); // Record<string, CacheInfo> — all active entries
254
+ cache.get('/users'); // CacheInfo | null
255
+ cache.getAll(); // Record<string, CacheInfo>
155
256
  ```
156
257
 
157
258
  `CacheInfo` shape:
@@ -164,17 +265,27 @@ cache.getAll(); // Record<string, CacheInfo> — all active entries
164
265
  contentType: string;
165
266
  expiresAt: number | null;
166
267
  remainingTtl: number | null; // ms until expiry, null if no TTL
268
+ hits: number; // times this key was served from cache
269
+ size: number; // approximate body size in bytes
167
270
  }
168
271
  ```
169
272
 
170
- ### Clear the cache
273
+ `hits` starts at `1` on the initial cache miss and increments on every hit. It resets to `1` if the entry is evicted and re-cached.
274
+
275
+ ### Event hooks
171
276
 
172
277
  ```typescript
173
- cache.delete('/users'); // remove one entry
174
- cache.deleteMatching('**/users/*'); // remove all /users/* entries
175
- cache.clear(); // remove all entries
278
+ import { MemorizeEventType } from 'express-memorize';
279
+
280
+ cache.on(MemorizeEventType.Set, (e) => console.log('stored', e.key));
281
+ cache.on(MemorizeEventType.Delete, (e) => console.log('deleted', e.key));
282
+ cache.on(MemorizeEventType.Expire, (e) => console.log('expired', e.key));
283
+ cache.on(MemorizeEventType.Evict, (e) => console.log('evicted', e.key)); // maxEntries LRU
284
+ cache.on(MemorizeEventType.Empty, () => console.log('cache is empty'));
176
285
  ```
177
286
 
287
+ ---
288
+
178
289
  ## API Reference
179
290
 
180
291
  ### `memorize(options?)`
@@ -184,32 +295,57 @@ Creates a cache instance. Returns a `Memorize` object.
184
295
  | Option | Type | Default | Description |
185
296
  |--------|------|---------|-------------|
186
297
  | `ttl` | `number` | `undefined` | Time-to-live in milliseconds. Omit for no expiry. |
298
+ | `maxEntries` | `number` | `undefined` | Maximum number of entries. LRU eviction when reached. |
187
299
 
188
- ### `cache(options?)`
300
+ ### `cache(options?)` / `cache.express(options?)`
189
301
 
190
- Returns an Express `RequestHandler` middleware. Can override the global TTL.
302
+ Returns an Express `RequestHandler`. `cache()` is a backwards-compatible alias for `cache.express()`.
191
303
 
192
304
  | Option | Type | Default | Description |
193
305
  |--------|------|---------|-------------|
194
- | `ttl` | `number` | global `ttl` | TTL override for this specific route. |
306
+ | `ttl` | `number` | global `ttl` | TTL override for this route. |
307
+ | `noCache` | `boolean` | `false` | Skip cache entirely. Sets `X-Cache: BYPASS`. |
308
+
309
+ ### Service-level cache methods
310
+
311
+ | Method | Signature | Description |
312
+ |--------|-----------|-------------|
313
+ | `remember` | `(key, factory, ttl?) => Promise<T>` | Return cached value or call factory and cache the result. |
314
+ | `set` | `(key, value, ttl?) => void` | Store an arbitrary value. |
315
+ | `getValue` | `(key) => T \| undefined` | Retrieve a value stored via `set` or `remember`. |
195
316
 
196
317
  ### Cache management
197
318
 
198
319
  | Method | Signature | Description |
199
320
  |--------|-----------|-------------|
200
- | `get` | `(key: string) => CacheInfo \| null` | Returns info for a cached key. |
201
- | `getAll` | `() => Record<string, CacheInfo>` | Returns all active cache entries. |
202
- | `delete` | `(key: string) => boolean` | Removes a single entry. Returns `false` if not found. |
203
- | `deleteMatching` | `(pattern: string) => number` | Removes all entries matching a glob pattern. Returns the count removed. |
321
+ | `get` | `(key) => CacheInfo \| null` | Returns info for a cached key. |
322
+ | `getAll` | `() => Record<string, CacheInfo>` | Returns all active entries. |
323
+ | `delete` | `(key) => boolean` | Removes a single entry. |
324
+ | `deleteMatching` | `(pattern) => number` | Removes entries matching a glob pattern. |
204
325
  | `clear` | `() => void` | Removes all entries. |
326
+ | `size` | `() => number` | Number of active entries. |
327
+ | `byteSize` | `() => number` | Approximate total body size in bytes. |
328
+ | `getStats` | `() => MemorizeStats` | Aggregate stats: `{ entries, maxEntries, byteSize }`. |
329
+
330
+ ### Adapters
331
+
332
+ | Import path | Export | Framework |
333
+ |-------------|--------|-----------|
334
+ | `express-memorize` | `memorize` | Core factory |
335
+ | `express-memorize/express` | `createExpressAdapter(cache, options?)` | Express |
336
+ | `express-memorize/nestjs` | `MemorizeModule`, `MemorizeInterceptor`, decorators | NestJS |
337
+ | `express-memorize/hono` | `createHonoMiddleware(cache, options?)` | Hono |
338
+ | `express-memorize/fetch` | `cacheFetchHandler(cache, handler, options?)` | Fetch API / Serverless |
205
339
 
206
340
  ### Events
207
341
 
208
342
  | Event | Payload | When |
209
343
  |-------|---------|------|
210
- | `set` | `{ type, key, body, statusCode, contentType, expiresAt }` | A response is stored |
211
- | `delete` | `{ type, key }` | `cache.delete()`, `cache.deleteMatching()`, or `cache.clear()` is called |
344
+ | `set` | `{ type, key, body, statusCode, contentType, expiresAt, size }` | A response is stored |
345
+ | `delete` | `{ type, key }` | Manual removal via `delete`, `deleteMatching`, or `clear` |
212
346
  | `expire` | `{ type, key }` | TTL timer fires or lazy expiry is detected |
347
+ | `evict` | `{ type, key }` | LRU eviction due to `maxEntries` limit |
348
+ | `empty` | `{ type }` | Last entry removed, cache is now empty |
213
349
 
214
350
  ## Response Headers
215
351
 
@@ -217,13 +353,15 @@ Returns an Express `RequestHandler` middleware. Can override the global TTL.
217
353
  |--------|-------|-------------|
218
354
  | `X-Cache` | `HIT` | Response served from cache |
219
355
  | `X-Cache` | `MISS` | Response computed and stored |
356
+ | `X-Cache` | `BYPASS` | Cache skipped — `noCache: true` |
220
357
 
221
358
  ## Behavior
222
359
 
223
- - Only `GET` requests are cached. All other methods bypass the middleware entirely.
360
+ - Only `GET` requests are cached. All other methods bypass the cache entirely.
224
361
  - Only responses with a `2xx` status code are stored.
225
- - Each call to `cache()` returns an independent middleware handler, but all handlers created from the same `memorize()` instance **share the same store**.
362
+ - All middleware and adapter instances created from the same `memorize()` call **share the same store**.
226
363
  - Two separate `memorize()` calls produce **independent stores**.
364
+ - Byte size is an approximation — strings use UTF-8 encoding, objects use `JSON.stringify` length.
227
365
 
228
366
  ## License
229
367
 
@@ -1,23 +1,28 @@
1
1
  import { CacheEntry } from './domain/CacheEntry';
2
2
  import { CacheInfo } from './domain/CacheInfo';
3
+ import { MemorizeStats } from './domain/MemorizeStats';
3
4
  import { MemorizeEventType } from './domain/MemorizeEventType';
4
5
  import { MemorizeEvent } from './domain/MemorizeEvent';
5
6
  import { MemorizeSetEvent } from './domain/MemorizeSetEvent';
6
7
  import { MemorizeDeleteEvent } from './domain/MemorizeDeleteEvent';
7
8
  import { MemorizeExpireEvent } from './domain/MemorizeExpireEvent';
8
9
  import { MemorizeEmptyEvent } from './domain/MemorizeEmptyEvent';
9
- export type { CacheEntry, CacheInfo, MemorizeEvent, MemorizeSetEvent, MemorizeDeleteEvent, MemorizeExpireEvent, MemorizeEmptyEvent, };
10
+ import { MemorizeEvictEvent } from './domain/MemorizeEvictEvent';
11
+ export type { CacheEntry, CacheInfo, MemorizeStats, MemorizeEvent, MemorizeSetEvent, MemorizeDeleteEvent, MemorizeExpireEvent, MemorizeEmptyEvent, MemorizeEvictEvent, };
10
12
  export { MemorizeEventType };
11
13
  /**
12
- * Low-level in-memory key-value store with optional TTL and event emission.
14
+ * Low-level in-memory key-value store with optional TTL, LRU eviction, and event emission.
13
15
  *
14
16
  * You do not usually interact with this class directly — use the {@link memorize} factory
15
17
  * instead, which wraps this store in an Express middleware.
16
18
  */
17
19
  export declare class MemorizeStore {
20
+ private readonly _maxEntries?;
18
21
  private _store;
19
22
  private _timers;
23
+ private _totalByteSize;
20
24
  private _listeners;
25
+ constructor(_maxEntries?: number | undefined);
21
26
  /**
22
27
  * Registers an event listener.
23
28
  *
@@ -26,25 +31,27 @@ export declare class MemorizeStore {
26
31
  *
27
32
  * @example
28
33
  * ```ts
29
- * store.on(MemorizeEventType.Set, (e) => console.log('cached', e.key));
30
- * store.on(MemorizeEventType.Expire, (e) => console.log('expired', e.key));
34
+ * store.on(MemorizeEventType.Set, (e) => console.log('cached', e.key));
35
+ * store.on(MemorizeEventType.Evict, (e) => console.log('evicted', e.key));
31
36
  * ```
32
37
  */
33
38
  on(event: MemorizeEventType.Set, handler: (e: MemorizeSetEvent) => void): void;
34
39
  on(event: MemorizeEventType.Delete, handler: (e: MemorizeDeleteEvent) => void): void;
35
40
  on(event: MemorizeEventType.Expire, handler: (e: MemorizeExpireEvent) => void): void;
36
41
  on(event: MemorizeEventType.Empty, handler: (e: MemorizeEmptyEvent) => void): void;
42
+ on(event: MemorizeEventType.Evict, handler: (e: MemorizeEvictEvent) => void): void;
37
43
  /**
38
44
  * Stores an entry in the cache.
39
45
  *
40
46
  * If an entry already exists for the given key its TTL timer is reset and the
41
- * value is overwritten. Emits a {@link MemorizeEventType.Set} event.
47
+ * value is overwritten. If `maxEntries` is configured and the store is full,
48
+ * the least-recently-used entry is evicted first. Emits a {@link MemorizeEventType.Set} event.
42
49
  *
43
50
  * @param key - The cache key (typically `req.originalUrl`).
44
51
  * @param entry - The response data to store.
45
52
  * @param ttl - Time-to-live in milliseconds. Omit or pass `null` for no expiry.
46
53
  */
47
- set(key: string, entry: Omit<CacheEntry, 'expiresAt'>, ttl?: number | null): void;
54
+ set(key: string, entry: Omit<CacheEntry, 'expiresAt' | 'hits' | 'size'>, ttl?: number | null): void;
48
55
  /**
49
56
  * Returns the formatted {@link CacheInfo} for the given key, or `null` if the
50
57
  * key does not exist or its TTL has elapsed.
@@ -82,15 +89,30 @@ export declare class MemorizeStore {
82
89
  * for each entry.
83
90
  */
84
91
  clear(): void;
92
+ /**
93
+ * Returns the number of active cache entries.
94
+ */
95
+ size(): number;
96
+ /**
97
+ * Returns the approximate total byte size of all cached bodies.
98
+ *
99
+ * The value is an estimate and may not reflect actual memory usage.
100
+ */
101
+ byteSize(): number;
102
+ /**
103
+ * Returns aggregate cache statistics.
104
+ */
105
+ getStats(): MemorizeStats;
85
106
  /**
86
107
  * Returns the raw {@link CacheEntry} for the given key without formatting metadata,
87
108
  * or `null` if the entry is missing or expired. Used internally by the middleware
88
- * to serve cached responses.
109
+ * to serve cached responses. Updates LRU order and increments the hit counter.
89
110
  *
90
111
  * @param key - The cache key to look up.
91
112
  * @internal
92
113
  */
93
114
  getRaw(key: string): CacheEntry | null;
115
+ private _evictLRU;
94
116
  private _evict;
95
117
  private _emit;
96
118
  private _format;
@@ -1 +1 @@
1
- {"version":3,"file":"MemorizeStore.d.ts","sourceRoot":"","sources":["../src/MemorizeStore.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAEjE,YAAY,EACV,UAAU,EACV,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,GACnB,CAAC;AACF,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAS7B;;;;;GAKG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,OAAO,CAAoD;IACnE,OAAO,CAAC,UAAU,CAKhB;IAEF;;;;;;;;;;;OAWG;IACH,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,GAAG,EAAK,OAAO,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,IAAI,GAAG,IAAI;IACjF,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,mBAAmB,KAAK,IAAI,GAAG,IAAI;IACpF,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,mBAAmB,KAAK,IAAI,GAAG,IAAI;IACpF,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,KAAK,EAAG,OAAO,EAAE,CAAC,CAAC,EAAE,kBAAkB,KAAK,IAAI,GAAG,IAAI;IAMnF;;;;;;;;;OASG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAsBjF;;;;;OAKG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAYlC;;;OAGG;IACH,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC;IAcnC;;;;;OAKG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAM5B;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAYvC;;;OAGG;IACH,KAAK,IAAI,IAAI;IAMb;;;;;;;OAOG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAYtC,OAAO,CAAC,MAAM;IAYd,OAAO,CAAC,KAAK;IAMb,OAAO,CAAC,OAAO;CAUhB"}
1
+ {"version":3,"file":"MemorizeStore.d.ts","sourceRoot":"","sources":["../src/MemorizeStore.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAEjE,YAAY,EACV,UAAU,EACV,SAAS,EACT,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GACnB,CAAC;AACF,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAsB7B;;;;;GAKG;AACH,qBAAa,aAAa;IAYZ,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAXzC,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,OAAO,CAAoD;IACnE,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,UAAU,CAMhB;gBAE2B,WAAW,CAAC,EAAE,MAAM,YAAA;IAEjD;;;;;;;;;;;OAWG;IACH,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,GAAG,EAAK,OAAO,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,IAAI,GAAG,IAAI;IACjF,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,mBAAmB,KAAK,IAAI,GAAG,IAAI;IACpF,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,mBAAmB,KAAK,IAAI,GAAG,IAAI;IACpF,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,KAAK,EAAG,OAAO,EAAE,CAAC,CAAC,EAAE,kBAAkB,KAAK,IAAI,GAAG,IAAI;IACnF,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,KAAK,EAAG,OAAO,EAAE,CAAC,CAAC,EAAE,kBAAkB,KAAK,IAAI,GAAG,IAAI;IAMnF;;;;;;;;;;OAUG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAiCnG;;;;;OAKG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAYlC;;;OAGG;IACH,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC;IAcnC;;;;;OAKG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAM5B;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAYvC;;;OAGG;IACH,KAAK,IAAI,IAAI;IAMb;;OAEG;IACH,IAAI,IAAI,MAAM;IAId;;;;OAIG;IACH,QAAQ,IAAI,MAAM;IAIlB;;OAEG;IACH,QAAQ,IAAI,aAAa;IAQzB;;;;;;;OAOG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAiBtC,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,MAAM;IAgBd,OAAO,CAAC,KAAK;IAMb,OAAO,CAAC,OAAO;CAYhB"}