express-memorize 1.0.0 → 1.2.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.
- package/CHANGELOG.md +45 -0
- package/LICENSE +21 -0
- package/README.md +201 -0
- package/dist/MemorizeStore.d.ts +70 -31
- package/dist/MemorizeStore.d.ts.map +1 -1
- package/dist/MemorizeStore.js +63 -10
- package/dist/MemorizeStore.js.map +1 -1
- package/dist/domain/CacheEntry.d.ts +14 -0
- package/dist/domain/CacheEntry.d.ts.map +1 -0
- package/dist/domain/CacheEntry.js +3 -0
- package/dist/domain/CacheEntry.js.map +1 -0
- package/dist/domain/CacheInfo.d.ts +12 -0
- package/dist/domain/CacheInfo.d.ts.map +1 -0
- package/dist/domain/CacheInfo.js +3 -0
- package/dist/domain/CacheInfo.js.map +1 -0
- package/dist/domain/Memorize.d.ts +123 -0
- package/dist/domain/Memorize.d.ts.map +1 -0
- package/dist/domain/Memorize.js +3 -0
- package/dist/domain/Memorize.js.map +1 -0
- package/dist/domain/MemorizeCallOptions.d.ts +18 -0
- package/dist/domain/MemorizeCallOptions.d.ts.map +1 -0
- package/dist/domain/MemorizeCallOptions.js +3 -0
- package/dist/domain/MemorizeCallOptions.js.map +1 -0
- package/dist/domain/MemorizeDeleteEvent.d.ts +18 -0
- package/dist/domain/MemorizeDeleteEvent.d.ts.map +1 -0
- package/dist/domain/MemorizeDeleteEvent.js +3 -0
- package/dist/domain/MemorizeDeleteEvent.js.map +1 -0
- package/dist/domain/MemorizeEmptyEvent.d.ts +16 -0
- package/dist/domain/MemorizeEmptyEvent.d.ts.map +1 -0
- package/dist/domain/MemorizeEmptyEvent.js +3 -0
- package/dist/domain/MemorizeEmptyEvent.js.map +1 -0
- package/dist/domain/MemorizeEvent.d.ts +7 -0
- package/dist/domain/MemorizeEvent.d.ts.map +1 -0
- package/dist/domain/MemorizeEvent.js +3 -0
- package/dist/domain/MemorizeEvent.js.map +1 -0
- package/dist/domain/MemorizeEventType.d.ts +22 -0
- package/dist/domain/MemorizeEventType.d.ts.map +1 -0
- package/dist/domain/MemorizeEventType.js +26 -0
- package/dist/domain/MemorizeEventType.js.map +1 -0
- package/dist/domain/MemorizeExpireEvent.d.ts +17 -0
- package/dist/domain/MemorizeExpireEvent.d.ts.map +1 -0
- package/dist/domain/MemorizeExpireEvent.js +3 -0
- package/dist/domain/MemorizeExpireEvent.js.map +1 -0
- package/dist/domain/MemorizeOptions.d.ts +16 -0
- package/dist/domain/MemorizeOptions.d.ts.map +1 -0
- package/dist/domain/MemorizeOptions.js +3 -0
- package/dist/domain/MemorizeOptions.js.map +1 -0
- package/dist/domain/MemorizeSetEvent.d.ts +25 -0
- package/dist/domain/MemorizeSetEvent.d.ts.map +1 -0
- package/dist/domain/MemorizeSetEvent.js +3 -0
- package/dist/domain/MemorizeSetEvent.js.map +1 -0
- package/dist/domain/index.d.ts +12 -0
- package/dist/domain/index.d.ts.map +1 -0
- package/dist/domain/index.js +6 -0
- package/dist/domain/index.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/memorize.d.ts +51 -18
- package/dist/memorize.d.ts.map +1 -1
- package/dist/memorize.js +51 -0
- package/dist/memorize.js.map +1 -1
- package/package.json +30 -6
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { RequestHandler } from 'express';
|
|
2
|
+
import { CacheInfo } from './CacheInfo';
|
|
3
|
+
import { MemorizeCallOptions } from './MemorizeCallOptions';
|
|
4
|
+
import { MemorizeEventType } from './MemorizeEventType';
|
|
5
|
+
import { MemorizeSetEvent } from './MemorizeSetEvent';
|
|
6
|
+
import { MemorizeDeleteEvent } from './MemorizeDeleteEvent';
|
|
7
|
+
import { MemorizeExpireEvent } from './MemorizeExpireEvent';
|
|
8
|
+
import { MemorizeEmptyEvent } from './MemorizeEmptyEvent';
|
|
9
|
+
/**
|
|
10
|
+
* The cache instance returned by {@link memorize}.
|
|
11
|
+
*
|
|
12
|
+
* It is both a callable that produces Express middleware **and** a namespace for
|
|
13
|
+
* cache management methods and event hooks. All middleware created from the same
|
|
14
|
+
* `Memorize` instance share a single underlying store.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const cache = memorize({ ttl: 30_000 });
|
|
19
|
+
*
|
|
20
|
+
* // Per-route middleware
|
|
21
|
+
* app.get('/users', cache(), handler);
|
|
22
|
+
*
|
|
23
|
+
* // Global middleware — caches every GET route automatically
|
|
24
|
+
* app.use(cache());
|
|
25
|
+
*
|
|
26
|
+
* // Cache management
|
|
27
|
+
* cache.delete('/users');
|
|
28
|
+
* cache.clear();
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export interface Memorize {
|
|
32
|
+
/**
|
|
33
|
+
* Returns an Express `RequestHandler` that caches `GET` responses with a `2xx`
|
|
34
|
+
* status code.
|
|
35
|
+
*
|
|
36
|
+
* - On a **cache miss** the request proceeds normally. The response is intercepted
|
|
37
|
+
* and stored after being sent. Sets `X-Cache: MISS`.
|
|
38
|
+
* - On a **cache hit** the stored response is returned immediately without calling
|
|
39
|
+
* downstream handlers. Sets `X-Cache: HIT`.
|
|
40
|
+
* - Non-`GET` requests are forwarded to `next()` unchanged.
|
|
41
|
+
*
|
|
42
|
+
* @param options - Optional per-route options (e.g. TTL override).
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* app.get('/users', cache(), handler); // global TTL
|
|
47
|
+
* app.get('/products', cache({ ttl: 5_000 }), handler); // 5-second override
|
|
48
|
+
* app.use(cache()); // global middleware
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
(options?: MemorizeCallOptions): RequestHandler;
|
|
52
|
+
/**
|
|
53
|
+
* Returns the {@link CacheInfo} for a specific cache key, or `null` if the key
|
|
54
|
+
* does not exist or has expired.
|
|
55
|
+
*
|
|
56
|
+
* @param key - The full request URL used as the cache key (e.g. `/users?page=1`).
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* const info = cache.get('/users');
|
|
61
|
+
* if (info) console.log(`expires in ${info.remainingTtl}ms`);
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
get(key: string): CacheInfo | null;
|
|
65
|
+
/**
|
|
66
|
+
* Returns all active (non-expired) cache entries as a plain object keyed by URL.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* console.log(Object.keys(cache.getAll())); // ['/users', '/products']
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
getAll(): Record<string, CacheInfo>;
|
|
74
|
+
/**
|
|
75
|
+
* Removes a single entry from the cache and emits a {@link MemorizeEventType.Delete} event.
|
|
76
|
+
*
|
|
77
|
+
* @param key - The full request URL to invalidate.
|
|
78
|
+
* @returns `true` if the entry existed and was removed, `false` otherwise.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* app.post('/users', (req, res) => {
|
|
83
|
+
* users.push(req.body);
|
|
84
|
+
* cache.delete('/users');
|
|
85
|
+
* res.status(201).json(req.body);
|
|
86
|
+
* });
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
delete(key: string): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Removes **all** entries from the cache and emits a {@link MemorizeEventType.Delete}
|
|
92
|
+
* event for each.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* cache.clear();
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
clear(): void;
|
|
100
|
+
/**
|
|
101
|
+
* Registers a listener for cache events.
|
|
102
|
+
*
|
|
103
|
+
* | Event | When |
|
|
104
|
+
* |-------|------|
|
|
105
|
+
* | `MemorizeEventType.Set` | A response is stored |
|
|
106
|
+
* | `MemorizeEventType.Delete` | An entry is removed via `delete()` or `clear()` |
|
|
107
|
+
* | `MemorizeEventType.Expire` | An entry's TTL elapses |
|
|
108
|
+
* | `MemorizeEventType.Empty` | The last entry is removed, cache is now empty |
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* cache.on(MemorizeEventType.Set, (e) => console.log('stored', e.key));
|
|
113
|
+
* cache.on(MemorizeEventType.Delete, (e) => console.log('deleted', e.key));
|
|
114
|
+
* cache.on(MemorizeEventType.Expire, (e) => console.log('expired', e.key));
|
|
115
|
+
* cache.on(MemorizeEventType.Empty, () => console.log('cache is empty'));
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
on(event: MemorizeEventType.Set, handler: (e: MemorizeSetEvent) => void): void;
|
|
119
|
+
on(event: MemorizeEventType.Delete, handler: (e: MemorizeDeleteEvent) => void): void;
|
|
120
|
+
on(event: MemorizeEventType.Expire, handler: (e: MemorizeExpireEvent) => void): void;
|
|
121
|
+
on(event: MemorizeEventType.Empty, handler: (e: MemorizeEmptyEvent) => void): void;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=Memorize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Memorize.d.ts","sourceRoot":"","sources":["../../src/domain/Memorize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,QAAQ;IACvB;;;;;;;;;;;;;;;;;;OAkBG;IACH,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,cAAc,CAAC;IAEhD;;;;;;;;;;;OAWG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAEnC;;;;;;;OAOG;IACH,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAEpC;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAE7B;;;;;;;;OAQG;IACH,KAAK,IAAI,IAAI,CAAC;IAEd;;;;;;;;;;;;;;;;;OAiBG;IACH,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,GAAG,EAAK,OAAO,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,IAAI,GAAG,IAAI,CAAC;IAClF,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,mBAAmB,KAAK,IAAI,GAAG,IAAI,CAAC;IACrF,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,mBAAmB,KAAK,IAAI,GAAG,IAAI,CAAC;IACrF,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,KAAK,EAAG,OAAO,EAAE,CAAC,CAAC,EAAE,kBAAkB,KAAK,IAAI,GAAG,IAAI,CAAC;CACrF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Memorize.js","sourceRoot":"","sources":["../../src/domain/Memorize.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options passed when invoking `cache()` to create a route-level middleware.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* // This route uses a 10-second TTL instead of the global 60-second TTL.
|
|
7
|
+
* app.get('/products', cache({ ttl: 10_000 }), handler);
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
export interface MemorizeCallOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Time-to-live override for this specific route, in milliseconds.
|
|
13
|
+
* Takes precedence over the global `ttl` set in {@link MemorizeOptions}.
|
|
14
|
+
* Pass `0` or omit to fall back to the global TTL.
|
|
15
|
+
*/
|
|
16
|
+
ttl?: number;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=MemorizeCallOptions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemorizeCallOptions.d.ts","sourceRoot":"","sources":["../../src/domain/MemorizeCallOptions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemorizeCallOptions.js","sourceRoot":"","sources":["../../src/domain/MemorizeCallOptions.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { MemorizeEventType } from './MemorizeEventType';
|
|
2
|
+
/**
|
|
3
|
+
* Emitted when a cache entry is manually removed via {@link Memorize.delete} or
|
|
4
|
+
* {@link Memorize.clear}.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* cache.on(MemorizeEventType.Delete, (e) => {
|
|
9
|
+
* console.log(`deleted ${e.key}`);
|
|
10
|
+
* });
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export interface MemorizeDeleteEvent {
|
|
14
|
+
type: MemorizeEventType.Delete;
|
|
15
|
+
/** The cache key that was removed. */
|
|
16
|
+
key: string;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=MemorizeDeleteEvent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemorizeDeleteEvent.d.ts","sourceRoot":"","sources":["../../src/domain/MemorizeDeleteEvent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC;IAC/B,sCAAsC;IACtC,GAAG,EAAE,MAAM,CAAC;CACb"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemorizeDeleteEvent.js","sourceRoot":"","sources":["../../src/domain/MemorizeDeleteEvent.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { MemorizeEventType } from './MemorizeEventType';
|
|
2
|
+
/**
|
|
3
|
+
* Emitted when the last entry is removed from the cache, leaving it empty.
|
|
4
|
+
* Triggered after a `delete` or `expire` eviction.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* cache.on(MemorizeEventType.Empty, () => {
|
|
9
|
+
* console.log('cache is now empty');
|
|
10
|
+
* });
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export interface MemorizeEmptyEvent {
|
|
14
|
+
type: MemorizeEventType.Empty;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=MemorizeEmptyEvent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemorizeEmptyEvent.d.ts","sourceRoot":"","sources":["../../src/domain/MemorizeEmptyEvent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,iBAAiB,CAAC,KAAK,CAAC;CAC/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemorizeEmptyEvent.js","sourceRoot":"","sources":["../../src/domain/MemorizeEmptyEvent.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { MemorizeSetEvent } from './MemorizeSetEvent';
|
|
2
|
+
import { MemorizeDeleteEvent } from './MemorizeDeleteEvent';
|
|
3
|
+
import { MemorizeExpireEvent } from './MemorizeExpireEvent';
|
|
4
|
+
import { MemorizeEmptyEvent } from './MemorizeEmptyEvent';
|
|
5
|
+
/** Union of all possible cache events. */
|
|
6
|
+
export type MemorizeEvent = MemorizeSetEvent | MemorizeDeleteEvent | MemorizeExpireEvent | MemorizeEmptyEvent;
|
|
7
|
+
//# sourceMappingURL=MemorizeEvent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemorizeEvent.d.ts","sourceRoot":"","sources":["../../src/domain/MemorizeEvent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,0CAA0C;AAC1C,MAAM,MAAM,aAAa,GACrB,gBAAgB,GAChB,mBAAmB,GACnB,mBAAmB,GACnB,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemorizeEvent.js","sourceRoot":"","sources":["../../src/domain/MemorizeEvent.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enum of all supported cache event types.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* cache.on(MemorizeEventType.Set, (e) => console.log('stored', e.key));
|
|
7
|
+
* cache.on(MemorizeEventType.Delete, (e) => console.log('deleted', e.key));
|
|
8
|
+
* cache.on(MemorizeEventType.Expire, (e) => console.log('expired', e.key));
|
|
9
|
+
* cache.on(MemorizeEventType.Empty, () => console.log('cache is empty'));
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export declare enum MemorizeEventType {
|
|
13
|
+
/** Fired when a response is stored in the cache. */
|
|
14
|
+
Set = "set",
|
|
15
|
+
/** Fired when an entry is manually removed via `delete()` or `clear()`. */
|
|
16
|
+
Delete = "delete",
|
|
17
|
+
/** Fired when an entry is automatically removed after its TTL elapses. */
|
|
18
|
+
Expire = "expire",
|
|
19
|
+
/** Fired when the last entry is removed, leaving the cache empty. */
|
|
20
|
+
Empty = "empty"
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=MemorizeEventType.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemorizeEventType.d.ts","sourceRoot":"","sources":["../../src/domain/MemorizeEventType.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,oBAAY,iBAAiB;IAC3B,oDAAoD;IACpD,GAAG,QAAQ;IACX,2EAA2E;IAC3E,MAAM,WAAW;IACjB,0EAA0E;IAC1E,MAAM,WAAW;IACjB,qEAAqE;IACrE,KAAK,UAAU;CAChB"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MemorizeEventType = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Enum of all supported cache event types.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* cache.on(MemorizeEventType.Set, (e) => console.log('stored', e.key));
|
|
10
|
+
* cache.on(MemorizeEventType.Delete, (e) => console.log('deleted', e.key));
|
|
11
|
+
* cache.on(MemorizeEventType.Expire, (e) => console.log('expired', e.key));
|
|
12
|
+
* cache.on(MemorizeEventType.Empty, () => console.log('cache is empty'));
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
var MemorizeEventType;
|
|
16
|
+
(function (MemorizeEventType) {
|
|
17
|
+
/** Fired when a response is stored in the cache. */
|
|
18
|
+
MemorizeEventType["Set"] = "set";
|
|
19
|
+
/** Fired when an entry is manually removed via `delete()` or `clear()`. */
|
|
20
|
+
MemorizeEventType["Delete"] = "delete";
|
|
21
|
+
/** Fired when an entry is automatically removed after its TTL elapses. */
|
|
22
|
+
MemorizeEventType["Expire"] = "expire";
|
|
23
|
+
/** Fired when the last entry is removed, leaving the cache empty. */
|
|
24
|
+
MemorizeEventType["Empty"] = "empty";
|
|
25
|
+
})(MemorizeEventType || (exports.MemorizeEventType = MemorizeEventType = {}));
|
|
26
|
+
//# sourceMappingURL=MemorizeEventType.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemorizeEventType.js","sourceRoot":"","sources":["../../src/domain/MemorizeEventType.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;GAUG;AACH,IAAY,iBASX;AATD,WAAY,iBAAiB;IAC3B,oDAAoD;IACpD,gCAAW,CAAA;IACX,2EAA2E;IAC3E,sCAAiB,CAAA;IACjB,0EAA0E;IAC1E,sCAAiB,CAAA;IACjB,qEAAqE;IACrE,oCAAe,CAAA;AACjB,CAAC,EATW,iBAAiB,iCAAjB,iBAAiB,QAS5B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { MemorizeEventType } from './MemorizeEventType';
|
|
2
|
+
/**
|
|
3
|
+
* Emitted when a cache entry is automatically removed after its TTL elapses.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* cache.on(MemorizeEventType.Expire, (e) => {
|
|
8
|
+
* console.log(`expired ${e.key}`);
|
|
9
|
+
* });
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export interface MemorizeExpireEvent {
|
|
13
|
+
type: MemorizeEventType.Expire;
|
|
14
|
+
/** The cache key that expired. */
|
|
15
|
+
key: string;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=MemorizeExpireEvent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemorizeExpireEvent.d.ts","sourceRoot":"","sources":["../../src/domain/MemorizeExpireEvent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;;;;;;GASG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC;IAC/B,kCAAkC;IAClC,GAAG,EAAE,MAAM,CAAC;CACb"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemorizeExpireEvent.js","sourceRoot":"","sources":["../../src/domain/MemorizeExpireEvent.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options passed to the {@link memorize} factory.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* const cache = memorize({ ttl: 60_000 }); // cache entries live for 60 seconds
|
|
7
|
+
* ```
|
|
8
|
+
*/
|
|
9
|
+
export interface MemorizeOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Default time-to-live for every cached entry, in milliseconds.
|
|
12
|
+
* Omit to cache indefinitely. Can be overridden per-route via {@link MemorizeCallOptions}.
|
|
13
|
+
*/
|
|
14
|
+
ttl?: number;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=MemorizeOptions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemorizeOptions.d.ts","sourceRoot":"","sources":["../../src/domain/MemorizeOptions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemorizeOptions.js","sourceRoot":"","sources":["../../src/domain/MemorizeOptions.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { MemorizeEventType } from './MemorizeEventType';
|
|
2
|
+
/**
|
|
3
|
+
* Emitted when a new response is stored in the cache.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* cache.on(MemorizeEventType.Set, (e) => {
|
|
8
|
+
* console.log(`stored ${e.key} — status ${e.statusCode}`);
|
|
9
|
+
* });
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export interface MemorizeSetEvent {
|
|
13
|
+
type: MemorizeEventType.Set;
|
|
14
|
+
/** The cache key (full request URL). */
|
|
15
|
+
key: string;
|
|
16
|
+
/** The stored response body. */
|
|
17
|
+
body: unknown;
|
|
18
|
+
/** HTTP status code of the stored response. */
|
|
19
|
+
statusCode: number;
|
|
20
|
+
/** `Content-Type` header value of the stored response. */
|
|
21
|
+
contentType: string;
|
|
22
|
+
/** Expiry timestamp in ms, or `null` if no TTL was set. */
|
|
23
|
+
expiresAt: number | null;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=MemorizeSetEvent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemorizeSetEvent.d.ts","sourceRoot":"","sources":["../../src/domain/MemorizeSetEvent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,iBAAiB,CAAC,GAAG,CAAC;IAC5B,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,gCAAgC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemorizeSetEvent.js","sourceRoot":"","sources":["../../src/domain/MemorizeSetEvent.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type { CacheEntry } from './CacheEntry';
|
|
2
|
+
export type { CacheInfo } from './CacheInfo';
|
|
3
|
+
export { MemorizeEventType } from './MemorizeEventType';
|
|
4
|
+
export type { MemorizeEvent } from './MemorizeEvent';
|
|
5
|
+
export type { MemorizeSetEvent } from './MemorizeSetEvent';
|
|
6
|
+
export type { MemorizeDeleteEvent } from './MemorizeDeleteEvent';
|
|
7
|
+
export type { MemorizeExpireEvent } from './MemorizeExpireEvent';
|
|
8
|
+
export type { MemorizeEmptyEvent } from './MemorizeEmptyEvent';
|
|
9
|
+
export type { MemorizeOptions } from './MemorizeOptions';
|
|
10
|
+
export type { MemorizeCallOptions } from './MemorizeCallOptions';
|
|
11
|
+
export type { Memorize } from './Memorize';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,YAAY,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACjE,YAAY,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACjE,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,YAAY,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACjE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MemorizeEventType = void 0;
|
|
4
|
+
var MemorizeEventType_1 = require("./MemorizeEventType");
|
|
5
|
+
Object.defineProperty(exports, "MemorizeEventType", { enumerable: true, get: function () { return MemorizeEventType_1.MemorizeEventType; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":";;;AAEA,yDAAwD;AAA/C,sHAAA,iBAAiB,OAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { memorize } from './memorize';
|
|
2
|
-
export type { MemorizeOptions, MemorizeCallOptions
|
|
3
|
-
export
|
|
2
|
+
export type { Memorize, MemorizeOptions, MemorizeCallOptions } from './memorize';
|
|
3
|
+
export { MemorizeEventType } from './domain/MemorizeEventType';
|
|
4
|
+
export type { CacheEntry, CacheInfo, MemorizeEvent, MemorizeSetEvent, MemorizeDeleteEvent, MemorizeExpireEvent, MemorizeEmptyEvent, } from './domain/index';
|
|
4
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,YAAY,EACV,UAAU,EACV,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.memorize = void 0;
|
|
3
|
+
exports.MemorizeEventType = exports.memorize = void 0;
|
|
4
4
|
var memorize_1 = require("./memorize");
|
|
5
5
|
Object.defineProperty(exports, "memorize", { enumerable: true, get: function () { return memorize_1.memorize; } });
|
|
6
|
+
var MemorizeEventType_1 = require("./domain/MemorizeEventType");
|
|
7
|
+
Object.defineProperty(exports, "MemorizeEventType", { enumerable: true, get: function () { return MemorizeEventType_1.MemorizeEventType; } });
|
|
6
8
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,uCAAsC;AAA7B,oGAAA,QAAQ,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,uCAAsC;AAA7B,oGAAA,QAAQ,OAAA;AAEjB,gEAA+D;AAAtD,sHAAA,iBAAiB,OAAA"}
|
package/dist/memorize.d.ts
CHANGED
|
@@ -1,20 +1,53 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { Memorize } from './domain/Memorize';
|
|
2
|
+
import { MemorizeOptions } from './domain/MemorizeOptions';
|
|
3
|
+
import { MemorizeCallOptions } from './domain/MemorizeCallOptions';
|
|
4
|
+
export type { Memorize, MemorizeOptions, MemorizeCallOptions };
|
|
5
|
+
/**
|
|
6
|
+
* Creates an in-memory cache for an Express application.
|
|
7
|
+
*
|
|
8
|
+
* Returns a {@link Memorize} instance that can be used as per-route middleware,
|
|
9
|
+
* a global `app.use()` middleware, or a cache management API — all sharing the
|
|
10
|
+
* same underlying store.
|
|
11
|
+
*
|
|
12
|
+
* **Only `GET` requests are cached.** Responses are cached only when the HTTP
|
|
13
|
+
* status code is in the `2xx` range. The cache key is `req.originalUrl`, which
|
|
14
|
+
* includes the query string.
|
|
15
|
+
*
|
|
16
|
+
* @param options - Global configuration for the cache instance.
|
|
17
|
+
*
|
|
18
|
+
* @example Per-route middleware
|
|
19
|
+
* ```ts
|
|
20
|
+
* const cache = memorize({ ttl: 30_000 });
|
|
21
|
+
*
|
|
22
|
+
* app.get('/users', cache(), (req, res) => {
|
|
23
|
+
* res.json({ data: users });
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @example Global middleware
|
|
28
|
+
* ```ts
|
|
29
|
+
* const cache = memorize({ ttl: 60_000 });
|
|
30
|
+
* app.use(cache()); // caches all GET routes
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @example Cache invalidation
|
|
34
|
+
* ```ts
|
|
35
|
+
* const cache = memorize({ ttl: 30_000 });
|
|
36
|
+
*
|
|
37
|
+
* app.post('/users', (req, res) => {
|
|
38
|
+
* users.push(req.body);
|
|
39
|
+
* cache.delete('/users');
|
|
40
|
+
* res.status(201).json(req.body);
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @example Event hooks
|
|
45
|
+
* ```ts
|
|
46
|
+
* cache.on(MemorizeEventType.Set, (e) => console.log('stored', e.key));
|
|
47
|
+
* cache.on(MemorizeEventType.Delete, (e) => console.log('deleted', e.key));
|
|
48
|
+
* cache.on(MemorizeEventType.Expire, (e) => console.log('expired', e.key));
|
|
49
|
+
* cache.on(MemorizeEventType.Empty, () => console.log('cache is empty'));
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
19
52
|
export declare function memorize(options?: MemorizeOptions): Memorize;
|
|
20
53
|
//# sourceMappingURL=memorize.d.ts.map
|
package/dist/memorize.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memorize.d.ts","sourceRoot":"","sources":["../src/memorize.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"memorize.d.ts","sourceRoot":"","sources":["../src/memorize.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,mBAAmB,EAAE,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,wBAAgB,QAAQ,CAAC,OAAO,GAAE,eAAoB,GAAG,QAAQ,CA6ChE"}
|
package/dist/memorize.js
CHANGED
|
@@ -2,6 +2,53 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.memorize = memorize;
|
|
4
4
|
const MemorizeStore_1 = require("./MemorizeStore");
|
|
5
|
+
/**
|
|
6
|
+
* Creates an in-memory cache for an Express application.
|
|
7
|
+
*
|
|
8
|
+
* Returns a {@link Memorize} instance that can be used as per-route middleware,
|
|
9
|
+
* a global `app.use()` middleware, or a cache management API — all sharing the
|
|
10
|
+
* same underlying store.
|
|
11
|
+
*
|
|
12
|
+
* **Only `GET` requests are cached.** Responses are cached only when the HTTP
|
|
13
|
+
* status code is in the `2xx` range. The cache key is `req.originalUrl`, which
|
|
14
|
+
* includes the query string.
|
|
15
|
+
*
|
|
16
|
+
* @param options - Global configuration for the cache instance.
|
|
17
|
+
*
|
|
18
|
+
* @example Per-route middleware
|
|
19
|
+
* ```ts
|
|
20
|
+
* const cache = memorize({ ttl: 30_000 });
|
|
21
|
+
*
|
|
22
|
+
* app.get('/users', cache(), (req, res) => {
|
|
23
|
+
* res.json({ data: users });
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @example Global middleware
|
|
28
|
+
* ```ts
|
|
29
|
+
* const cache = memorize({ ttl: 60_000 });
|
|
30
|
+
* app.use(cache()); // caches all GET routes
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @example Cache invalidation
|
|
34
|
+
* ```ts
|
|
35
|
+
* const cache = memorize({ ttl: 30_000 });
|
|
36
|
+
*
|
|
37
|
+
* app.post('/users', (req, res) => {
|
|
38
|
+
* users.push(req.body);
|
|
39
|
+
* cache.delete('/users');
|
|
40
|
+
* res.status(201).json(req.body);
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @example Event hooks
|
|
45
|
+
* ```ts
|
|
46
|
+
* cache.on(MemorizeEventType.Set, (e) => console.log('stored', e.key));
|
|
47
|
+
* cache.on(MemorizeEventType.Delete, (e) => console.log('deleted', e.key));
|
|
48
|
+
* cache.on(MemorizeEventType.Expire, (e) => console.log('expired', e.key));
|
|
49
|
+
* cache.on(MemorizeEventType.Empty, () => console.log('cache is empty'));
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
5
52
|
function memorize(options = {}) {
|
|
6
53
|
const { ttl } = options;
|
|
7
54
|
const store = new MemorizeStore_1.MemorizeStore();
|
|
@@ -9,6 +56,10 @@ function memorize(options = {}) {
|
|
|
9
56
|
var _a;
|
|
10
57
|
const effectiveTtl = (_a = callOptions === null || callOptions === void 0 ? void 0 : callOptions.ttl) !== null && _a !== void 0 ? _a : ttl;
|
|
11
58
|
return function (req, res, next) {
|
|
59
|
+
if (req.method !== 'GET') {
|
|
60
|
+
next();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
12
63
|
const key = req.originalUrl;
|
|
13
64
|
const cached = store.getRaw(key);
|
|
14
65
|
if (cached) {
|
package/dist/memorize.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memorize.js","sourceRoot":"","sources":["../src/memorize.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"memorize.js","sourceRoot":"","sources":["../src/memorize.ts"],"names":[],"mappings":";;AAuDA,4BA6CC;AAnGD,mDAAgD;AAOhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,SAAgB,QAAQ,CAAC,UAA2B,EAAE;IACpD,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IACxB,MAAM,KAAK,GAAG,IAAI,6BAAa,EAAE,CAAC;IAElC,MAAM,KAAK,GAAG,UAAU,WAAiC;;QACvD,MAAM,YAAY,GAAG,MAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,GAAG,mCAAI,GAAG,CAAC;QAE7C,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,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,CAAa,CAAC;IAEd,KAAK,CAAC,GAAG,GAAM,CAAC,GAAW,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/C,KAAK,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;IACpC,KAAK,CAAC,MAAM,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAClD,KAAK,CAAC,KAAK,GAAI,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACnC,KAAK,CAAC,EAAE,GAAO,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAmB,CAAC;IAEtD,OAAO,KAAK,CAAC;AACf,CAAC"}
|