express-memorize 1.4.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 (52) hide show
  1. package/README.md +201 -78
  2. package/dist/MemorizeStore.d.ts +29 -7
  3. package/dist/MemorizeStore.d.ts.map +1 -1
  4. package/dist/MemorizeStore.js +76 -7
  5. package/dist/MemorizeStore.js.map +1 -1
  6. package/dist/adapters/express.d.ts +25 -0
  7. package/dist/adapters/express.d.ts.map +1 -0
  8. package/dist/adapters/express.js +62 -0
  9. package/dist/adapters/express.js.map +1 -0
  10. package/dist/adapters/fetch.d.ts +45 -0
  11. package/dist/adapters/fetch.d.ts.map +1 -0
  12. package/dist/adapters/fetch.js +72 -0
  13. package/dist/adapters/fetch.js.map +1 -0
  14. package/dist/adapters/hono.d.ts +34 -0
  15. package/dist/adapters/hono.d.ts.map +1 -0
  16. package/dist/adapters/hono.js +63 -0
  17. package/dist/adapters/hono.js.map +1 -0
  18. package/dist/adapters/nestjs.d.ts +84 -0
  19. package/dist/adapters/nestjs.d.ts.map +1 -0
  20. package/dist/adapters/nestjs.js +194 -0
  21. package/dist/adapters/nestjs.js.map +1 -0
  22. package/dist/domain/CacheEntry.d.ts +2 -0
  23. package/dist/domain/CacheEntry.d.ts.map +1 -1
  24. package/dist/domain/Memorize.d.ts +99 -4
  25. package/dist/domain/Memorize.d.ts.map +1 -1
  26. package/dist/domain/MemorizeEvent.d.ts +2 -1
  27. package/dist/domain/MemorizeEvent.d.ts.map +1 -1
  28. package/dist/domain/MemorizeEventType.d.ts +3 -1
  29. package/dist/domain/MemorizeEventType.d.ts.map +1 -1
  30. package/dist/domain/MemorizeEventType.js +2 -0
  31. package/dist/domain/MemorizeEventType.js.map +1 -1
  32. package/dist/domain/MemorizeEvictEvent.d.ts +18 -0
  33. package/dist/domain/MemorizeEvictEvent.d.ts.map +1 -0
  34. package/dist/domain/MemorizeEvictEvent.js +3 -0
  35. package/dist/domain/MemorizeEvictEvent.js.map +1 -0
  36. package/dist/domain/MemorizeOptions.d.ts +12 -0
  37. package/dist/domain/MemorizeOptions.d.ts.map +1 -1
  38. package/dist/domain/MemorizeSetEvent.d.ts +2 -0
  39. package/dist/domain/MemorizeSetEvent.d.ts.map +1 -1
  40. package/dist/domain/MemorizeStats.d.ts +12 -0
  41. package/dist/domain/MemorizeStats.d.ts.map +1 -0
  42. package/dist/domain/MemorizeStats.js +3 -0
  43. package/dist/domain/MemorizeStats.js.map +1 -0
  44. package/dist/domain/index.d.ts +2 -0
  45. package/dist/domain/index.d.ts.map +1 -1
  46. package/dist/index.d.ts +1 -1
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/memorize.d.ts +19 -16
  49. package/dist/memorize.d.ts.map +1 -1
  50. package/dist/memorize.js +51 -50
  51. package/dist/memorize.js.map +1 -1
  52. package/package.json +46 -12
@@ -4,21 +4,41 @@ exports.MemorizeStore = exports.MemorizeEventType = void 0;
4
4
  const globToRegex_1 = require("./utils/globToRegex");
5
5
  const MemorizeEventType_1 = require("./domain/MemorizeEventType");
6
6
  Object.defineProperty(exports, "MemorizeEventType", { enumerable: true, get: function () { return MemorizeEventType_1.MemorizeEventType; } });
