@hazeljs/cache 0.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,374 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const memory_strategy_1 = require("./strategies/memory.strategy");
13
+ const redis_strategy_1 = require("./strategies/redis.strategy");
14
+ const multi_tier_strategy_1 = require("./strategies/multi-tier.strategy");
15
+ const cache_service_1 = require("./cache.service");
16
+ const cache_decorator_1 = require("./decorators/cache.decorator");
17
+ describe('MemoryCacheStore', () => {
18
+ let store;
19
+ beforeEach(() => {
20
+ store = new memory_strategy_1.MemoryCacheStore(100); // Short cleanup interval for testing
21
+ });
22
+ afterEach(() => {
23
+ store.destroy();
24
+ });
25
+ describe('get and set', () => {
26
+ it('should set and get a value', async () => {
27
+ await store.set('key1', 'value1', 60);
28
+ const value = await store.get('key1');
29
+ expect(value).toBe('value1');
30
+ });
31
+ it('should return null for non-existent key', async () => {
32
+ const value = await store.get('nonexistent');
33
+ expect(value).toBeNull();
34
+ });
35
+ it('should handle complex objects', async () => {
36
+ const obj = { name: 'test', nested: { value: 123 } };
37
+ await store.set('obj', obj, 60);
38
+ const retrieved = await store.get('obj');
39
+ expect(retrieved).toEqual(obj);
40
+ });
41
+ });
42
+ describe('expiration', () => {
43
+ it('should expire entries after TTL', async () => {
44
+ await store.set('expire', 'value', 0.1); // 100ms
45
+ await new Promise((resolve) => setTimeout(resolve, 150));
46
+ const value = await store.get('expire');
47
+ expect(value).toBeNull();
48
+ });
49
+ it('should not return expired entries', async () => {
50
+ await store.set('key', 'value', 0.05); // 50ms
51
+ await new Promise((resolve) => setTimeout(resolve, 100));
52
+ const exists = await store.has('key');
53
+ expect(exists).toBe(false);
54
+ });
55
+ });
56
+ describe('tags', () => {
57
+ it('should set value with tags', async () => {
58
+ await store.setWithTags('user1', { name: 'John' }, 60, ['users', 'profiles']);
59
+ const value = await store.get('user1');
60
+ expect(value).toEqual({ name: 'John' });
61
+ });
62
+ it('should delete entries by tag', async () => {
63
+ await store.setWithTags('user1', { name: 'John' }, 60, ['users']);
64
+ await store.setWithTags('user2', { name: 'Jane' }, 60, ['users']);
65
+ await store.setWithTags('post1', { title: 'Post' }, 60, ['posts']);
66
+ await store.deleteByTag('users');
67
+ expect(await store.get('user1')).toBeNull();
68
+ expect(await store.get('user2')).toBeNull();
69
+ expect(await store.get('post1')).toEqual({ title: 'Post' });
70
+ });
71
+ });
72
+ describe('operations', () => {
73
+ it('should delete a key', async () => {
74
+ await store.set('key', 'value', 60);
75
+ await store.delete('key');
76
+ const value = await store.get('key');
77
+ expect(value).toBeNull();
78
+ });
79
+ it('should check if key exists', async () => {
80
+ await store.set('key', 'value', 60);
81
+ expect(await store.has('key')).toBe(true);
82
+ expect(await store.has('nonexistent')).toBe(false);
83
+ });
84
+ it('should clear all entries', async () => {
85
+ await store.set('key1', 'value1', 60);
86
+ await store.set('key2', 'value2', 60);
87
+ await store.clear();
88
+ expect(await store.get('key1')).toBeNull();
89
+ expect(await store.get('key2')).toBeNull();
90
+ });
91
+ it('should get keys by pattern', async () => {
92
+ await store.set('user:1', 'value1', 60);
93
+ await store.set('user:2', 'value2', 60);
94
+ await store.set('post:1', 'value3', 60);
95
+ const userKeys = await store.keys('user:*');
96
+ expect(userKeys).toHaveLength(2);
97
+ expect(userKeys).toContain('user:1');
98
+ expect(userKeys).toContain('user:2');
99
+ });
100
+ });
101
+ describe('statistics', () => {
102
+ it('should track hits and misses', async () => {
103
+ await store.set('key', 'value', 60);
104
+ await store.get('key'); // hit
105
+ await store.get('nonexistent'); // miss
106
+ await store.get('key'); // hit
107
+ const stats = await store.getStats();
108
+ expect(stats.hits).toBe(2);
109
+ expect(stats.misses).toBe(1);
110
+ expect(stats.hitRate).toBeGreaterThan(0);
111
+ });
112
+ it('should report cache size', async () => {
113
+ await store.set('key1', 'value1', 60);
114
+ await store.set('key2', 'value2', 60);
115
+ const stats = await store.getStats();
116
+ expect(stats.size).toBe(2);
117
+ });
118
+ it('should reset statistics', async () => {
119
+ await store.set('key', 'value', 60);
120
+ await store.get('key');
121
+ store.resetStats();
122
+ const stats = await store.getStats();
123
+ expect(stats.hits).toBe(0);
124
+ expect(stats.misses).toBe(0);
125
+ });
126
+ });
127
+ });
128
+ describe('RedisCacheStore', () => {
129
+ let store;
130
+ beforeEach(() => {
131
+ store = new redis_strategy_1.RedisCacheStore();
132
+ });
133
+ afterEach(async () => {
134
+ await store.disconnect();
135
+ });
136
+ it('should set and get a value', async () => {
137
+ await store.set('key1', 'value1', 60);
138
+ const value = await store.get('key1');
139
+ expect(value).toBe('value1');
140
+ });
141
+ it('should handle objects', async () => {
142
+ const obj = { name: 'test', value: 123 };
143
+ await store.set('obj', obj, 60);
144
+ const retrieved = await store.get('obj');
145
+ expect(retrieved).toEqual(obj);
146
+ });
147
+ it('should delete by tag', async () => {
148
+ await store.setWithTags('key1', 'value1', 60, ['tag1']);
149
+ await store.setWithTags('key2', 'value2', 60, ['tag1']);
150
+ await store.deleteByTag('tag1');
151
+ expect(await store.get('key1')).toBeNull();
152
+ expect(await store.get('key2')).toBeNull();
153
+ });
154
+ });
155
+ describe('MultiTierCacheStore', () => {
156
+ let store;
157
+ beforeEach(() => {
158
+ store = new multi_tier_strategy_1.MultiTierCacheStore();
159
+ });
160
+ afterEach(async () => {
161
+ await store.destroy();
162
+ });
163
+ it('should set and get from multi-tier cache', async () => {
164
+ await store.set('key', 'value', 60);
165
+ const value = await store.get('key');
166
+ expect(value).toBe('value');
167
+ });
168
+ it('should promote from L2 to L1', async () => {
169
+ await store.set('key', 'value', 60);
170
+ // Clear L1 to simulate L2-only scenario
171
+ const l1Stats = await store.getL1Stats();
172
+ // Get should promote to L1
173
+ await store.get('key');
174
+ const newL1Stats = await store.getL1Stats();
175
+ expect(newL1Stats.size).toBeGreaterThanOrEqual(l1Stats.size);
176
+ });
177
+ it('should delete from both tiers', async () => {
178
+ await store.set('key', 'value', 60);
179
+ await store.delete('key');
180
+ expect(await store.get('key')).toBeNull();
181
+ });
182
+ it('should get combined statistics', async () => {
183
+ await store.set('key1', 'value1', 60);
184
+ await store.set('key2', 'value2', 60);
185
+ await store.get('key1');
186
+ await store.get('nonexistent');
187
+ const stats = await store.getStats();
188
+ expect(stats.hits).toBeGreaterThan(0);
189
+ expect(stats.misses).toBeGreaterThan(0);
190
+ });
191
+ });
192
+ describe('CacheService', () => {
193
+ let service;
194
+ beforeEach(() => {
195
+ service = new cache_service_1.CacheService('memory');
196
+ });
197
+ describe('basic operations', () => {
198
+ it('should get and set values', async () => {
199
+ await service.set('key', 'value', 60);
200
+ const value = await service.get('key');
201
+ expect(value).toBe('value');
202
+ });
203
+ it('should delete values', async () => {
204
+ await service.set('key', 'value', 60);
205
+ await service.delete('key');
206
+ expect(await service.get('key')).toBeNull();
207
+ });
208
+ it('should clear all cache', async () => {
209
+ await service.set('key1', 'value1', 60);
210
+ await service.set('key2', 'value2', 60);
211
+ await service.clear();
212
+ expect(await service.get('key1')).toBeNull();
213
+ });
214
+ });
215
+ describe('cache-aside pattern', () => {
216
+ it('should get or set value', async () => {
217
+ let fetchCount = 0;
218
+ const fetcher = async () => {
219
+ fetchCount++;
220
+ return { data: 'fetched' };
221
+ };
222
+ const result1 = await service.getOrSet('key', fetcher, 60);
223
+ const result2 = await service.getOrSet('key', fetcher, 60);
224
+ expect(result1).toEqual({ data: 'fetched' });
225
+ expect(result2).toEqual({ data: 'fetched' });
226
+ expect(fetchCount).toBe(1); // Should only fetch once
227
+ });
228
+ });
229
+ describe('cache warming', () => {
230
+ it('should warm up cache', async () => {
231
+ await service.warmUp({
232
+ keys: ['key1', 'key2', 'key3'],
233
+ fetcher: async (key) => ({ key, data: `data-${key}` }),
234
+ ttl: 60,
235
+ });
236
+ expect(await service.get('key1')).toEqual({ key: 'key1', data: 'data-key1' });
237
+ expect(await service.get('key2')).toEqual({ key: 'key2', data: 'data-key2' });
238
+ expect(await service.get('key3')).toEqual({ key: 'key3', data: 'data-key3' });
239
+ });
240
+ });
241
+ describe('tags', () => {
242
+ it('should invalidate by tags', async () => {
243
+ await service.setWithTags('user1', { name: 'John' }, 60, ['users']);
244
+ await service.setWithTags('user2', { name: 'Jane' }, 60, ['users']);
245
+ await service.invalidateTags(['users']);
246
+ expect(await service.get('user1')).toBeNull();
247
+ expect(await service.get('user2')).toBeNull();
248
+ });
249
+ });
250
+ describe('statistics', () => {
251
+ it('should get cache statistics', async () => {
252
+ await service.set('key', 'value', 60);
253
+ await service.get('key');
254
+ const stats = await service.getStats();
255
+ expect(stats).toBeDefined();
256
+ expect(stats.hits).toBeGreaterThanOrEqual(0);
257
+ expect(stats.misses).toBeGreaterThanOrEqual(0);
258
+ });
259
+ });
260
+ });
261
+ describe('CacheManager', () => {
262
+ let manager;
263
+ beforeEach(() => {
264
+ manager = new cache_service_1.CacheManager();
265
+ });
266
+ it('should register and get cache', () => {
267
+ const cache = new cache_service_1.CacheService('memory');
268
+ manager.register('test', cache);
269
+ expect(manager.get('test')).toBe(cache);
270
+ });
271
+ it('should set default cache', () => {
272
+ const cache = new cache_service_1.CacheService('memory');
273
+ manager.register('default', cache, true);
274
+ expect(manager.get()).toBe(cache);
275
+ });
276
+ it('should get all caches', () => {
277
+ const cache1 = new cache_service_1.CacheService('memory');
278
+ const cache2 = new cache_service_1.CacheService('memory');
279
+ manager.register('cache1', cache1);
280
+ manager.register('cache2', cache2);
281
+ const all = manager.getAll();
282
+ expect(all.size).toBe(2);
283
+ });
284
+ it('should clear all caches', async () => {
285
+ const cache1 = new cache_service_1.CacheService('memory');
286
+ const cache2 = new cache_service_1.CacheService('memory');
287
+ manager.register('cache1', cache1);
288
+ manager.register('cache2', cache2);
289
+ await cache1.set('key', 'value', 60);
290
+ await cache2.set('key', 'value', 60);
291
+ await manager.clearAll();
292
+ expect(await cache1.get('key')).toBeNull();
293
+ expect(await cache2.get('key')).toBeNull();
294
+ });
295
+ });
296
+ describe('Cache Decorators', () => {
297
+ describe('@Cache', () => {
298
+ it('should store cache metadata', () => {
299
+ class TestClass {
300
+ testMethod() {
301
+ return 'test';
302
+ }
303
+ }
304
+ __decorate([
305
+ (0, cache_decorator_1.Cache)({ ttl: 120, strategy: 'memory' }),
306
+ __metadata("design:type", Function),
307
+ __metadata("design:paramtypes", []),
308
+ __metadata("design:returntype", void 0)
309
+ ], TestClass.prototype, "testMethod", null);
310
+ const instance = new TestClass();
311
+ const metadata = (0, cache_decorator_1.getCacheMetadata)(instance, 'testMethod');
312
+ expect(metadata).toBeDefined();
313
+ expect(metadata?.ttl).toBe(120);
314
+ expect(metadata?.strategy).toBe('memory');
315
+ });
316
+ });
317
+ describe('@CacheKey', () => {
318
+ it('should set cache key pattern', () => {
319
+ class TestClass {
320
+ testMethod() {
321
+ return 'test';
322
+ }
323
+ }
324
+ __decorate([
325
+ (0, cache_decorator_1.CacheKey)('user-{id}'),
326
+ (0, cache_decorator_1.Cache)(),
327
+ __metadata("design:type", Function),
328
+ __metadata("design:paramtypes", []),
329
+ __metadata("design:returntype", void 0)
330
+ ], TestClass.prototype, "testMethod", null);
331
+ const instance = new TestClass();
332
+ const metadata = (0, cache_decorator_1.getCacheMetadata)(instance, 'testMethod');
333
+ expect(metadata?.key).toBe('user-{id}');
334
+ });
335
+ });
336
+ describe('@CacheTTL', () => {
337
+ it('should set cache TTL', () => {
338
+ class TestClass {
339
+ testMethod() {
340
+ return 'test';
341
+ }
342
+ }
343
+ __decorate([
344
+ (0, cache_decorator_1.CacheTTL)(300),
345
+ (0, cache_decorator_1.Cache)(),
346
+ __metadata("design:type", Function),
347
+ __metadata("design:paramtypes", []),
348
+ __metadata("design:returntype", void 0)
349
+ ], TestClass.prototype, "testMethod", null);
350
+ const instance = new TestClass();
351
+ const metadata = (0, cache_decorator_1.getCacheMetadata)(instance, 'testMethod');
352
+ expect(metadata?.ttl).toBe(300);
353
+ });
354
+ });
355
+ describe('@CacheTags', () => {
356
+ it('should set cache tags', () => {
357
+ class TestClass {
358
+ testMethod() {
359
+ return 'test';
360
+ }
361
+ }
362
+ __decorate([
363
+ (0, cache_decorator_1.CacheTags)(['users', 'profiles']),
364
+ (0, cache_decorator_1.Cache)(),
365
+ __metadata("design:type", Function),
366
+ __metadata("design:paramtypes", []),
367
+ __metadata("design:returntype", void 0)
368
+ ], TestClass.prototype, "testMethod", null);
369
+ const instance = new TestClass();
370
+ const metadata = (0, cache_decorator_1.getCacheMetadata)(instance, 'testMethod');
371
+ expect(metadata?.tags).toEqual(['users', 'profiles']);
372
+ });
373
+ });
374
+ });
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Cache strategy types
3
+ */
4
+ export type CacheStrategy = 'memory' | 'redis' | 'multi-tier';
5
+ /**
6
+ * TTL strategy types
7
+ */
8
+ export type TTLStrategy = 'absolute' | 'sliding';
9
+ /**
10
+ * Cache options
11
+ */
12
+ export interface CacheOptions {
13
+ /**
14
+ * Cache strategy to use
15
+ * @default 'memory'
16
+ */
17
+ strategy?: CacheStrategy;
18
+ /**
19
+ * Time to live in seconds
20
+ * @default 3600
21
+ */
22
+ ttl?: number;
23
+ /**
24
+ * TTL strategy
25
+ * @default 'absolute'
26
+ */
27
+ ttlStrategy?: TTLStrategy;
28
+ /**
29
+ * Cache key pattern (supports placeholders like {id}, {userId})
30
+ */
31
+ key?: string;
32
+ /**
33
+ * Tags for group invalidation
34
+ */
35
+ tags?: string[];
36
+ /**
37
+ * Events that should invalidate this cache
38
+ */
39
+ invalidateOn?: string[];
40
+ /**
41
+ * Whether to cache null/undefined values
42
+ * @default false
43
+ */
44
+ cacheNull?: boolean;
45
+ /**
46
+ * Custom condition function to determine if value should be cached
47
+ */
48
+ condition?: (value: unknown) => boolean;
49
+ }
50
+ /**
51
+ * Cache entry metadata
52
+ */
53
+ export interface CacheEntry<T = unknown> {
54
+ /**
55
+ * Cached value
56
+ */
57
+ value: T;
58
+ /**
59
+ * Timestamp when cached
60
+ */
61
+ cachedAt: number;
62
+ /**
63
+ * Expiration timestamp
64
+ */
65
+ expiresAt: number;
66
+ /**
67
+ * Last accessed timestamp (for sliding TTL)
68
+ */
69
+ lastAccessedAt?: number;
70
+ /**
71
+ * Cache tags
72
+ */
73
+ tags?: string[];
74
+ /**
75
+ * Cache key
76
+ */
77
+ key: string;
78
+ }
79
+ /**
80
+ * Cache statistics
81
+ */
82
+ export interface CacheStats {
83
+ /**
84
+ * Total number of cache hits
85
+ */
86
+ hits: number;
87
+ /**
88
+ * Total number of cache misses
89
+ */
90
+ misses: number;
91
+ /**
92
+ * Hit rate percentage
93
+ */
94
+ hitRate: number;
95
+ /**
96
+ * Total number of cached entries
97
+ */
98
+ size: number;
99
+ /**
100
+ * Total memory used (in bytes, if applicable)
101
+ */
102
+ memoryUsage?: number;
103
+ }
104
+ /**
105
+ * Cache store interface
106
+ */
107
+ export interface ICacheStore {
108
+ /**
109
+ * Get a value from cache
110
+ */
111
+ get<T>(key: string): Promise<T | null>;
112
+ /**
113
+ * Set a value in cache
114
+ */
115
+ set<T>(key: string, value: T, ttl?: number): Promise<void>;
116
+ /**
117
+ * Delete a value from cache
118
+ */
119
+ delete(key: string): Promise<void>;
120
+ /**
121
+ * Check if key exists in cache
122
+ */
123
+ has(key: string): Promise<boolean>;
124
+ /**
125
+ * Clear all cache entries
126
+ */
127
+ clear(): Promise<void>;
128
+ /**
129
+ * Get all keys matching a pattern
130
+ */
131
+ keys(pattern?: string): Promise<string[]>;
132
+ /**
133
+ * Get cache statistics
134
+ */
135
+ getStats(): Promise<CacheStats>;
136
+ }
137
+ /**
138
+ * Cache warming options
139
+ */
140
+ export interface CacheWarmingOptions {
141
+ /**
142
+ * Keys to warm up
143
+ */
144
+ keys: string[];
145
+ /**
146
+ * Function to fetch data for warming
147
+ */
148
+ fetcher: (key: string) => Promise<unknown>;
149
+ /**
150
+ * TTL for warmed entries
151
+ */
152
+ ttl?: number;
153
+ /**
154
+ * Whether to warm in parallel
155
+ * @default true
156
+ */
157
+ parallel?: boolean;
158
+ }
159
+ /**
160
+ * Cache invalidation event
161
+ */
162
+ export interface CacheInvalidationEvent {
163
+ /**
164
+ * Event name
165
+ */
166
+ event: string;
167
+ /**
168
+ * Keys to invalidate
169
+ */
170
+ keys?: string[];
171
+ /**
172
+ * Tags to invalidate
173
+ */
174
+ tags?: string[];
175
+ /**
176
+ * Timestamp
177
+ */
178
+ timestamp: number;
179
+ }
180
+ //# sourceMappingURL=cache.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.types.d.ts","sourceRoot":"","sources":["../src/cache.types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,aAAa,CAAC;IAEzB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAE1B;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CACzC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC,GAAG,OAAO;IACrC;;OAEG;IACH,KAAK,EAAE,CAAC,CAAC;IAET;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAEvC;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3D;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEnC;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;OAEG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE1C;;OAEG;IACH,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,IAAI,EAAE,MAAM,EAAE,CAAC;IAEf;;OAEG;IACH,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAE3C;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,93 @@
1
+ import 'reflect-metadata';
2
+ import { CacheOptions } from '../cache.types';
3
+ /**
4
+ * Cache decorator for methods
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * @Cache({
9
+ * strategy: 'memory',
10
+ * ttl: 3600,
11
+ * key: 'user-{id}',
12
+ * tags: ['users']
13
+ * })
14
+ * @Get('/users/:id')
15
+ * async getUser(@Param('id') id: string) {
16
+ * return this.userService.findById(id);
17
+ * }
18
+ * ```
19
+ */
20
+ export declare function Cache(options?: CacheOptions): MethodDecorator;
21
+ /**
22
+ * Get cache metadata from a method
23
+ */
24
+ export declare function getCacheMetadata(target: object, propertyKey: string | symbol): CacheOptions | undefined;
25
+ /**
26
+ * Check if a method has cache metadata
27
+ */
28
+ export declare function hasCacheMetadata(target: object, propertyKey: string | symbol): boolean;
29
+ /**
30
+ * CacheKey decorator to specify custom cache key generation
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * @CacheKey('user-{id}-{role}')
35
+ * @Get('/users/:id')
36
+ * async getUser(@Param('id') id: string, @Query('role') role: string) {
37
+ * return this.userService.findById(id);
38
+ * }
39
+ * ```
40
+ */
41
+ export declare function CacheKey(keyPattern: string): MethodDecorator;
42
+ /**
43
+ * CacheTTL decorator to specify cache TTL
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * @CacheTTL(7200) // 2 hours
48
+ * @Get('/users')
49
+ * async getUsers() {
50
+ * return this.userService.findAll();
51
+ * }
52
+ * ```
53
+ */
54
+ export declare function CacheTTL(ttl: number): MethodDecorator;
55
+ /**
56
+ * CacheTags decorator to specify cache tags
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * @CacheTags(['users', 'profiles'])
61
+ * @Get('/users/:id/profile')
62
+ * async getUserProfile(@Param('id') id: string) {
63
+ * return this.userService.getProfile(id);
64
+ * }
65
+ * ```
66
+ */
67
+ export declare function CacheTags(tags: string[]): MethodDecorator;
68
+ /**
69
+ * CacheEvict decorator to evict cache entries
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * @CacheEvict({ tags: ['users'] })
74
+ * @Post('/users')
75
+ * async createUser(@Body() user: CreateUserDto) {
76
+ * return this.userService.create(user);
77
+ * }
78
+ * ```
79
+ */
80
+ export declare function CacheEvict(options: {
81
+ keys?: string[];
82
+ tags?: string[];
83
+ all?: boolean;
84
+ }): MethodDecorator;
85
+ /**
86
+ * Get cache evict metadata
87
+ */
88
+ export declare function getCacheEvictMetadata(target: object, propertyKey: string | symbol): {
89
+ keys?: string[];
90
+ tags?: string[];
91
+ all?: boolean;
92
+ } | undefined;
93
+ //# sourceMappingURL=cache.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/cache.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAK9C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,eAAe,CAoBjE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,MAAM,GAC3B,YAAY,GAAG,SAAS,CAE1B;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAEtF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAY5D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAYrD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,eAAe,CAYzD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE;IAClC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,GAAG,eAAe,CAMlB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,MAAM,GAC3B;IAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAEjE"}