@carno.js/core 1.1.1 → 1.1.2

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 (119) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +188 -188
  3. package/dist/Carno.js +46 -26
  4. package/dist/Carno.mjs +46 -26
  5. package/dist/bun/index.js +4 -4
  6. package/dist/bun/index.js.map +29 -29
  7. package/package.json +2 -2
  8. package/src/Carno.ts +718 -673
  9. package/src/DefaultRoutes.ts +34 -34
  10. package/src/cache/CacheDriver.ts +50 -50
  11. package/src/cache/CacheService.ts +139 -139
  12. package/src/cache/MemoryDriver.ts +104 -104
  13. package/src/cache/RedisDriver.ts +116 -116
  14. package/src/compiler/JITCompiler.ts +167 -167
  15. package/src/container/Container.ts +168 -168
  16. package/src/context/Context.ts +130 -130
  17. package/src/cors/CorsHandler.ts +145 -145
  18. package/src/decorators/Controller.ts +63 -63
  19. package/src/decorators/Inject.ts +16 -16
  20. package/src/decorators/Middleware.ts +22 -22
  21. package/src/decorators/Service.ts +18 -18
  22. package/src/decorators/methods.ts +58 -58
  23. package/src/decorators/params.ts +47 -47
  24. package/src/events/Lifecycle.ts +97 -97
  25. package/src/exceptions/HttpException.ts +99 -99
  26. package/src/index.ts +95 -95
  27. package/src/metadata.ts +46 -46
  28. package/src/middleware/CarnoMiddleware.ts +14 -14
  29. package/src/router/RadixRouter.ts +225 -225
  30. package/src/testing/TestHarness.ts +185 -185
  31. package/src/utils/Metadata.ts +43 -43
  32. package/src/utils/parseQuery.ts +161 -161
  33. package/src/validation/ValibotAdapter.ts +95 -95
  34. package/src/validation/ValidatorAdapter.ts +69 -69
  35. package/src/validation/ZodAdapter.ts +102 -102
  36. package/dist/Carno.d.js +0 -14
  37. package/dist/Carno.d.mjs +0 -1
  38. package/dist/DefaultRoutes.d.js +0 -13
  39. package/dist/DefaultRoutes.d.mjs +0 -0
  40. package/dist/cache/CacheDriver.d.js +0 -13
  41. package/dist/cache/CacheDriver.d.mjs +0 -0
  42. package/dist/cache/CacheService.d.js +0 -13
  43. package/dist/cache/CacheService.d.mjs +0 -0
  44. package/dist/cache/MemoryDriver.d.js +0 -13
  45. package/dist/cache/MemoryDriver.d.mjs +0 -0
  46. package/dist/cache/RedisDriver.d.js +0 -13
  47. package/dist/cache/RedisDriver.d.mjs +0 -0
  48. package/dist/compiler/JITCompiler.d.js +0 -13
  49. package/dist/compiler/JITCompiler.d.mjs +0 -0
  50. package/dist/container/Container.d.js +0 -13
  51. package/dist/container/Container.d.mjs +0 -0
  52. package/dist/context/Context.d.js +0 -13
  53. package/dist/context/Context.d.mjs +0 -0
  54. package/dist/cors/CorsHandler.d.js +0 -13
  55. package/dist/cors/CorsHandler.d.mjs +0 -0
  56. package/dist/decorators/Controller.d.js +0 -13
  57. package/dist/decorators/Controller.d.mjs +0 -0
  58. package/dist/decorators/Inject.d.js +0 -13
  59. package/dist/decorators/Inject.d.mjs +0 -0
  60. package/dist/decorators/Middleware.d.js +0 -13
  61. package/dist/decorators/Middleware.d.mjs +0 -0
  62. package/dist/decorators/Service.d.js +0 -13
  63. package/dist/decorators/Service.d.mjs +0 -0
  64. package/dist/decorators/methods.d.js +0 -13
  65. package/dist/decorators/methods.d.mjs +0 -0
  66. package/dist/decorators/params.d.js +0 -13
  67. package/dist/decorators/params.d.mjs +0 -0
  68. package/dist/events/Lifecycle.d.js +0 -13
  69. package/dist/events/Lifecycle.d.mjs +0 -0
  70. package/dist/exceptions/HttpException.d.js +0 -13
  71. package/dist/exceptions/HttpException.d.mjs +0 -0
  72. package/dist/index.d.js +0 -130
  73. package/dist/index.d.mjs +0 -78
  74. package/dist/metadata.d.js +0 -13
  75. package/dist/metadata.d.mjs +0 -0
  76. package/dist/middleware/CarnoMiddleware.d.js +0 -13
  77. package/dist/middleware/CarnoMiddleware.d.mjs +0 -0
  78. package/dist/router/RadixRouter.d.js +0 -13
  79. package/dist/router/RadixRouter.d.mjs +0 -0
  80. package/dist/testing/TestHarness.d.js +0 -13
  81. package/dist/testing/TestHarness.d.mjs +0 -0
  82. package/dist/utils/Metadata.d.js +0 -13
  83. package/dist/utils/Metadata.d.mjs +0 -0
  84. package/dist/utils/parseQuery.d.js +0 -13
  85. package/dist/utils/parseQuery.d.mjs +0 -0
  86. package/dist/validation/ValibotAdapter.d.js +0 -13
  87. package/dist/validation/ValibotAdapter.d.mjs +0 -0
  88. package/dist/validation/ValidatorAdapter.d.js +0 -13
  89. package/dist/validation/ValidatorAdapter.d.mjs +0 -0
  90. package/dist/validation/ZodAdapter.d.js +0 -13
  91. package/dist/validation/ZodAdapter.d.mjs +0 -0
  92. package/src/Carno.d.ts +0 -135
  93. package/src/DefaultRoutes.d.ts +0 -19
  94. package/src/cache/CacheDriver.d.ts +0 -43
  95. package/src/cache/CacheService.d.ts +0 -89
  96. package/src/cache/MemoryDriver.d.ts +0 -32
  97. package/src/cache/RedisDriver.d.ts +0 -34
  98. package/src/compiler/JITCompiler.d.ts +0 -36
  99. package/src/container/Container.d.ts +0 -38
  100. package/src/context/Context.d.ts +0 -36
  101. package/src/cors/CorsHandler.d.ts +0 -47
  102. package/src/decorators/Controller.d.ts +0 -13
  103. package/src/decorators/Inject.d.ts +0 -6
  104. package/src/decorators/Middleware.d.ts +0 -5
  105. package/src/decorators/Service.d.ts +0 -9
  106. package/src/decorators/methods.d.ts +0 -7
  107. package/src/decorators/params.d.ts +0 -13
  108. package/src/events/Lifecycle.d.ts +0 -54
  109. package/src/exceptions/HttpException.d.ts +0 -43
  110. package/src/index.d.ts +0 -42
  111. package/src/metadata.d.ts +0 -41
  112. package/src/middleware/CarnoMiddleware.d.ts +0 -12
  113. package/src/router/RadixRouter.d.ts +0 -19
  114. package/src/testing/TestHarness.d.ts +0 -71
  115. package/src/utils/Metadata.d.ts +0 -20
  116. package/src/utils/parseQuery.d.ts +0 -23
  117. package/src/validation/ValibotAdapter.d.ts +0 -30
  118. package/src/validation/ValidatorAdapter.d.ts +0 -54
  119. package/src/validation/ZodAdapter.d.ts +0 -35
