mcp-wordpress 1.1.7 → 1.2.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 (255) hide show
  1. package/README.md +388 -66
  2. package/dist/cache/CacheInvalidation.d.ts +118 -0
  3. package/dist/cache/CacheInvalidation.d.ts.map +1 -0
  4. package/dist/cache/CacheInvalidation.js +349 -0
  5. package/dist/cache/CacheInvalidation.js.map +1 -0
  6. package/dist/cache/CacheManager.d.ts +143 -0
  7. package/dist/cache/CacheManager.d.ts.map +1 -0
  8. package/dist/cache/CacheManager.js +308 -0
  9. package/dist/cache/CacheManager.js.map +1 -0
  10. package/dist/cache/HttpCacheWrapper.d.ts +121 -0
  11. package/dist/cache/HttpCacheWrapper.d.ts.map +1 -0
  12. package/dist/cache/HttpCacheWrapper.js +280 -0
  13. package/dist/cache/HttpCacheWrapper.js.map +1 -0
  14. package/dist/cache/__tests__/CacheInvalidation.test.d.ts +5 -0
  15. package/dist/cache/__tests__/CacheInvalidation.test.d.ts.map +1 -0
  16. package/dist/cache/__tests__/CacheInvalidation.test.js +236 -0
  17. package/dist/cache/__tests__/CacheInvalidation.test.js.map +1 -0
  18. package/dist/cache/__tests__/CacheManager.test.d.ts +5 -0
  19. package/dist/cache/__tests__/CacheManager.test.d.ts.map +1 -0
  20. package/dist/cache/__tests__/CacheManager.test.js +233 -0
  21. package/dist/cache/__tests__/CacheManager.test.js.map +1 -0
  22. package/dist/cache/__tests__/CachedWordPressClient.test.d.ts +5 -0
  23. package/dist/cache/__tests__/CachedWordPressClient.test.d.ts.map +1 -0
  24. package/dist/cache/__tests__/CachedWordPressClient.test.js +228 -0
  25. package/dist/cache/__tests__/CachedWordPressClient.test.js.map +1 -0
  26. package/dist/cache/__tests__/HttpCacheWrapper.test.d.ts +5 -0
  27. package/dist/cache/__tests__/HttpCacheWrapper.test.d.ts.map +1 -0
  28. package/dist/cache/__tests__/HttpCacheWrapper.test.js +296 -0
  29. package/dist/cache/__tests__/HttpCacheWrapper.test.js.map +1 -0
  30. package/dist/cache/index.d.ts +12 -0
  31. package/dist/cache/index.d.ts.map +1 -0
  32. package/dist/cache/index.js +9 -0
  33. package/dist/cache/index.js.map +1 -0
  34. package/dist/client/CachedWordPressClient.d.ts +160 -0
  35. package/dist/client/CachedWordPressClient.d.ts.map +1 -0
  36. package/dist/client/CachedWordPressClient.js +338 -0
  37. package/dist/client/CachedWordPressClient.js.map +1 -0
  38. package/dist/client/WordPressClient.d.ts +81 -0
  39. package/dist/client/WordPressClient.d.ts.map +1 -0
  40. package/dist/client/WordPressClient.js +354 -0
  41. package/dist/client/WordPressClient.js.map +1 -0
  42. package/dist/config/ConfigurationSchema.d.ts +281 -0
  43. package/dist/config/ConfigurationSchema.d.ts.map +1 -0
  44. package/dist/config/ConfigurationSchema.js +205 -0
  45. package/dist/config/ConfigurationSchema.js.map +1 -0
  46. package/dist/config/ServerConfiguration.d.ts +38 -0
  47. package/dist/config/ServerConfiguration.d.ts.map +1 -0
  48. package/dist/config/ServerConfiguration.js +158 -0
  49. package/dist/config/ServerConfiguration.js.map +1 -0
  50. package/dist/docs/DocumentationGenerator.d.ts +184 -0
  51. package/dist/docs/DocumentationGenerator.d.ts.map +1 -0
  52. package/dist/docs/DocumentationGenerator.js +735 -0
  53. package/dist/docs/DocumentationGenerator.js.map +1 -0
  54. package/dist/docs/MarkdownFormatter.d.ts +84 -0
  55. package/dist/docs/MarkdownFormatter.d.ts.map +1 -0
  56. package/dist/docs/MarkdownFormatter.js +448 -0
  57. package/dist/docs/MarkdownFormatter.js.map +1 -0
  58. package/dist/docs/index.d.ts +8 -0
  59. package/dist/docs/index.d.ts.map +1 -0
  60. package/dist/docs/index.js +7 -0
  61. package/dist/docs/index.js.map +1 -0
  62. package/dist/index.d.ts +1 -4
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +12 -212
  65. package/dist/index.js.map +1 -1
  66. package/dist/performance/AnomalyDetector.d.ts +63 -0
  67. package/dist/performance/AnomalyDetector.d.ts.map +1 -0
  68. package/dist/performance/AnomalyDetector.js +222 -0
  69. package/dist/performance/AnomalyDetector.js.map +1 -0
  70. package/dist/performance/BenchmarkAnalyzer.d.ts +67 -0
  71. package/dist/performance/BenchmarkAnalyzer.d.ts.map +1 -0
  72. package/dist/performance/BenchmarkAnalyzer.js +301 -0
  73. package/dist/performance/BenchmarkAnalyzer.js.map +1 -0
  74. package/dist/performance/MetricsCollector.d.ts +139 -0
  75. package/dist/performance/MetricsCollector.d.ts.map +1 -0
  76. package/dist/performance/MetricsCollector.js +320 -0
  77. package/dist/performance/MetricsCollector.js.map +1 -0
  78. package/dist/performance/PerformanceAnalytics.d.ts +162 -0
  79. package/dist/performance/PerformanceAnalytics.d.ts.map +1 -0
  80. package/dist/performance/PerformanceAnalytics.js +554 -0
  81. package/dist/performance/PerformanceAnalytics.js.map +1 -0
  82. package/dist/performance/PerformanceMonitor.d.ts +202 -0
  83. package/dist/performance/PerformanceMonitor.d.ts.map +1 -0
  84. package/dist/performance/PerformanceMonitor.js +478 -0
  85. package/dist/performance/PerformanceMonitor.js.map +1 -0
  86. package/dist/performance/TrendAnalyzer.d.ts +69 -0
  87. package/dist/performance/TrendAnalyzer.d.ts.map +1 -0
  88. package/dist/performance/TrendAnalyzer.js +203 -0
  89. package/dist/performance/TrendAnalyzer.js.map +1 -0
  90. package/dist/performance/index.d.ts +11 -0
  91. package/dist/performance/index.d.ts.map +1 -0
  92. package/dist/performance/index.js +8 -0
  93. package/dist/performance/index.js.map +1 -0
  94. package/dist/security/InputValidator.d.ts +215 -0
  95. package/dist/security/InputValidator.d.ts.map +1 -0
  96. package/dist/security/InputValidator.js +278 -0
  97. package/dist/security/InputValidator.js.map +1 -0
  98. package/dist/security/SecurityConfig.d.ts +129 -0
  99. package/dist/security/SecurityConfig.d.ts.map +1 -0
  100. package/dist/security/SecurityConfig.js +262 -0
  101. package/dist/security/SecurityConfig.js.map +1 -0
  102. package/dist/server/ConnectionTester.d.ts +24 -0
  103. package/dist/server/ConnectionTester.d.ts.map +1 -0
  104. package/dist/server/ConnectionTester.js +61 -0
  105. package/dist/server/ConnectionTester.js.map +1 -0
  106. package/dist/server/ToolRegistry.d.ts +46 -0
  107. package/dist/server/ToolRegistry.d.ts.map +1 -0
  108. package/dist/server/ToolRegistry.js +148 -0
  109. package/dist/server/ToolRegistry.js.map +1 -0
  110. package/dist/tools/BaseToolClass.d.ts +76 -0
  111. package/dist/tools/BaseToolClass.d.ts.map +1 -0
  112. package/dist/tools/BaseToolClass.js +104 -0
  113. package/dist/tools/BaseToolClass.js.map +1 -0
  114. package/dist/tools/BaseToolManager.d.ts +26 -0
  115. package/dist/tools/BaseToolManager.d.ts.map +1 -0
  116. package/dist/tools/BaseToolManager.js +56 -0
  117. package/dist/tools/BaseToolManager.js.map +1 -0
  118. package/dist/tools/base.d.ts +37 -0
  119. package/dist/tools/base.d.ts.map +1 -0
  120. package/dist/tools/base.js +60 -0
  121. package/dist/tools/base.js.map +1 -0
  122. package/dist/tools/cache.d.ts +260 -0
  123. package/dist/tools/cache.d.ts.map +1 -0
  124. package/dist/tools/cache.js +237 -0
  125. package/dist/tools/cache.js.map +1 -0
  126. package/dist/tools/index.d.ts +2 -0
  127. package/dist/tools/index.d.ts.map +1 -1
  128. package/dist/tools/index.js +2 -0
  129. package/dist/tools/index.js.map +1 -1
  130. package/dist/tools/performance.d.ts +63 -0
  131. package/dist/tools/performance.d.ts.map +1 -0
  132. package/dist/tools/performance.js +865 -0
  133. package/dist/tools/performance.js.map +1 -0
  134. package/dist/types/client.d.ts +1 -0
  135. package/dist/types/client.d.ts.map +1 -1
  136. package/dist/types/client.js.map +1 -1
  137. package/dist/utils/toolWrapper.d.ts +4 -0
  138. package/dist/utils/toolWrapper.d.ts.map +1 -1
  139. package/dist/utils/toolWrapper.js +11 -0
  140. package/dist/utils/toolWrapper.js.map +1 -1
  141. package/dist/utils/validation.d.ts +68 -0
  142. package/dist/utils/validation.d.ts.map +1 -0
  143. package/dist/utils/validation.js +185 -0
  144. package/dist/utils/validation.js.map +1 -0
  145. package/docs/CACHING.md +340 -0
  146. package/docs/DOCKER.md +451 -0
  147. package/docs/PERFORMANCE_MONITORING.md +471 -0
  148. package/docs/SECURITY_TESTING.md +393 -0
  149. package/docs/api/README.md +200 -0
  150. package/docs/api/categories/auth.md +40 -0
  151. package/docs/api/categories/cache.md +41 -0
  152. package/docs/api/categories/comment.md +44 -0
  153. package/docs/api/categories/media.md +43 -0
  154. package/docs/api/categories/page.md +43 -0
  155. package/docs/api/categories/performance.md +44 -0
  156. package/docs/api/categories/post.md +43 -0
  157. package/docs/api/categories/site.md +43 -0
  158. package/docs/api/categories/taxonomy.md +47 -0
  159. package/docs/api/categories/user.md +43 -0
  160. package/docs/api/openapi.json +3305 -0
  161. package/docs/api/summary.json +12 -0
  162. package/docs/api/tools/wp_approve_comment.md +98 -0
  163. package/docs/api/tools/wp_cache_clear.md +120 -0
  164. package/docs/api/tools/wp_cache_info.md +119 -0
  165. package/docs/api/tools/wp_cache_stats.md +119 -0
  166. package/docs/api/tools/wp_cache_warm.md +119 -0
  167. package/docs/api/tools/wp_create_application_password.md +102 -0
  168. package/docs/api/tools/wp_create_category.md +102 -0
  169. package/docs/api/tools/wp_create_comment.md +128 -0
  170. package/docs/api/tools/wp_create_page.md +135 -0
  171. package/docs/api/tools/wp_create_post.md +147 -0
  172. package/docs/api/tools/wp_create_tag.md +101 -0
  173. package/docs/api/tools/wp_create_user.md +135 -0
  174. package/docs/api/tools/wp_delete_application_password.md +101 -0
  175. package/docs/api/tools/wp_delete_category.md +100 -0
  176. package/docs/api/tools/wp_delete_comment.md +101 -0
  177. package/docs/api/tools/wp_delete_media.md +108 -0
  178. package/docs/api/tools/wp_delete_page.md +108 -0
  179. package/docs/api/tools/wp_delete_post.md +117 -0
  180. package/docs/api/tools/wp_delete_tag.md +100 -0
  181. package/docs/api/tools/wp_delete_user.md +108 -0
  182. package/docs/api/tools/wp_get_application_passwords.md +103 -0
  183. package/docs/api/tools/wp_get_auth_status.md +101 -0
  184. package/docs/api/tools/wp_get_category.md +103 -0
  185. package/docs/api/tools/wp_get_comment.md +103 -0
  186. package/docs/api/tools/wp_get_current_user.md +101 -0
  187. package/docs/api/tools/wp_get_media.md +103 -0
  188. package/docs/api/tools/wp_get_page.md +103 -0
  189. package/docs/api/tools/wp_get_page_revisions.md +103 -0
  190. package/docs/api/tools/wp_get_post.md +112 -0
  191. package/docs/api/tools/wp_get_post_revisions.md +103 -0
  192. package/docs/api/tools/wp_get_site_settings.md +108 -0
  193. package/docs/api/tools/wp_get_tag.md +103 -0
  194. package/docs/api/tools/wp_get_user.md +103 -0
  195. package/docs/api/tools/wp_list_categories.md +111 -0
  196. package/docs/api/tools/wp_list_comments.md +111 -0
  197. package/docs/api/tools/wp_list_media.md +145 -0
  198. package/docs/api/tools/wp_list_pages.md +145 -0
  199. package/docs/api/tools/wp_list_posts.md +156 -0
  200. package/docs/api/tools/wp_list_tags.md +110 -0
  201. package/docs/api/tools/wp_list_users.md +111 -0
  202. package/docs/api/tools/wp_performance_alerts.md +162 -0
  203. package/docs/api/tools/wp_performance_benchmark.md +160 -0
  204. package/docs/api/tools/wp_performance_export.md +162 -0
  205. package/docs/api/tools/wp_performance_history.md +161 -0
  206. package/docs/api/tools/wp_performance_optimize.md +162 -0
  207. package/docs/api/tools/wp_performance_stats.md +160 -0
  208. package/docs/api/tools/wp_search_site.md +99 -0
  209. package/docs/api/tools/wp_spam_comment.md +98 -0
  210. package/docs/api/tools/wp_switch_auth_method.md +122 -0
  211. package/docs/api/tools/wp_test_auth.md +96 -0
  212. package/docs/api/tools/wp_update_category.md +102 -0
  213. package/docs/api/tools/wp_update_comment.md +127 -0
  214. package/docs/api/tools/wp_update_media.md +129 -0
  215. package/docs/api/tools/wp_update_page.md +135 -0
  216. package/docs/api/tools/wp_update_post.md +144 -0
  217. package/docs/api/tools/wp_update_site_settings.md +127 -0
  218. package/docs/api/tools/wp_update_tag.md +102 -0
  219. package/docs/api/tools/wp_update_user.md +134 -0
  220. package/docs/api/tools/wp_upload_media.md +131 -0
  221. package/docs/api/types/WordPressPost.md +39 -0
  222. package/docs/contract-testing.md +183 -0
  223. package/docs/developer/NPM_AUTH_SETUP.md +3 -3
  224. package/docs/wordpress-rest-api-authentication-troubleshooting.md +218 -0
  225. package/package.json +84 -64
  226. package/src/cache/CacheInvalidation.ts +421 -0
  227. package/src/cache/CacheManager.ts +391 -0
  228. package/src/cache/HttpCacheWrapper.ts +372 -0
  229. package/src/cache/__tests__/CacheInvalidation.test.ts +299 -0
  230. package/src/cache/__tests__/CacheManager.test.ts +300 -0
  231. package/src/cache/__tests__/CachedWordPressClient.test.ts +304 -0
  232. package/src/cache/__tests__/HttpCacheWrapper.test.ts +359 -0
  233. package/src/cache/index.ts +26 -0
  234. package/src/client/CachedWordPressClient.ts +442 -0
  235. package/src/config/ConfigurationSchema.ts +246 -0
  236. package/src/config/ServerConfiguration.ts +215 -0
  237. package/src/docs/DocumentationGenerator.ts +952 -0
  238. package/src/docs/MarkdownFormatter.ts +494 -0
  239. package/src/docs/index.ts +21 -0
  240. package/src/index.ts +14 -274
  241. package/src/performance/MetricsCollector.ts +447 -0
  242. package/src/performance/PerformanceAnalytics.ts +762 -0
  243. package/src/performance/PerformanceMonitor.ts +649 -0
  244. package/src/performance/index.ts +28 -0
  245. package/src/security/InputValidator.ts +319 -0
  246. package/src/security/SecurityConfig.ts +301 -0
  247. package/src/server/ConnectionTester.ts +74 -0
  248. package/src/server/ToolRegistry.ts +194 -0
  249. package/src/tools/BaseToolManager.ts +66 -0
  250. package/src/tools/cache.ts +259 -0
  251. package/src/tools/index.ts +2 -0
  252. package/src/tools/performance.ts +948 -0
  253. package/src/types/client.ts +1 -0
  254. package/src/utils/toolWrapper.ts +11 -0
  255. package/src/utils/validation.ts +259 -0