7
+ function estimateByteSize(value) {
8
+ var _a;
9
+ if (typeof value === 'string')
10
+ return Buffer.byteLength(value);
11
+ if (Buffer.isBuffer(value))
12
+ return value.byteLength;
13
+ if (value instanceof ArrayBuffer)
14
+ return value.byteLength;
15
+ if (ArrayBuffer.isView(value))
16
+ return value.byteLength;
17
+ try {
18
+ return Buffer.byteLength((_a = JSON.stringify(value)) !== null && _a !== void 0 ? _a : '');
19
+ }
20
+ catch (_b) {
21
+ return 0;
22
+ }
23
+ }
7
24
  /**
8
- * Low-level in-memory key-value store with optional TTL and event emission.
25
+ * Low-level in-memory key-value store with optional TTL, LRU eviction, and event emission.
9
26
  *
10
27
  * You do not usually interact with this class directly — use the {@link memorize} factory
11
28
  * instead, which wraps this store in an Express middleware.
12
29
  */
13
30
  class MemorizeStore {
14
- constructor() {
31
+ constructor(_maxEntries) {
32
+ this._maxEntries = _maxEntries;
15
33
  this._store = new Map();
16
34
  this._timers = new Map();
35
+ this._totalByteSize = 0;
17
36
  this._listeners = {
18
37
  [MemorizeEventType_1.MemorizeEventType.Set]: [],
19
38
  [MemorizeEventType_1.MemorizeEventType.Delete]: [],
20
39
  [MemorizeEventType_1.MemorizeEventType.Expire]: [],
21
40
  [MemorizeEventType_1.MemorizeEventType.Empty]: [],
41
+ [MemorizeEventType_1.MemorizeEventType.Evict]: [],
22
42
  };
23
43
  }
24
44
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -29,21 +49,31 @@ class MemorizeStore {
29
49
  * Stores an entry in the cache.
30
50
  *
31
51
  * If an entry already exists for the given key its TTL timer is reset and the
32
- * value is overwritten. Emits a {@link MemorizeEventType.Set} event.
52
+ * value is overwritten. If `maxEntries` is configured and the store is full,
53
+ * the least-recently-used entry is evicted first. Emits a {@link MemorizeEventType.Set} event.
33
54
  *
34
55
  * @param key - The cache key (typically `req.originalUrl`).
35
56
  * @param entry - The response data to store.
36
57
  * @param ttl - Time-to-live in milliseconds. Omit or pass `null` for no expiry.
37
58
  */
38
59
  set(key, entry, ttl) {
60
+ if (this._maxEntries && !this._store.has(key) && this._store.size >= this._maxEntries) {
61
+ this._evictLRU();
62
+ }
39
63
  if (this._timers.has(key)) {
40
64
  clearTimeout(this._timers.get(key));
41
65
  this._timers.delete(key);
42
66
  }
67
+ const existing = this._store.get(key);
68
+ if (existing) {
69
+ this._totalByteSize -= existing.size;
70
+ }
43
71
  const expiresAt = ttl ? Date.now() + ttl : null;
44
- const stored = { ...entry, expiresAt, hits: 1 };
72
+ const size = estimateByteSize(entry.body);
73
+ const stored = { ...entry, expiresAt, hits: 1, size };
45
74
  this._store.set(key, stored);
46
- this._emit(MemorizeEventType_1.MemorizeEventType.Set, { type: MemorizeEventType_1.MemorizeEventType.Set, key, ...entry, expiresAt });
75
+ this._totalByteSize += size;
76
+ this._emit(MemorizeEventType_1.MemorizeEventType.Set, { type: MemorizeEventType_1.MemorizeEventType.Set, key, ...entry, expiresAt, size });
47
77
  if (ttl) {
48
78
  const timer = setTimeout(() => {
49
79
  this._evict(key, MemorizeEventType_1.MemorizeEventType.Expire);
@@ -124,14 +154,39 @@ class MemorizeStore {
124
154
  * for each entry.
125
155
  */
126
156
  clear() {
127
- for (const key of this._store.keys()) {
157
+ for (const key of [...this._store.keys()]) {
128
158
  this._evict(key, MemorizeEventType_1.MemorizeEventType.Delete);
129
159
  }
130
160
  }
161
+ /**
162
+ * Returns the number of active cache entries.
163
+ */
164
+ size() {
165
+ return this._store.size;
166
+ }
167
+ /**
168
+ * Returns the approximate total byte size of all cached bodies.
169
+ *
170
+ * The value is an estimate and may not reflect actual memory usage.
171
+ */
172
+ byteSize() {
173
+ return this._totalByteSize;
174
+ }
175
+ /**
176
+ * Returns aggregate cache statistics.
177
+ */
178
+ getStats() {
179
+ var _a;
180
+ return {
181
+ entries: this._store.size,
182
+ maxEntries: (_a = this._maxEntries) !== null && _a !== void 0 ? _a : null,
183
+ byteSize: this._totalByteSize,
184
+ };
185
+ }
131
186
  /**
132
187
  * Returns the raw {@link CacheEntry} for the given key without formatting metadata,
133
188
  * or `null` if the entry is missing or expired. Used internally by the middleware
134
- * to serve cached responses.
189
+ * to serve cached responses. Updates LRU order and increments the hit counter.
135
190
  *
136
191
  * @param key - The cache key to look up.
137
192
  * @internal
@@ -144,14 +199,27 @@ class MemorizeStore {
144
199
  this._evict(key, MemorizeEventType_1.MemorizeEventType.Expire);
145
200
  return null;
146
201
  }
202
+ // Move to most-recently-used position for LRU eviction
203
+ this._store.delete(key);
204
+ this._store.set(key, entry);
147
205
  entry.hits++;
148
206
  return entry;
149
207
  }
208
+ _evictLRU() {
209
+ const firstKey = this._store.keys().next().value;
210
+ if (firstKey !== undefined) {
211
+ this._evict(firstKey, MemorizeEventType_1.MemorizeEventType.Evict);
212
+ }
213
+ }
150
214
  _evict(key, reason) {
151
215
  if (this._timers.has(key)) {
152
216
  clearTimeout(this._timers.get(key));
153
217
  this._timers.delete(key);
154
218
  }
219
+ const entry = this._store.get(key);
220
+ if (entry) {
221
+ this._totalByteSize = Math.max(0, this._totalByteSize - entry.size);
222
+ }
155
223
  this._store.delete(key);
156
224
  this._emit(reason, { type: reason, key });
157
225
  if (this._store.size === 0) {
@@ -171,6 +239,7 @@ class MemorizeStore {
171
239
  contentType: entry.contentType,
172
240
  expiresAt: entry.expiresAt,
173
241
  hits: entry.hits,
242
+ size: entry.size,
174
243
  remainingTtl: entry.expiresAt ? Math.max(0, entry.expiresAt - Date.now()) : null,
175
244
  };
176
245
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MemorizeStore.js","sourceRoot":"","sources":["../src/MemorizeStore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MemorizeStore.js","sourceRoot":"","sources":["../src/MemorizeStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { RequestHandler } from 'express';
2
+ import type { Memorize } from '../domain/Memorize';
3
+ import { MemorizeStore } from '../MemorizeStore';
4
+ import { MemorizeCallOptions } from '../domain/MemorizeCallOptions';
5
+ /**
6
+ * Creates an Express `RequestHandler` that caches `GET` responses using the
7
+ * provided {@link Memorize} instance.
8
+ *
9
+ * Import from `express-memorize/express` when you need the adapter directly,
10
+ * without going through the `memorize()` factory.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * import { memorize } from 'express-memorize';
15
+ * import { createExpressAdapter } from 'express-memorize/express';
16
+ *
17
+ * const cache = memorize({ ttl: 30_000 });
18
+ * app.get('/users', createExpressAdapter(cache), handler);
19
+ * app.get('/products', createExpressAdapter(cache, { ttl: 5_000 }), handler);
20
+ * ```
21
+ */
22
+ export declare function createExpressAdapter(cache: Memorize, options?: MemorizeCallOptions): RequestHandler;
23
+ /** @internal Used by the memorize() factory. */
24
+ export declare function createExpressMiddleware(store: MemorizeStore, globalTtl?: number): (callOptions?: MemorizeCallOptions) => RequestHandler;
25
+ //# sourceMappingURL=express.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/adapters/express.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmC,cAAc,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEpE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,QAAQ,EACf,OAAO,CAAC,EAAE,mBAAmB,GAC5B,cAAc,CAEhB;AAED,gDAAgD;AAChD,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,aAAa,EACpB,SAAS,CAAC,EAAE,MAAM,GACjB,CAAC,WAAW,CAAC,EAAE,mBAAmB,KAAK,cAAc,CAwCvD"}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createExpressAdapter = createExpressAdapter;
4
+ exports.createExpressMiddleware = createExpressMiddleware;
5
+ /**
6
+ * Creates an Express `RequestHandler` that caches `GET` responses using the
7
+ * provided {@link Memorize} instance.
8
+ *
9
+ * Import from `express-memorize/express` when you need the adapter directly,
10
+ * without going through the `memorize()` factory.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * import { memorize } from 'express-memorize';
15
+ * import { createExpressAdapter } from 'express-memorize/express';
16
+ *
17
+ * const cache = memorize({ ttl: 30_000 });
18
+ * app.get('/users', createExpressAdapter(cache), handler);
19
+ * app.get('/products', createExpressAdapter(cache, { ttl: 5_000 }), handler);
20
+ * ```
21
+ */
22
+ function createExpressAdapter(cache, options) {
23
+ return cache.express(options);
24
+ }
25
+ /** @internal Used by the memorize() factory. */
26
+ function createExpressMiddleware(store, globalTtl) {
27
+ return function (callOptions) {
28
+ var _a;
29
+ const effectiveTtl = (_a = callOptions === null || callOptions === void 0 ? void 0 : callOptions.ttl) !== null && _a !== void 0 ? _a : globalTtl;
30
+ return function (req, res, next) {
31
+ if (req.method !== 'GET') {
32
+ next();
33
+ return;
34
+ }
35
+ if (callOptions === null || callOptions === void 0 ? void 0 : callOptions.noCache) {
36
+ res.setHeader('X-Cache', 'BYPASS');
37
+ next();
38
+ return;
39
+ }
40
+ const key = req.originalUrl;
41
+ const cached = store.getRaw(key);
42
+ if (cached) {
43
+ res.setHeader('X-Cache', 'HIT');
44
+ res.setHeader('Content-Type', cached.contentType);
45
+ res.status(cached.statusCode).send(cached.body);
46
+ return;
47
+ }
48
+ const originalSend = res.send.bind(res);
49
+ res.send = function (body) {
50
+ var _a;
51
+ if (res.statusCode >= 200 && res.statusCode < 300) {
52
+ const contentType = (_a = res.getHeader('Content-Type')) !== null && _a !== void 0 ? _a : 'application/octet-stream';
53
+ store.set(key, { body, statusCode: res.statusCode, contentType }, effectiveTtl);
54
+ }
55
+ res.setHeader('X-Cache', 'MISS');
56
+ return originalSend(body);
57
+ };
58
+ next();
59
+ };
60
+ };
61
+ }
62
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/adapters/express.ts"],"names":[],"mappings":";;AAsBA,oDAKC;AAGD,0DA2CC;AApED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,oBAAoB,CAClC,KAAe,EACf,OAA6B;IAE7B,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AAChC,CAAC;AAED,gDAAgD;AAChD,SAAgB,uBAAuB,CACrC,KAAoB,EACpB,SAAkB;IAElB,OAAO,UAAU,WAAiC;;QAChD,MAAM,YAAY,GAAG,MAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,GAAG,mCAAI,SAAS,CAAC;QAEnD,OAAO,UAAU,GAAY,EAAE,GAAa,EAAE,IAAkB;YAC9D,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;gBACzB,IAAI,EAAE,CAAC;gBACP,OAAO;YACT,CAAC;YAED,IAAI,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,OAAO,EAAE,CAAC;gBACzB,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;gBACnC,IAAI,EAAE,CAAC;gBACP,OAAO;YACT,CAAC;YAED,MAAM,GAAG,GAAG,GAAG,CAAC,WAAW,CAAC;YAC5B,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAEjC,IAAI,MAAM,EAAE,CAAC;gBACX,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;gBAChC,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;gBAClD,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAChD,OAAO;YACT,CAAC;YAED,MAAM,YAAY,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAiC,CAAC;YAExE,GAAG,CAAC,IAAI,GAAG,UAAU,IAAc;;gBACjC,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC;oBAClD,MAAM,WAAW,GAAG,MAAC,GAAG,CAAC,SAAS,CAAC,cAAc,CAAY,mCAAI,0BAA0B,CAAC;oBAC5F,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,WAAW,EAAE,EAAE,YAAY,CAAC,CAAC;gBAClF,CAAC;gBACD,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;gBACjC,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC,CAAC;YAEF,IAAI,EAAE,CAAC;QACT,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,45 @@
1
+ import type { Memorize } from '../domain/Memorize';
2
+ type FetchHandler = (request: Request) => Promise<Response>;
3
+ export interface FetchAdapterOptions {
4
+ /** Time-to-live in milliseconds. Defaults to the global TTL. */
5
+ ttl?: number;
6
+ /** Skip caching. Sets `X-Cache: BYPASS`. */
7
+ noCache?: boolean;
8
+ /** Custom cache key extractor. Defaults to `pathname + search`. */
9
+ key?: (request: Request) => string;
10
+ }
11
+ /**
12
+ * Wraps a Fetch API handler with in-memory caching for `GET` requests with
13
+ * `2xx` responses.
14
+ *
15
+ * Works in any runtime that supports the Web-standard `Request` and `Response`
16
+ * APIs: Node.js, Bun, Deno, Cloudflare Workers, and similar environments.
17
+ *
18
+ * @param cache - The {@link Memorize} instance to use as the backing store.
19
+ * @param handler - The original fetch handler to wrap.
20
+ * @param options - Optional per-handler options.
21
+ *
22
+ * @example Serverless handler
23
+ * ```ts
24
+ * import { memorize } from 'express-memorize';
25
+ * import { cacheFetchHandler } from 'express-memorize/fetch';
26
+ *
27
+ * const cache = memorize({ ttl: 30_000 });
28
+ *
29
+ * export default cacheFetchHandler(cache, async (request) => {
30
+ * const users = await usersService.findAll();
31
+ * return Response.json(users);
32
+ * });
33
+ * ```
34
+ *
35
+ * @example With options
36
+ * ```ts
37
+ * const handler = cacheFetchHandler(cache, originalHandler, {
38
+ * ttl: 60_000,
39
+ * key: (req) => new URL(req.url).pathname,
40
+ * });
41
+ * ```
42
+ */
43
+ export declare function cacheFetchHandler(cache: Memorize, handler: FetchHandler, options?: FetchAdapterOptions): FetchHandler;
44
+ export {};
45
+ //# sourceMappingURL=fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/adapters/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,KAAK,YAAY,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE5D,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mEAAmE;IACnE,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,QAAQ,EACf,OAAO,EAAE,YAAY,EACrB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,YAAY,CAyCd"}
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cacheFetchHandler = cacheFetchHandler;
4
+ /**
5
+ * Wraps a Fetch API handler with in-memory caching for `GET` requests with
6
+ * `2xx` responses.
7
+ *
8
+ * Works in any runtime that supports the Web-standard `Request` and `Response`
9
+ * APIs: Node.js, Bun, Deno, Cloudflare Workers, and similar environments.
10
+ *
11
+ * @param cache - The {@link Memorize} instance to use as the backing store.
12
+ * @param handler - The original fetch handler to wrap.
13
+ * @param options - Optional per-handler options.
14
+ *
15
+ * @example Serverless handler
16
+ * ```ts
17
+ * import { memorize } from 'express-memorize';
18
+ * import { cacheFetchHandler } from 'express-memorize/fetch';
19
+ *
20
+ * const cache = memorize({ ttl: 30_000 });
21
+ *
22
+ * export default cacheFetchHandler(cache, async (request) => {
23
+ * const users = await usersService.findAll();
24
+ * return Response.json(users);
25
+ * });
26
+ * ```
27
+ *
28
+ * @example With options
29
+ * ```ts
30
+ * const handler = cacheFetchHandler(cache, originalHandler, {
31
+ * ttl: 60_000,
32
+ * key: (req) => new URL(req.url).pathname,
33
+ * });
34
+ * ```
35
+ */
36
+ function cacheFetchHandler(cache, handler, options) {
37
+ return async (request) => {
38
+ var _a;
39
+ if (request.method !== 'GET') {
40
+ return handler(request);
41
+ }
42
+ if (options === null || options === void 0 ? void 0 : options.noCache) {
43
+ const response = await handler(request);
44
+ const headers = new Headers(response.headers);
45
+ headers.set('X-Cache', 'BYPASS');
46
+ return new Response(response.body, { status: response.status, headers });
47
+ }
48
+ const { pathname, search } = new URL(request.url);
49
+ const key = (options === null || options === void 0 ? void 0 : options.key) ? options.key(request) : pathname + search;
50
+ const cached = cache._store.getRaw(key);
51
+ if (cached) {
52
+ return new Response(cached.body, {
53
+ status: cached.statusCode,
54
+ headers: {
55
+ 'Content-Type': cached.contentType,
56
+ 'X-Cache': 'HIT',
57
+ },
58
+ });
59
+ }
60
+ const response = await handler(request);
61
+ if (response.status >= 200 && response.status < 300) {
62
+ const body = await response.clone().text();
63
+ const contentType = (_a = response.headers.get('Content-Type')) !== null && _a !== void 0 ? _a : 'application/octet-stream';
64
+ cache._store.set(key, { body, statusCode: response.status, contentType }, options === null || options === void 0 ? void 0 : options.ttl);
65
+ const headers = new Headers(response.headers);
66
+ headers.set('X-Cache', 'MISS');
67
+ return new Response(body, { status: response.status, headers });
68
+ }
69
+ return response;
70
+ };
71
+ }
72
+ //# sourceMappingURL=fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/adapters/fetch.ts"],"names":[],"mappings":";;AA6CA,8CA6CC;AA7ED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,SAAgB,iBAAiB,CAC/B,KAAe,EACf,OAAqB,EACrB,OAA6B;IAE7B,OAAO,KAAK,EAAE,OAAgB,EAAqB,EAAE;;QACnD,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC7B,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC;QAED,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO,EAAE,CAAC;YACrB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;YACxC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC9C,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YACjC,OAAO,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3E,CAAC;QAED,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,GAAG,EAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,MAAM,CAAC;QACpE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAExC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAc,EAAE;gBACzC,MAAM,EAAE,MAAM,CAAC,UAAU;gBACzB,OAAO,EAAE;oBACP,cAAc,EAAE,MAAM,CAAC,WAAW;oBAClC,SAAS,EAAE,KAAK;iBACjB;aACF,CAAC,CAAC;QACL,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;QAExC,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YACpD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC;YAC3C,MAAM,WAAW,GAAG,MAAA,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,mCAAI,0BAA0B,CAAC;YACvF,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,GAAG,CAAC,CAAC;YAExF,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC9C,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAC/B,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { Context, MiddlewareHandler } from 'hono';
2
+ import type { Memorize } from '../domain/Memorize';
3
+ export interface HonoCallOptions {
4
+ /** Time-to-live in milliseconds. Defaults to the global TTL. */
5
+ ttl?: number;
6
+ /** Skip caching for this route. Sets `X-Cache: BYPASS`. */
7
+ noCache?: boolean;
8
+ /** Custom cache key extractor. Defaults to `c.req.url`. */
9
+ key?: (c: Context) => string;
10
+ }
11
+ /**
12
+ * Creates a Hono middleware that caches `GET` responses with a `2xx` status code.
13
+ *
14
+ * Requires `hono` to be installed as a peer dependency.
15
+ *
16
+ * @param cache - The {@link Memorize} instance to use as the backing store.
17
+ * @param options - Optional per-route options.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * import { Hono } from 'hono';
22
+ * import { memorize } from 'express-memorize';
23
+ * import { createHonoMiddleware } from 'express-memorize/hono';
24
+ *
25
+ * const app = new Hono();
26
+ * const cache = memorize({ ttl: 30_000 });
27
+ *
28
+ * app.get('/users', createHonoMiddleware(cache), async (c) => {
29
+ * return c.json(await usersService.findAll());
30
+ * });
31
+ * ```
32
+ */
33
+ export declare function createHonoMiddleware(cache: Memorize, options?: HonoCallOptions): MiddlewareHandler;
34
+ //# sourceMappingURL=hono.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../../src/adapters/hono.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAQ,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2DAA2D;IAC3D,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,iBAAiB,CA0ClG"}
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createHonoMiddleware = createHonoMiddleware;
4
+ /**
5
+ * Creates a Hono middleware that caches `GET` responses with a `2xx` status code.
6
+ *
7
+ * Requires `hono` to be installed as a peer dependency.
8
+ *
9
+ * @param cache - The {@link Memorize} instance to use as the backing store.
10
+ * @param options - Optional per-route options.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * import { Hono } from 'hono';
15
+ * import { memorize } from 'express-memorize';
16
+ * import { createHonoMiddleware } from 'express-memorize/hono';
17
+ *
18
+ * const app = new Hono();
19
+ * const cache = memorize({ ttl: 30_000 });
20
+ *
21
+ * app.get('/users', createHonoMiddleware(cache), async (c) => {
22
+ * return c.json(await usersService.findAll());
23
+ * });
24
+ * ```
25
+ */
26
+ function createHonoMiddleware(cache, options) {
27
+ return async (c, next) => {
28
+ var _a;
29
+ if (c.req.method !== 'GET') {
30
+ return next();
31
+ }
32
+ if (options === null || options === void 0 ? void 0 : options.noCache) {
33
+ await next();
34
+ const headers = new Headers(c.res.headers);
35
+ headers.set('X-Cache', 'BYPASS');
36
+ c.res = new Response(c.res.body, { status: c.res.status, headers });
37
+ return;
38
+ }
39
+ const { pathname, search } = new URL(c.req.url);
40
+ const key = (options === null || options === void 0 ? void 0 : options.key) ? options.key(c) : pathname + search;
41
+ const cached = cache._store.getRaw(key);
42
+ if (cached) {
43
+ return new Response(cached.body, {
44
+ status: cached.statusCode,
45
+ headers: {
46
+ 'Content-Type': cached.contentType,
47
+ 'X-Cache': 'HIT',
48
+ },
49
+ });
50
+ }
51
+ await next();
52
+ const { status } = c.res;
53
+ if (status >= 200 && status < 300) {
54
+ const body = await c.res.clone().text();
55
+ const contentType = (_a = c.res.headers.get('Content-Type')) !== null && _a !== void 0 ? _a : 'application/octet-stream';
56
+ cache._store.set(key, { body, statusCode: status, contentType }, options === null || options === void 0 ? void 0 : options.ttl);
57
+ const headers = new Headers(c.res.headers);
58
+ headers.set('X-Cache', 'MISS');
59
+ c.res = new Response(body, { status, headers });
60
+ }
61
+ };
62
+ }
63
+ //# sourceMappingURL=hono.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.js","sourceRoot":"","sources":["../../src/adapters/hono.ts"],"names":[],"mappings":";;AAkCA,oDA0CC;AAhED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,SAAgB,oBAAoB,CAAC,KAAe,EAAE,OAAyB;IAC7E,OAAO,KAAK,EAAE,CAAU,EAAE,IAAU,EAAE,EAAE;;QACtC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC3B,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QAED,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO,EAAE,CAAC;YACrB,MAAM,IAAI,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YACjC,CAAC,CAAC,GAAG,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;YACpE,OAAO;QACT,CAAC;QAED,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,GAAG,GAAG,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,GAAG,EAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,MAAM,CAAC;QAC9D,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAExC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAc,EAAE;gBACzC,MAAM,EAAE,MAAM,CAAC,UAAU;gBACzB,OAAO,EAAE;oBACP,cAAc,EAAE,MAAM,CAAC,WAAW;oBAClC,SAAS,EAAE,KAAK;iBACjB;aACF,CAAC,CAAC;QACL,CAAC;QAED,MAAM,IAAI,EAAE,CAAC;QAEb,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC;QAEzB,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;YAClC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,WAAW,GAAG,MAAA,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,mCAAI,0BAA0B,CAAC;YACpF,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,GAAG,CAAC,CAAC;YAE/E,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAC/B,CAAC,CAAC,GAAG,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QAClD,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,84 @@
1
+ import type { Memorize } from '../domain/Memorize';
2
+ import type { MemorizeOptions } from '../domain/MemorizeOptions';
3
+ export declare const MEMORIZE_CACHE: unique symbol;
4
+ export declare const MEMORIZE_MODULE_OPTIONS: unique symbol;
5
+ type MetadataTarget = object;
6
+ export interface MemorizeNestExecutionContext {
7
+ getClass(): MetadataTarget;
8
+ getHandler(): MetadataTarget;
9
+ switchToHttp(): {
10
+ getRequest(): MemorizeNestHttpRequest;
11
+ getResponse(): MemorizeNestHttpResponse;
12
+ };
13
+ }
14
+ export interface MemorizeNestCallHandler<T = unknown> {
15
+ handle(): MemorizeNestObservable<T>;
16
+ }
17
+ export interface MemorizeNestObservable<T = unknown> {
18
+ subscribe(observerOrNext?: Partial<ObserverLike<T>> | ((value: T) => void), error?: (error: unknown) => void, complete?: () => void): unknown;
19
+ }
20
+ interface ObserverLike<T = unknown> {
21
+ next(value: T): void;
22
+ error(error: unknown): void;
23
+ complete(): void;
24
+ }
25
+ export interface MemorizeNestHttpRequest {
26
+ method?: string;
27
+ originalUrl?: string;
28
+ url?: string;
29
+ }
30
+ export interface MemorizeNestHttpResponse {
31
+ statusCode?: number;
32
+ setHeader?: (name: string, value: string) => void;
33
+ header?: (name: string, value: string) => void;
34
+ headersSent?: boolean;
35
+ }
36
+ export interface MemorizeNestKeyContext {
37
+ context: MemorizeNestExecutionContext;
38
+ request: MemorizeNestHttpRequest;
39
+ }
40
+ export interface MemorizeNestOptions extends MemorizeOptions {
41
+ /**
42
+ * Custom request-based cache key generator. Defaults to
43
+ * `request.originalUrl ?? request.url`.
44
+ */
45
+ key?: (ctx: MemorizeNestKeyContext) => string;
46
+ }
47
+ interface DynamicModuleLike {
48
+ module: unknown;
49
+ providers: unknown[];
50
+ exports: unknown[];
51
+ global?: boolean;
52
+ }
53
+ /**
54
+ * Decorates a controller or handler with a fixed cache key.
55
+ */
56
+ export declare function MemorizeCacheKey(key: string): MethodDecorator & ClassDecorator;
57
+ /**
58
+ * Decorates a controller or handler with a TTL override in milliseconds.
59
+ */
60
+ export declare function MemorizeTtl(ttl: number): MethodDecorator & ClassDecorator;
61
+ /**
62
+ * Decorates a controller or handler so the interceptor bypasses cache reads and writes.
63
+ */
64
+ export declare function MemorizeNoCache(): MethodDecorator & ClassDecorator;
65
+ /**
66
+ * NestJS interceptor backed by a shared {@link Memorize} cache instance.
67
+ *
68
+ * Register through {@link MemorizeModule.forRoot} for dependency injection, or
69
+ * instantiate directly in tests and small applications.
70
+ */
71
+ export declare class MemorizeInterceptor {
72
+ private readonly cache;
73
+ private readonly options;
74
+ constructor(cache?: Memorize, options?: MemorizeNestOptions);
75
+ intercept(context: MemorizeNestExecutionContext, next: MemorizeNestCallHandler): MemorizeNestObservable<unknown>;
76
+ }
77
+ /**
78
+ * Dynamic Nest module that provides a shared cache and interceptor.
79
+ */
80
+ export declare class MemorizeModule {
81
+ static forRoot(options?: MemorizeNestOptions): DynamicModuleLike;
82
+ }
83
+ export {};
84
+ //# sourceMappingURL=nestjs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nestjs.d.ts","sourceRoot":"","sources":["../../src/adapters/nestjs.ts"],"names":[],"mappings":"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"}