@@ -1,34 +1,34 @@
1
- import { Controller } from './decorators/Controller';
2
- import { Get } from './decorators/methods';
3
-
4
- /**
5
- * Default routes controller.
6
- * Auto-registered by Turbo for common endpoints.
7
- */
8
- @Controller()
9
- export class DefaultRoutes {
10
-
11
- /**
12
- * Favicon - returns empty response to prevent 404.
13
- */
14
- @Get('/favicon.ico')
15
- favicon() {
16
- return new Response(null, { status: 204 });
17
- }
18
- }
19
-
20
- /**
21
- * Pre-compiled static responses for maximum performance.
22
- * Use these directly in Bun.serve static routes.
23
- */
24
- export const DEFAULT_STATIC_ROUTES = {
25
- '/health': new Response('{"status":"ok"}', {
26
- status: 200,
27
- headers: { 'Content-Type': 'application/json' }
28
- }),
29
- '/ready': new Response('{"ready":true}', {
30
- status: 200,
31
- headers: { 'Content-Type': 'application/json' }
32
- }),
33
- '/favicon.ico': new Response(null, { status: 204 })
34
- };
1
+ import { Controller } from './decorators/Controller';
2
+ import { Get } from './decorators/methods';
3
+
4
+ /**
5
+ * Default routes controller.
6
+ * Auto-registered by Turbo for common endpoints.
7
+ */
8
+ @Controller()
9
+ export class DefaultRoutes {
10
+
11
+ /**
12
+ * Favicon - returns empty response to prevent 404.
13
+ */
14
+ @Get('/favicon.ico')
15
+ favicon() {
16
+ return new Response(null, { status: 204 });
17
+ }
18
+ }
19
+
20
+ /**
21
+ * Pre-compiled static responses for maximum performance.
22
+ * Use these directly in Bun.serve static routes.
23
+ */
24
+ export const DEFAULT_STATIC_ROUTES = {
25
+ '/health': new Response('{"status":"ok"}', {
26
+ status: 200,
27
+ headers: { 'Content-Type': 'application/json' }
28
+ }),
29
+ '/ready': new Response('{"ready":true}', {
30
+ status: 200,
31
+ headers: { 'Content-Type': 'application/json' }
32
+ }),
33
+ '/favicon.ico': new Response(null, { status: 204 })
34
+ };
@@ -1,50 +1,50 @@
1
- /**
2
- * Cache Driver Interface.
3
- * Implement this to add new cache backends (Redis, Memcached, etc.)
4
- */
5
- export interface CacheDriver {
6
- /**
7
- * Driver name for debugging.
8
- */
9
- readonly name: string;
10
-
11
- /**
12
- * Get a value from cache.
13
- */
14
- get<T>(key: string): Promise<T | null>;
15
-
16
- /**
17
- * Set a value in cache.
18
- * @param ttl Time to live in seconds (optional)
19
- */
20
- set<T>(key: string, value: T, ttl?: number): Promise<boolean>;
21
-
22
- /**
23
- * Delete a value from cache.
24
- */
25
- del(key: string): Promise<boolean>;
26
-
27
- /**
28
- * Check if key exists.
29
- */
30
- has(key: string): Promise<boolean>;
31
-
32
- /**
33
- * Clear all cached values.
34
- */
35
- clear(): Promise<void>;
36
-
37
- /**
38
- * Close connection (for Redis, etc.)
39
- */
40
- close?(): Promise<void>;
41
- }
42
-
43
- /**
44
- * Cache configuration.
45
- */
46
- export interface CacheConfig {
47
- driver?: CacheDriver;
48
- prefix?: string;
49
- defaultTtl?: number;
50
- }
1
+ /**
2
+ * Cache Driver Interface.
3
+ * Implement this to add new cache backends (Redis, Memcached, etc.)
4
+ */
5
+ export interface CacheDriver {
6
+ /**
7
+ * Driver name for debugging.
8
+ */
9
+ readonly name: string;
10
+
11
+ /**
12
+ * Get a value from cache.
13
+ */
14
+ get<T>(key: string): Promise<T | null>;
15
+
16
+ /**
17
+ * Set a value in cache.
18
+ * @param ttl Time to live in seconds (optional)
19
+ */
20
+ set<T>(key: string, value: T, ttl?: number): Promise<boolean>;
21
+
22
+ /**
23
+ * Delete a value from cache.
24
+ */
25
+ del(key: string): Promise<boolean>;
26
+
27
+ /**
28
+ * Check if key exists.
29
+ */
30
+ has(key: string): Promise<boolean>;
31
+
32
+ /**
33
+ * Clear all cached values.
34
+ */
35
+ clear(): Promise<void>;
36
+
37
+ /**
38
+ * Close connection (for Redis, etc.)
39
+ */
40
+ close?(): Promise<void>;
41
+ }
42
+
43
+ /**
44
+ * Cache configuration.
45
+ */
46
+ export interface CacheConfig {
47
+ driver?: CacheDriver;
48
+ prefix?: string;
49
+ defaultTtl?: number;
50
+ }
@@ -1,139 +1,139 @@
1
- import type { CacheDriver, CacheConfig } from './CacheDriver';
2
- import { MemoryDriver } from './MemoryDriver';
3
-
4
- /**
5
- * CacheService - High-performance caching with driver pattern.
6
- *
7
- * Features:
8
- * - In-memory (default) or Redis backend
9
- * - getOrSet for cache-aside pattern
10
- * - Key prefixing for namespacing
11
- * - Configurable default TTL
12
- *
13
- * Usage:
14
- * ```typescript
15
- * const cache = new CacheService();
16
- *
17
- * // Basic operations
18
- * await cache.set('user:123', { name: 'John' }, 3600);
19
- * const user = await cache.get<User>('user:123');
20
- *
21
- * // Cache-aside pattern
22
- * const user = await cache.getOrSet('user:123',
23
- * async () => db.findUser(123),
24
- * 3600
25
- * );
26
- * ```
27
- */
28
- export class CacheService {
29
- private driver: CacheDriver;
30
- private prefix: string;
31
- private defaultTtl: number | undefined;
32
-
33
- constructor(config: CacheConfig = {}) {
34
- this.driver = config.driver || new MemoryDriver();
35
- this.prefix = config.prefix || '';
36
- this.defaultTtl = config.defaultTtl;
37
- }
38
-
39
- /**
40
- * Get the full key with prefix.
41
- */
42
- private key(key: string): string {
43
- return this.prefix ? `${this.prefix}:${key}` : key;
44
- }
45
-
46
- /**
47
- * Get a value from cache.
48
- */
49
- async get<T>(key: string): Promise<T | null> {
50
- return this.driver.get<T>(this.key(key));
51
- }
52
-
53
- /**
54
- * Set a value in cache.
55
- * @param ttl Time to live in seconds
56
- */
57
- async set<T>(key: string, value: T, ttl?: number): Promise<boolean> {
58
- return this.driver.set(this.key(key), value, ttl ?? this.defaultTtl);
59
- }
60
-
61
- /**
62
- * Delete a value from cache.
63
- */
64
- async del(key: string): Promise<boolean> {
65
- return this.driver.del(this.key(key));
66
- }
67
-
68
- /**
69
- * Check if key exists.
70
- */
71
- async has(key: string): Promise<boolean> {
72
- return this.driver.has(this.key(key));
73
- }
74
-
75
- /**
76
- * Clear all cached values.
77
- */
78
- async clear(): Promise<void> {
79
- return this.driver.clear();
80
- }
81
-
82
- /**
83
- * Get value from cache or compute and store it.
84
- * This is the cache-aside pattern - most commonly used method.
85
- *
86
- * @param key Cache key
87
- * @param cb Callback to compute value if not cached
88
- * @param ttl Time to live in seconds
89
- */
90
- async getOrSet<T>(key: string, cb: () => Promise<T>, ttl?: number): Promise<T> {
91
- const cached = await this.get<T>(key);
92
-
93
- if (cached !== null) {
94
- return cached;
95
- }
96
-
97
- const value = await cb();
98
- await this.set(key, value, ttl);
99
-
100
- return value;
101
- }
102
-
103
- /**
104
- * Get multiple values at once.
105
- */
106
- async getMany<T>(keys: string[]): Promise<(T | null)[]> {
107
- return Promise.all(keys.map(key => this.get<T>(key)));
108
- }
109
-
110
- /**
111
- * Set multiple values at once.
112
- */
113
- async setMany<T>(entries: Array<{ key: string; value: T; ttl?: number }>): Promise<boolean[]> {
114
- return Promise.all(
115
- entries.map(entry => this.set(entry.key, entry.value, entry.ttl))
116
- );
117
- }
118
-
119
- /**
120
- * Delete multiple values at once.
121
- */
122
- async delMany(keys: string[]): Promise<boolean[]> {
123
- return Promise.all(keys.map(key => this.del(key)));
124
- }
125
-
126
- /**
127
- * Close the cache driver connection.
128
- */
129
- async close(): Promise<void> {
130
- await this.driver.close?.();
131
- }
132
-
133
- /**
134
- * Get the underlying driver (for advanced use).
135
- */
136
- getDriver(): CacheDriver {
137
- return this.driver;
138
- }
139
- }
1
+ import type { CacheDriver, CacheConfig } from './CacheDriver';
2
+ import { MemoryDriver } from './MemoryDriver';
3
+
4
+ /**
5
+ * CacheService - High-performance caching with driver pattern.
6
+ *
7
+ * Features:
8
+ * - In-memory (default) or Redis backend
9
+ * - getOrSet for cache-aside pattern
10
+ * - Key prefixing for namespacing
11
+ * - Configurable default TTL
12
+ *
13
+ * Usage:
14
+ * ```typescript
15
+ * const cache = new CacheService();
16
+ *
17
+ * // Basic operations
18
+ * await cache.set('user:123', { name: 'John' }, 3600);
19
+ * const user = await cache.get<User>('user:123');
20
+ *
21
+ * // Cache-aside pattern
22
+ * const user = await cache.getOrSet('user:123',
23
+ * async () => db.findUser(123),
24
+ * 3600
25
+ * );
26
+ * ```
27
+ */
28
+ export class CacheService {
29
+ private driver: CacheDriver;
30
+ private prefix: string;
31
+ private defaultTtl: number | undefined;
32
+
33
+ constructor(config: CacheConfig = {}) {
34
+ this.driver = config.driver || new MemoryDriver();
35
+ this.prefix = config.prefix || '';
36
+ this.defaultTtl = config.defaultTtl;
37
+ }
38
+
39
+ /**
40
+ * Get the full key with prefix.
41
+ */
42
+ private key(key: string): string {
43
+ return this.prefix ? `${this.prefix}:${key}` : key;
44
+ }
45
+
46
+ /**
47
+ * Get a value from cache.
48
+ */
49
+ async get<T>(key: string): Promise<T | null> {
50
+ return this.driver.get<T>(this.key(key));
51
+ }
52
+
53
+ /**
54
+ * Set a value in cache.
55
+ * @param ttl Time to live in seconds
56
+ */
57
+ async set<T>(key: string, value: T, ttl?: number): Promise<boolean> {
58
+ return this.driver.set(this.key(key), value, ttl ?? this.defaultTtl);
59
+ }
60
+
61
+ /**
62
+ * Delete a value from cache.
63
+ */
64
+ async del(key: string): Promise<boolean> {
65
+ return this.driver.del(this.key(key));
66
+ }
67
+
68
+ /**
69
+ * Check if key exists.
70
+ */
71
+ async has(key: string): Promise<boolean> {
72
+ return this.driver.has(this.key(key));
73
+ }
74
+
75
+ /**
76
+ * Clear all cached values.
77
+ */
78
+ async clear(): Promise<void> {
79
+ return this.driver.clear();
80
+ }
81
+
82
+ /**
83
+ * Get value from cache or compute and store it.
84
+ * This is the cache-aside pattern - most commonly used method.
85
+ *
86
+ * @param key Cache key
87
+ * @param cb Callback to compute value if not cached
88
+ * @param ttl Time to live in seconds
89
+ */
90
+ async getOrSet<T>(key: string, cb: () => Promise<T>, ttl?: number): Promise<T> {
91
+ const cached = await this.get<T>(key);
92
+
93
+ if (cached !== null) {
94
+ return cached;
95
+ }
96
+
97
+ const value = await cb();
98
+ await this.set(key, value, ttl);
99
+
100
+ return value;
101
+ }
102
+
103
+ /**
104
+ * Get multiple values at once.
105
+ */
106
+ async getMany<T>(keys: string[]): Promise<(T | null)[]> {
107
+ return Promise.all(keys.map(key => this.get<T>(key)));
108
+ }
109
+
110
+ /**
111
+ * Set multiple values at once.
112
+ */
113
+ async setMany<T>(entries: Array<{ key: string; value: T; ttl?: number }>): Promise<boolean[]> {
114
+ return Promise.all(
115
+ entries.map(entry => this.set(entry.key, entry.value, entry.ttl))
116
+ );
117
+ }
118
+
119
+ /**
120
+ * Delete multiple values at once.
121
+ */
122
+ async delMany(keys: string[]): Promise<boolean[]> {
123
+ return Promise.all(keys.map(key => this.del(key)));
124
+ }
125
+
126
+ /**
127
+ * Close the cache driver connection.
128
+ */
129
+ async close(): Promise<void> {
130
+ await this.driver.close?.();
131
+ }
132
+
133
+ /**
134
+ * Get the underlying driver (for advanced use).
135
+ */
136
+ getDriver(): CacheDriver {
137
+ return this.driver;
138
+ }
139
+ }
@@ -1,104 +1,104 @@
1
- import type { CacheDriver } from './CacheDriver';
2
-
3
- interface CacheEntry<T> {
4
- value: T;
5
- expiresAt: number | null;
6
- }
7
-
8
- /**
9
- * In-Memory Cache Driver.
10
- * Ultra-fast, perfect for single-instance applications.
11
- *
12
- * Features:
13
- * - O(1) get/set/del operations
14
- * - Lazy expiration (checked on access)
15
- * - Periodic cleanup of expired entries
16
- */
17
- export class MemoryDriver implements CacheDriver {
18
- readonly name = 'MemoryDriver';
19
-
20
- private cache = new Map<string, CacheEntry<any>>();
21
- private cleanupInterval: Timer | null = null;
22
-
23
- constructor(cleanupIntervalMs: number = 0) {
24
- // Periodic cleanup of expired entries (disabled by default for performance)
25
- if (cleanupIntervalMs > 0) {
26
- this.cleanupInterval = setInterval(() => this.cleanup(), cleanupIntervalMs);
27
- }
28
- }
29
-
30
- async get<T>(key: string): Promise<T | null> {
31
- const entry = this.cache.get(key);
32
-
33
- if (!entry) {
34
- return null;
35
- }
36
-
37
- // Check expiration
38
- if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
39
- this.cache.delete(key);
40
- return null;
41
- }
42
-
43
- return entry.value;
44
- }
45
-
46
- async set<T>(key: string, value: T, ttl?: number): Promise<boolean> {
47
- const expiresAt = ttl ? Date.now() + ttl : null;
48
-
49
- this.cache.set(key, { value, expiresAt });
50
-
51
- return true;
52
- }
53
-
54
- async del(key: string): Promise<boolean> {
55
- return this.cache.delete(key);
56
- }
57
-
58
- async has(key: string): Promise<boolean> {
59
- const entry = this.cache.get(key);
60
-
61
- if (!entry) {
62
- return false;
63
- }
64
-
65
- if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
66
- this.cache.delete(key);
67
- return false;
68
- }
69
-
70
- return true;
71
- }
72
-
73
- async clear(): Promise<void> {
74
- this.cache.clear();
75
- }
76
-
77
- async close(): Promise<void> {
78
- if (this.cleanupInterval) {
79
- clearInterval(this.cleanupInterval);
80
- this.cleanupInterval = null;
81
- }
82
- this.cache.clear();
83
- }
84
-
85
- /**
86
- * Remove expired entries.
87
- */
88
- private cleanup(): void {
89
- const now = Date.now();
90
-
91
- for (const [key, entry] of this.cache) {
92
- if (entry.expiresAt !== null && now > entry.expiresAt) {
93
- this.cache.delete(key);
94
- }
95
- }
96
- }
97
-
98
- /**
99
- * Get cache stats (for debugging).
100
- */
101
- stats(): { size: number } {
102
- return { size: this.cache.size };
103
- }
104
- }
1
+ import type { CacheDriver } from './CacheDriver';
2
+
3
+ interface CacheEntry<T> {
4
+ value: T;
5
+ expiresAt: number | null;
6
+ }
7
+
8
+ /**
9
+ * In-Memory Cache Driver.
10
+ * Ultra-fast, perfect for single-instance applications.
11
+ *
12
+ * Features:
13
+ * - O(1) get/set/del operations
14
+ * - Lazy expiration (checked on access)
15
+ * - Periodic cleanup of expired entries
16
+ */
17
+ export class MemoryDriver implements CacheDriver {
18
+ readonly name = 'MemoryDriver';
19
+
20
+ private cache = new Map<string, CacheEntry<any>>();
21
+ private cleanupInterval: Timer | null = null;
22
+
23
+ constructor(cleanupIntervalMs: number = 0) {
24
+ // Periodic cleanup of expired entries (disabled by default for performance)
25
+ if (cleanupIntervalMs > 0) {
26
+ this.cleanupInterval = setInterval(() => this.cleanup(), cleanupIntervalMs);
27
+ }
28
+ }
29
+
30
+ async get<T>(key: string): Promise<T | null> {
31
+ const entry = this.cache.get(key);
32
+
33
+ if (!entry) {
34
+ return null;
35
+ }
36
+
37
+ // Check expiration
38
+ if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
39
+ this.cache.delete(key);
40
+ return null;
41
+ }
42
+
43
+ return entry.value;
44
+ }
45
+
46
+ async set<T>(key: string, value: T, ttl?: number): Promise<boolean> {
47
+ const expiresAt = ttl ? Date.now() + ttl : null;
48
+
49
+ this.cache.set(key, { value, expiresAt });
50
+
51
+ return true;
52
+ }
53
+
54
+ async del(key: string): Promise<boolean> {
55
+ return this.cache.delete(key);
56
+ }
57
+
58
+ async has(key: string): Promise<boolean> {
59
+ const entry = this.cache.get(key);
60
+
61
+ if (!entry) {
62
+ return false;
63
+ }
64
+
65
+ if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
66
+ this.cache.delete(key);
67
+ return false;
68
+ }
69
+
70
+ return true;
71
+ }
72
+
73
+ async clear(): Promise<void> {
74
+ this.cache.clear();
75
+ }
76
+
77
+ async close(): Promise<void> {
78
+ if (this.cleanupInterval) {
79
+ clearInterval(this.cleanupInterval);
80
+ this.cleanupInterval = null;
81
+ }
82
+ this.cache.clear();
83
+ }
84
+
85
+ /**
86
+ * Remove expired entries.
87
+ */
88
+ private cleanup(): void {
89
+ const now = Date.now();
90
+
91
+ for (const [key, entry] of this.cache) {
92
+ if (entry.expiresAt !== null && now > entry.expiresAt) {
93
+ this.cache.delete(key);
94
+ }
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Get cache stats (for debugging).
100
+ */
101
+ stats(): { size: number } {
102
+ return { size: this.cache.size };
103
+ }
104
+ }