@@ -0,0 +1,391 @@
1
+ /**
2
+ * Intelligent caching system for WordPress MCP Server
3
+ * Implements multi-layer caching with TTL, LRU eviction, and site-specific keys
4
+ */
5
+
6
+ import * as crypto from 'crypto';
7
+
8
+ export interface CacheEntry<T = any> {
9
+ value: T;
10
+ timestamp: number;
11
+ ttl: number;
12
+ etag?: string | undefined;
13
+ lastModified?: string | undefined;
14
+ accessCount: number;
15
+ lastAccessed: number;
16
+ }
17
+
18
+ export interface CacheStats {
19
+ hits: number;
20
+ misses: number;
21
+ evictions: number;
22
+ totalSize: number;
23
+ hitRate: number;
24
+ }
25
+
26
+ export interface CacheConfig {
27
+ maxSize: number;
28
+ defaultTTL: number;
29
+ enableLRU: boolean;
30
+ enableStats: boolean;
31
+ sitePrefix?: string;
32
+ }
33
+
34
+ /**
35
+ * High-performance in-memory cache with TTL and LRU eviction
36
+ */
37
+ export class CacheManager {
38
+ private cache: Map<string, CacheEntry> = new Map();
39
+ private accessOrder: string[] = [];
40
+ private stats: CacheStats = {
41
+ hits: 0,
42
+ misses: 0,
43
+ evictions: 0,
44
+ totalSize: 0,
45
+ hitRate: 0
46
+ };
47
+
48
+ constructor(private config: CacheConfig) {
49
+ // Start cleanup interval
50
+ this.startCleanupInterval();
51
+ }
52
+
53
+ /**
54
+ * Generate cache key with site prefix and parameter hash
55
+ */
56
+ generateKey(siteId: string, endpoint: string, params?: any): string {
57
+ const baseKey = `${siteId}:${endpoint}`;
58
+
59
+ if (!params || Object.keys(params).length === 0) {
60
+ return baseKey;
61
+ }
62
+
63
+ // Create deterministic hash of parameters
64
+ const paramHash = crypto
65
+ .createHash('md5')
66
+ .update(JSON.stringify(this.normalizeParams(params)))
67
+ .digest('hex')
68
+ .substring(0, 8);
69
+
70
+ return `${baseKey}:${paramHash}`;
71
+ }
72
+
73
+ /**
74
+ * Get value from cache if not expired
75
+ */
76
+ get<T>(key: string): T | null {
77
+ const entry = this.cache.get(key);
78
+
79
+ if (!entry) {
80
+ this.stats.misses++;
81
+ this.updateHitRate();
82
+ return null;
83
+ }
84
+
85
+ // Check if expired
86
+ if (this.isExpired(entry)) {
87
+ this.cache.delete(key);
88
+ this.removeFromAccessOrder(key);
89
+ this.stats.misses++;
90
+ this.updateHitRate();
91
+ return null;
92
+ }
93
+
94
+ // Update access tracking
95
+ entry.accessCount++;
96
+ entry.lastAccessed = Date.now();
97
+ this.updateAccessOrder(key);
98
+
99
+ this.stats.hits++;
100
+ this.updateHitRate();
101
+
102
+ return entry.value;
103
+ }
104
+
105
+ /**
106
+ * Set value in cache with TTL
107
+ */
108
+ set<T>(
109
+ key: string,
110
+ value: T,
111
+ ttl: number = this.config.defaultTTL,
112
+ etag?: string,
113
+ lastModified?: string
114
+ ): void {
115
+ // Check if we need to evict entries
116
+ if (this.cache.size >= this.config.maxSize && !this.cache.has(key)) {
117
+ this.evictLRU();
118
+ }
119
+
120
+ const entry: CacheEntry<T> = {
121
+ value,
122
+ timestamp: Date.now(),
123
+ ttl,
124
+ etag,
125
+ lastModified,
126
+ accessCount: 1,
127
+ lastAccessed: Date.now()
128
+ };
129
+
130
+ // If updating existing entry, remove from access order first
131
+ if (this.cache.has(key)) {
132
+ this.removeFromAccessOrder(key);
133
+ }
134
+
135
+ this.cache.set(key, entry);
136
+ this.accessOrder.push(key);
137
+ this.stats.totalSize = this.cache.size;
138
+ }
139
+
140
+ /**
141
+ * Check if cache entry exists and is valid
142
+ */
143
+ has(key: string): boolean {
144
+ const entry = this.cache.get(key);
145
+ return entry !== undefined && !this.isExpired(entry);
146
+ }
147
+
148
+ /**
149
+ * Delete specific cache entry
150
+ */
151
+ delete(key: string): boolean {
152
+ const existed = this.cache.delete(key);
153
+ if (existed) {
154
+ this.removeFromAccessOrder(key);
155
+ this.stats.totalSize = this.cache.size;
156
+ }
157
+ return existed;
158
+ }
159
+
160
+ /**
161
+ * Clear all cache entries
162
+ */
163
+ clear(): void {
164
+ this.cache.clear();
165
+ this.accessOrder = [];
166
+ this.stats.totalSize = 0;
167
+ }
168
+
169
+ /**
170
+ * Clear cache entries for specific site
171
+ */
172
+ clearSite(siteId: string): number {
173
+ let cleared = 0;
174
+ const keysToDelete: string[] = [];
175
+
176
+ for (const key of this.cache.keys()) {
177
+ if (key.startsWith(`${siteId}:`)) {
178
+ keysToDelete.push(key);
179
+ }
180
+ }
181
+
182
+ for (const key of keysToDelete) {
183
+ this.delete(key);
184
+ cleared++;
185
+ }
186
+
187
+ return cleared;
188
+ }
189
+
190
+ /**
191
+ * Clear cache entries matching pattern
192
+ */
193
+ clearPattern(pattern: RegExp): number {
194
+ let cleared = 0;
195
+ const keysToDelete: string[] = [];
196
+
197
+ for (const key of this.cache.keys()) {
198
+ if (pattern.test(key)) {
199
+ keysToDelete.push(key);
200
+ }
201
+ }
202
+
203
+ for (const key of keysToDelete) {
204
+ this.delete(key);
205
+ cleared++;
206
+ }
207
+
208
+ return cleared;
209
+ }
210
+
211
+ /**
212
+ * Get cache statistics
213
+ */
214
+ getStats(): CacheStats {
215
+ return { ...this.stats };
216
+ }
217
+
218
+ /**
219
+ * Get cache entry with metadata
220
+ */
221
+ getEntry(key: string): CacheEntry | null {
222
+ const entry = this.cache.get(key);
223
+ if (!entry || this.isExpired(entry)) {
224
+ return null;
225
+ }
226
+ return { ...entry };
227
+ }
228
+
229
+ /**
230
+ * Check if entry supports conditional requests
231
+ */
232
+ supportsConditionalRequest(key: string): boolean {
233
+ const entry = this.cache.get(key);
234
+ return !!(entry && (entry.etag || entry.lastModified));
235
+ }
236
+
237
+ /**
238
+ * Get conditional request headers
239
+ */
240
+ getConditionalHeaders(key: string): Record<string, string> {
241
+ const entry = this.cache.get(key);
242
+ if (!entry) return {};
243
+
244
+ const headers: Record<string, string> = {};
245
+
246
+ if (entry.etag) {
247
+ headers['If-None-Match'] = entry.etag;
248
+ }
249
+
250
+ if (entry.lastModified) {
251
+ headers['If-Modified-Since'] = entry.lastModified;
252
+ }
253
+
254
+ return headers;
255
+ }
256
+
257
+ /**
258
+ * Check if entry is expired
259
+ */
260
+ private isExpired(entry: CacheEntry): boolean {
261
+ return Date.now() - entry.timestamp > entry.ttl;
262
+ }
263
+
264
+ /**
265
+ * Evict least recently used entry
266
+ */
267
+ private evictLRU(): void {
268
+ if (this.accessOrder.length === 0) return;
269
+
270
+ const lruKey = this.accessOrder[0];
271
+ this.cache.delete(lruKey);
272
+ this.accessOrder.shift();
273
+ this.stats.evictions++;
274
+ this.stats.totalSize = this.cache.size;
275
+ }
276
+
277
+ /**
278
+ * Update access order for LRU tracking
279
+ */
280
+ private updateAccessOrder(key: string): void {
281
+ if (!this.config.enableLRU) return;
282
+
283
+ const index = this.accessOrder.indexOf(key);
284
+ if (index > -1) {
285
+ this.accessOrder.splice(index, 1);
286
+ }
287
+ this.accessOrder.push(key);
288
+ }
289
+
290
+ /**
291
+ * Remove key from access order
292
+ */
293
+ private removeFromAccessOrder(key: string): void {
294
+ const index = this.accessOrder.indexOf(key);
295
+ if (index > -1) {
296
+ this.accessOrder.splice(index, 1);
297
+ }
298
+ }
299
+
300
+ /**
301
+ * Normalize parameters for consistent hashing
302
+ */
303
+ private normalizeParams(params: any): any {
304
+ if (typeof params !== 'object' || params === null) {
305
+ return params;
306
+ }
307
+
308
+ // Sort object keys for consistent hashing
309
+ const normalized: any = Array.isArray(params) ? [] : {};
310
+ const keys = Object.keys(params).sort();
311
+
312
+ for (const key of keys) {
313
+ normalized[key] = this.normalizeParams(params[key]);
314
+ }
315
+
316
+ return normalized;
317
+ }
318
+
319
+ /**
320
+ * Update hit rate calculation
321
+ */
322
+ private updateHitRate(): void {
323
+ const total = this.stats.hits + this.stats.misses;
324
+ this.stats.hitRate = total > 0 ? this.stats.hits / total : 0;
325
+ }
326
+
327
+ /**
328
+ * Start periodic cleanup of expired entries
329
+ */
330
+ private startCleanupInterval(): void {
331
+ setInterval(() => {
332
+ this.cleanupExpired();
333
+ }, 60000); // Cleanup every minute
334
+ }
335
+
336
+ /**
337
+ * Remove expired entries
338
+ */
339
+ private cleanupExpired(): void {
340
+ const now = Date.now();
341
+ const keysToDelete: string[] = [];
342
+
343
+ for (const [key, entry] of this.cache.entries()) {
344
+ if (now - entry.timestamp > entry.ttl) {
345
+ keysToDelete.push(key);
346
+ }
347
+ }
348
+
349
+ for (const key of keysToDelete) {
350
+ this.cache.delete(key);
351
+ this.removeFromAccessOrder(key);
352
+ }
353
+
354
+ this.stats.totalSize = this.cache.size;
355
+ }
356
+ }
357
+
358
+ /**
359
+ * Cache configuration presets for different data types
360
+ */
361
+ export const CachePresets = {
362
+ // Static data: site settings, user roles
363
+ STATIC: {
364
+ ttl: 4 * 60 * 60 * 1000, // 4 hours
365
+ cacheControl: 'public, max-age=14400'
366
+ },
367
+
368
+ // Semi-static: categories, tags, user profiles
369
+ SEMI_STATIC: {
370
+ ttl: 2 * 60 * 60 * 1000, // 2 hours
371
+ cacheControl: 'public, max-age=7200'
372
+ },
373
+
374
+ // Dynamic: posts, pages, comments
375
+ DYNAMIC: {
376
+ ttl: 15 * 60 * 1000, // 15 minutes
377
+ cacheControl: 'public, max-age=900'
378
+ },
379
+
380
+ // Session: authentication, current user
381
+ SESSION: {
382
+ ttl: 30 * 60 * 1000, // 30 minutes
383
+ cacheControl: 'private, max-age=1800'
384
+ },
385
+
386
+ // Fast changing: real-time data
387
+ REALTIME: {
388
+ ttl: 60 * 1000, // 1 minute
389
+ cacheControl: 'public, max-age=60'
390
+ }
391
+ };