mcp-wordpress 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. package/README.md +210 -182
  2. package/dist/cache/CacheInvalidation.d.ts +3 -3
  3. package/dist/cache/CacheInvalidation.d.ts.map +1 -1
  4. package/dist/cache/CacheInvalidation.js +119 -119
  5. package/dist/cache/CacheInvalidation.js.map +1 -1
  6. package/dist/cache/CacheManager.d.ts +5 -0
  7. package/dist/cache/CacheManager.d.ts.map +1 -1
  8. package/dist/cache/CacheManager.js +26 -16
  9. package/dist/cache/CacheManager.js.map +1 -1
  10. package/dist/cache/HttpCacheWrapper.d.ts +1 -1
  11. package/dist/cache/HttpCacheWrapper.d.ts.map +1 -1
  12. package/dist/cache/HttpCacheWrapper.js +29 -29
  13. package/dist/cache/HttpCacheWrapper.js.map +1 -1
  14. package/dist/cache/__tests__/CacheInvalidation.test.js +96 -94
  15. package/dist/cache/__tests__/CacheInvalidation.test.js.map +1 -1
  16. package/dist/cache/__tests__/CacheManager.test.js +113 -113
  17. package/dist/cache/__tests__/CacheManager.test.js.map +1 -1
  18. package/dist/cache/__tests__/CachedWordPressClient.test.js +102 -99
  19. package/dist/cache/__tests__/CachedWordPressClient.test.js.map +1 -1
  20. package/dist/cache/__tests__/HttpCacheWrapper.test.js +98 -95
  21. package/dist/cache/__tests__/HttpCacheWrapper.test.js.map +1 -1
  22. package/dist/cache/index.d.ts +7 -7
  23. package/dist/cache/index.d.ts.map +1 -1
  24. package/dist/cache/index.js +4 -4
  25. package/dist/cache/index.js.map +1 -1
  26. package/dist/client/CachedWordPressClient.d.ts +4 -4
  27. package/dist/client/CachedWordPressClient.d.ts.map +1 -1
  28. package/dist/client/CachedWordPressClient.js +55 -51
  29. package/dist/client/CachedWordPressClient.js.map +1 -1
  30. package/dist/client/api.d.ts +10 -10
  31. package/dist/client/api.js +158 -158
  32. package/dist/client/api.js.map +1 -1
  33. package/dist/client/auth.d.ts +2 -2
  34. package/dist/client/auth.js +72 -72
  35. package/dist/client/managers/AuthenticationManager.d.ts +2 -2
  36. package/dist/client/managers/AuthenticationManager.js +46 -46
  37. package/dist/client/managers/BaseManager.d.ts +1 -1
  38. package/dist/client/managers/BaseManager.js +9 -9
  39. package/dist/client/managers/RequestManager.d.ts +5 -3
  40. package/dist/client/managers/RequestManager.d.ts.map +1 -1
  41. package/dist/client/managers/RequestManager.js +39 -19
  42. package/dist/client/managers/RequestManager.js.map +1 -1
  43. package/dist/client/managers/index.d.ts +3 -3
  44. package/dist/client/managers/index.js +3 -3
  45. package/dist/config/ConfigurationSchema.d.ts +2 -2
  46. package/dist/config/ConfigurationSchema.d.ts.map +1 -1
  47. package/dist/config/ConfigurationSchema.js +40 -40
  48. package/dist/config/ConfigurationSchema.js.map +1 -1
  49. package/dist/config/ServerConfiguration.d.ts +2 -2
  50. package/dist/config/ServerConfiguration.js +35 -35
  51. package/dist/config/ServerConfiguration.js.map +1 -1
  52. package/dist/docs/DocumentationGenerator.d.ts.map +1 -1
  53. package/dist/docs/DocumentationGenerator.js +296 -255
  54. package/dist/docs/DocumentationGenerator.js.map +1 -1
  55. package/dist/docs/MarkdownFormatter.d.ts +1 -1
  56. package/dist/docs/MarkdownFormatter.d.ts.map +1 -1
  57. package/dist/docs/MarkdownFormatter.js +60 -51
  58. package/dist/docs/MarkdownFormatter.js.map +1 -1
  59. package/dist/docs/index.d.ts +3 -3
  60. package/dist/docs/index.d.ts.map +1 -1
  61. package/dist/docs/index.js +2 -2
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +16 -16
  64. package/dist/index.js.map +1 -1
  65. package/dist/mcp-wordpress-1.3.0.tgz +0 -0
  66. package/dist/performance/MetricsCollector.d.ts +3 -3
  67. package/dist/performance/MetricsCollector.d.ts.map +1 -1
  68. package/dist/performance/MetricsCollector.js +33 -27
  69. package/dist/performance/MetricsCollector.js.map +1 -1
  70. package/dist/performance/PerformanceAnalytics.d.ts +12 -12
  71. package/dist/performance/PerformanceAnalytics.d.ts.map +1 -1
  72. package/dist/performance/PerformanceAnalytics.js +200 -154
  73. package/dist/performance/PerformanceAnalytics.js.map +1 -1
  74. package/dist/performance/PerformanceMonitor.d.ts +5 -5
  75. package/dist/performance/PerformanceMonitor.d.ts.map +1 -1
  76. package/dist/performance/PerformanceMonitor.js +53 -52
  77. package/dist/performance/PerformanceMonitor.js.map +1 -1
  78. package/dist/performance/index.d.ts +6 -6
  79. package/dist/performance/index.d.ts.map +1 -1
  80. package/dist/performance/index.js +3 -3
  81. package/dist/security/InputValidator.d.ts +1 -1
  82. package/dist/security/InputValidator.d.ts.map +1 -1
  83. package/dist/security/InputValidator.js +111 -88
  84. package/dist/security/InputValidator.js.map +1 -1
  85. package/dist/security/SecurityConfig.d.ts +5 -5
  86. package/dist/security/SecurityConfig.js +92 -92
  87. package/dist/security/SecurityConfig.js.map +1 -1
  88. package/dist/server/ConnectionTester.d.ts +1 -1
  89. package/dist/server/ConnectionTester.d.ts.map +1 -1
  90. package/dist/server/ConnectionTester.js +4 -4
  91. package/dist/server/ConnectionTester.js.map +1 -1
  92. package/dist/server/ToolRegistry.d.ts +2 -2
  93. package/dist/server/ToolRegistry.d.ts.map +1 -1
  94. package/dist/server/ToolRegistry.js +35 -32
  95. package/dist/server/ToolRegistry.js.map +1 -1
  96. package/dist/server.d.ts +2 -2
  97. package/dist/server.js +2 -2
  98. package/dist/tools/BaseToolManager.js +5 -5
  99. package/dist/tools/auth.d.ts +2 -2
  100. package/dist/tools/auth.d.ts.map +1 -1
  101. package/dist/tools/auth.js +32 -31
  102. package/dist/tools/auth.js.map +1 -1
  103. package/dist/tools/cache.d.ts +1 -1
  104. package/dist/tools/cache.d.ts.map +1 -1
  105. package/dist/tools/cache.js +71 -71
  106. package/dist/tools/cache.js.map +1 -1
  107. package/dist/tools/comments.d.ts +2 -2
  108. package/dist/tools/comments.d.ts.map +1 -1
  109. package/dist/tools/comments.js +79 -79
  110. package/dist/tools/comments.js.map +1 -1
  111. package/dist/tools/index.d.ts +10 -10
  112. package/dist/tools/index.js +10 -10
  113. package/dist/tools/media.d.ts +2 -2
  114. package/dist/tools/media.js +80 -80
  115. package/dist/tools/pages.d.ts +2 -2
  116. package/dist/tools/pages.d.ts.map +1 -1
  117. package/dist/tools/pages.js +75 -75
  118. package/dist/tools/pages.js.map +1 -1
  119. package/dist/tools/performance.d.ts +1 -1
  120. package/dist/tools/performance.d.ts.map +1 -1
  121. package/dist/tools/performance.js +311 -287
  122. package/dist/tools/performance.js.map +1 -1
  123. package/dist/tools/posts.d.ts +2 -2
  124. package/dist/tools/posts.d.ts.map +1 -1
  125. package/dist/tools/posts.js +94 -94
  126. package/dist/tools/posts.js.map +1 -1
  127. package/dist/tools/site.d.ts +2 -2
  128. package/dist/tools/site.d.ts.map +1 -1
  129. package/dist/tools/site.js +60 -60
  130. package/dist/tools/site.js.map +1 -1
  131. package/dist/tools/taxonomies.d.ts +2 -2
  132. package/dist/tools/taxonomies.js +89 -89
  133. package/dist/tools/users.d.ts +2 -2
  134. package/dist/tools/users.js +68 -68
  135. package/dist/tools/users.js.map +1 -1
  136. package/dist/types/client.d.ts +13 -13
  137. package/dist/types/client.d.ts.map +1 -1
  138. package/dist/types/client.js +12 -12
  139. package/dist/types/client.js.map +1 -1
  140. package/dist/types/index.d.ts +19 -19
  141. package/dist/types/index.d.ts.map +1 -1
  142. package/dist/types/index.js +3 -3
  143. package/dist/types/mcp.d.ts +7 -7
  144. package/dist/types/wordpress.d.ts +21 -21
  145. package/dist/types/wordpress.d.ts.map +1 -1
  146. package/dist/utils/debug.d.ts +2 -2
  147. package/dist/utils/debug.js +28 -28
  148. package/dist/utils/error.d.ts.map +1 -1
  149. package/dist/utils/error.js +13 -13
  150. package/dist/utils/error.js.map +1 -1
  151. package/dist/utils/toolWrapper.d.ts.map +1 -1
  152. package/dist/utils/toolWrapper.js +5 -5
  153. package/dist/utils/toolWrapper.js.map +1 -1
  154. package/dist/utils/validation.d.ts.map +1 -1
  155. package/dist/utils/validation.js +41 -31
  156. package/dist/utils/validation.js.map +1 -1
  157. package/docs/CACHING.md +36 -2
  158. package/docs/DOCKER.md +24 -18
  159. package/docs/PERFORMANCE_MONITORING.md +49 -1
  160. package/docs/SECURITY_TESTING.md +30 -1
  161. package/docs/api/README.md +9 -1
  162. package/docs/api/summary.json +1 -1
  163. package/docs/contract-testing.md +24 -3
  164. package/docs/developer/GITHUB_ACTIONS_SETUP.md +8 -2
  165. package/docs/developer/MAINTENANCE.md +29 -3
  166. package/docs/developer/MIGRATION_GUIDE.md +13 -1
  167. package/docs/developer/NPM_AUTH_SETUP.md +13 -2
  168. package/docs/developer/REFACTORING.md +31 -1
  169. package/docs/releases/COMMUNITY_ANNOUNCEMENT_v1.1.2.md +18 -7
  170. package/docs/releases/RELEASE_NOTES_v1.1.2.md +31 -5
  171. package/docs/user-guides/DOCKER_SETUP.md +264 -0
  172. package/docs/user-guides/DTX_SETUP.md +327 -0
  173. package/docs/user-guides/NPM_SETUP.md +109 -0
  174. package/docs/user-guides/NPX_SETUP.md +281 -0
  175. package/docs/wordpress-rest-api-authentication-troubleshooting.md +13 -2
  176. package/package.json +27 -8
  177. package/src/cache/CacheInvalidation.ts +140 -132
  178. package/src/cache/CacheManager.ts +40 -29
  179. package/src/cache/HttpCacheWrapper.ts +105 -68
  180. package/src/cache/__tests__/CacheInvalidation.test.ts +123 -118
  181. package/src/cache/__tests__/CacheManager.test.ts +156 -152
  182. package/src/cache/__tests__/CachedWordPressClient.test.ts +131 -116
  183. package/src/cache/__tests__/HttpCacheWrapper.test.ts +118 -115
  184. package/src/cache/index.ts +13 -13
  185. package/src/client/CachedWordPressClient.ts +90 -80
  186. package/src/client/api.ts +205 -205
  187. package/src/client/auth.ts +80 -80
  188. package/src/client/managers/AuthenticationManager.ts +61 -61
  189. package/src/client/managers/BaseManager.ts +11 -11
  190. package/src/client/managers/RequestManager.ts +79 -47
  191. package/src/client/managers/index.ts +3 -3
  192. package/src/config/ConfigurationSchema.ts +44 -44
  193. package/src/config/ServerConfiguration.ts +39 -39
  194. package/src/docs/DocumentationGenerator.ts +402 -295
  195. package/src/docs/MarkdownFormatter.ts +94 -69
  196. package/src/docs/index.ts +4 -4
  197. package/src/index.ts +24 -21
  198. package/src/performance/MetricsCollector.ts +90 -58
  199. package/src/performance/PerformanceAnalytics.ts +386 -262
  200. package/src/performance/PerformanceMonitor.ts +152 -118
  201. package/src/performance/index.ts +9 -9
  202. package/src/security/InputValidator.ts +148 -91
  203. package/src/security/SecurityConfig.ts +94 -94
  204. package/src/server/ConnectionTester.ts +21 -15
  205. package/src/server/ToolRegistry.ts +64 -51
  206. package/src/server.ts +2 -2
  207. package/src/tools/BaseToolManager.ts +6 -6
  208. package/src/tools/auth.ts +42 -37
  209. package/src/tools/cache.ts +85 -81
  210. package/src/tools/comments.ts +93 -91
  211. package/src/tools/index.ts +10 -10
  212. package/src/tools/media.ts +89 -89
  213. package/src/tools/pages.ts +89 -87
  214. package/src/tools/performance.ts +443 -352
  215. package/src/tools/posts.ts +109 -107
  216. package/src/tools/site.ts +86 -77
  217. package/src/tools/taxonomies.ts +102 -102
  218. package/src/tools/users.ts +77 -77
  219. package/src/types/client.ts +157 -60
  220. package/src/types/index.ts +49 -27
  221. package/src/types/mcp.ts +15 -15
  222. package/src/types/wordpress.ts +57 -29
  223. package/src/utils/debug.ts +37 -37
  224. package/src/utils/error.ts +47 -25
  225. package/src/utils/toolWrapper.ts +12 -8
  226. package/src/utils/validation.ts +116 -65
  227. package/dist/client/WordPressClient.d.ts +0 -81
  228. package/dist/client/WordPressClient.d.ts.map +0 -1
  229. package/dist/client/WordPressClient.js +0 -354
  230. package/dist/client/WordPressClient.js.map +0 -1
  231. package/dist/performance/AnomalyDetector.d.ts +0 -63
  232. package/dist/performance/AnomalyDetector.d.ts.map +0 -1
  233. package/dist/performance/AnomalyDetector.js +0 -222
  234. package/dist/performance/AnomalyDetector.js.map +0 -1
  235. package/dist/performance/BenchmarkAnalyzer.d.ts +0 -67
  236. package/dist/performance/BenchmarkAnalyzer.d.ts.map +0 -1
  237. package/dist/performance/BenchmarkAnalyzer.js +0 -301
  238. package/dist/performance/BenchmarkAnalyzer.js.map +0 -1
  239. package/dist/performance/TrendAnalyzer.d.ts +0 -69
  240. package/dist/performance/TrendAnalyzer.d.ts.map +0 -1
  241. package/dist/performance/TrendAnalyzer.js +0 -203
  242. package/dist/performance/TrendAnalyzer.js.map +0 -1
  243. package/dist/tools/BaseToolClass.d.ts +0 -76
  244. package/dist/tools/BaseToolClass.d.ts.map +0 -1
  245. package/dist/tools/BaseToolClass.js +0 -104
  246. package/dist/tools/BaseToolClass.js.map +0 -1
  247. package/dist/tools/base.d.ts +0 -37
  248. package/dist/tools/base.d.ts.map +0 -1
  249. package/dist/tools/base.js +0 -60
  250. package/dist/tools/base.js.map +0 -1
  251. package/docs/user-guides/CLAUDE_DESKTOP_SETUP.md +0 -187
@@ -3,7 +3,7 @@
3
3
  * Implements multi-layer caching with TTL, LRU eviction, and site-specific keys
4
4
  */
5
5
 
6
- import * as crypto from 'crypto';
6
+ import * as crypto from "crypto";
7
7
 
8
8
  export interface CacheEntry<T = any> {
9
9
  value: T;
@@ -37,12 +37,13 @@ export interface CacheConfig {
37
37
  export class CacheManager {
38
38
  private cache: Map<string, CacheEntry> = new Map();
39
39
  private accessOrder: string[] = [];
40
+ private cleanupInterval: NodeJS.Timeout | null = null;
40
41
  private stats: CacheStats = {
41
42
  hits: 0,
42
43
  misses: 0,
43
44
  evictions: 0,
44
45
  totalSize: 0,
45
- hitRate: 0
46
+ hitRate: 0,
46
47
  };
47
48
 
48
49
  constructor(private config: CacheConfig) {
@@ -55,16 +56,16 @@ export class CacheManager {
55
56
  */
56
57
  generateKey(siteId: string, endpoint: string, params?: any): string {
57
58
  const baseKey = `${siteId}:${endpoint}`;
58
-
59
+
59
60
  if (!params || Object.keys(params).length === 0) {
60
61
  return baseKey;
61
62
  }
62
63
 
63
64
  // Create deterministic hash of parameters
64
65
  const paramHash = crypto
65
- .createHash('md5')
66
+ .createHash("md5")
66
67
  .update(JSON.stringify(this.normalizeParams(params)))
67
- .digest('hex')
68
+ .digest("hex")
68
69
  .substring(0, 8);
69
70
 
70
71
  return `${baseKey}:${paramHash}`;
@@ -75,7 +76,7 @@ export class CacheManager {
75
76
  */
76
77
  get<T>(key: string): T | null {
77
78
  const entry = this.cache.get(key);
78
-
79
+
79
80
  if (!entry) {
80
81
  this.stats.misses++;
81
82
  this.updateHitRate();
@@ -95,10 +96,10 @@ export class CacheManager {
95
96
  entry.accessCount++;
96
97
  entry.lastAccessed = Date.now();
97
98
  this.updateAccessOrder(key);
98
-
99
+
99
100
  this.stats.hits++;
100
101
  this.updateHitRate();
101
-
102
+
102
103
  return entry.value;
103
104
  }
104
105
 
@@ -106,11 +107,11 @@ export class CacheManager {
106
107
  * Set value in cache with TTL
107
108
  */
108
109
  set<T>(
109
- key: string,
110
- value: T,
110
+ key: string,
111
+ value: T,
111
112
  ttl: number = this.config.defaultTTL,
112
113
  etag?: string,
113
- lastModified?: string
114
+ lastModified?: string,
114
115
  ): void {
115
116
  // Check if we need to evict entries
116
117
  if (this.cache.size >= this.config.maxSize && !this.cache.has(key)) {
@@ -124,7 +125,7 @@ export class CacheManager {
124
125
  etag,
125
126
  lastModified,
126
127
  accessCount: 1,
127
- lastAccessed: Date.now()
128
+ lastAccessed: Date.now(),
128
129
  };
129
130
 
130
131
  // If updating existing entry, remove from access order first
@@ -242,13 +243,13 @@ export class CacheManager {
242
243
  if (!entry) return {};
243
244
 
244
245
  const headers: Record<string, string> = {};
245
-
246
+
246
247
  if (entry.etag) {
247
- headers['If-None-Match'] = entry.etag;
248
+ headers["If-None-Match"] = entry.etag;
248
249
  }
249
-
250
+
250
251
  if (entry.lastModified) {
251
- headers['If-Modified-Since'] = entry.lastModified;
252
+ headers["If-Modified-Since"] = entry.lastModified;
252
253
  }
253
254
 
254
255
  return headers;
@@ -301,7 +302,7 @@ export class CacheManager {
301
302
  * Normalize parameters for consistent hashing
302
303
  */
303
304
  private normalizeParams(params: any): any {
304
- if (typeof params !== 'object' || params === null) {
305
+ if (typeof params !== "object" || params === null) {
305
306
  return params;
306
307
  }
307
308
 
@@ -328,11 +329,21 @@ export class CacheManager {
328
329
  * Start periodic cleanup of expired entries
329
330
  */
330
331
  private startCleanupInterval(): void {
331
- setInterval(() => {
332
+ this.cleanupInterval = setInterval(() => {
332
333
  this.cleanupExpired();
333
334
  }, 60000); // Cleanup every minute
334
335
  }
335
336
 
337
+ /**
338
+ * Stop the cleanup interval and clean up resources
339
+ */
340
+ destroy(): void {
341
+ if (this.cleanupInterval) {
342
+ clearInterval(this.cleanupInterval);
343
+ this.cleanupInterval = null;
344
+ }
345
+ }
346
+
336
347
  /**
337
348
  * Remove expired entries
338
349
  */
@@ -362,30 +373,30 @@ export const CachePresets = {
362
373
  // Static data: site settings, user roles
363
374
  STATIC: {
364
375
  ttl: 4 * 60 * 60 * 1000, // 4 hours
365
- cacheControl: 'public, max-age=14400'
376
+ cacheControl: "public, max-age=14400",
366
377
  },
367
-
368
- // Semi-static: categories, tags, user profiles
378
+
379
+ // Semi-static: categories, tags, user profiles
369
380
  SEMI_STATIC: {
370
381
  ttl: 2 * 60 * 60 * 1000, // 2 hours
371
- cacheControl: 'public, max-age=7200'
382
+ cacheControl: "public, max-age=7200",
372
383
  },
373
-
384
+
374
385
  // Dynamic: posts, pages, comments
375
386
  DYNAMIC: {
376
387
  ttl: 15 * 60 * 1000, // 15 minutes
377
- cacheControl: 'public, max-age=900'
388
+ cacheControl: "public, max-age=900",
378
389
  },
379
-
390
+
380
391
  // Session: authentication, current user
381
392
  SESSION: {
382
393
  ttl: 30 * 60 * 1000, // 30 minutes
383
- cacheControl: 'private, max-age=1800'
394
+ cacheControl: "private, max-age=1800",
384
395
  },
385
-
396
+
386
397
  // Fast changing: real-time data
387
398
  REALTIME: {
388
399
  ttl: 60 * 1000, // 1 minute
389
- cacheControl: 'public, max-age=60'
390
- }
400
+ cacheControl: "public, max-age=60",
401
+ },
391
402
  };
@@ -3,8 +3,8 @@
3
3
  * Implements WordPress REST API caching best practices
4
4
  */
5
5
 
6
- import { CacheManager, CachePresets } from './CacheManager.js';
7
- import * as crypto from 'crypto';
6
+ import { CacheManager, CachePresets } from "./CacheManager.js";
7
+ import * as crypto from "crypto";
8
8
 
9
9
  export interface HttpCacheOptions {
10
10
  ttl?: number;
@@ -37,19 +37,28 @@ export interface RequestOptions {
37
37
  export class HttpCacheWrapper {
38
38
  constructor(
39
39
  private cacheManager: CacheManager,
40
- private siteId: string
40
+ private siteId: string,
41
41
  ) {}
42
42
 
43
43
  /**
44
44
  * Execute request with intelligent caching
45
45
  */
46
46
  async request<T = any>(
47
- requestFn: () => Promise<{ data: T; status: number; headers: Record<string, string> }>,
47
+ requestFn: () => Promise<{
48
+ data: T;
49
+ status: number;
50
+ headers: Record<string, string>;
51
+ }>,
48
52
  options: RequestOptions,
49
- cacheOptions?: HttpCacheOptions
50
- ): Promise<{ data: T; status: number; headers: Record<string, string>; cached?: boolean }> {
53
+ cacheOptions?: HttpCacheOptions,
54
+ ): Promise<{
55
+ data: T;
56
+ status: number;
57
+ headers: Record<string, string>;
58
+ cached?: boolean;
59
+ }> {
51
60
  // Only cache GET requests
52
- if (options.method.toUpperCase() !== 'GET') {
61
+ if (options.method.toUpperCase() !== "GET") {
53
62
  return await requestFn();
54
63
  }
55
64
 
@@ -58,36 +67,42 @@ export class HttpCacheWrapper {
58
67
 
59
68
  // Check for conditional request support
60
69
  if (cachedEntry && this.cacheManager.supportsConditionalRequest(cacheKey)) {
61
- const conditionalHeaders = this.cacheManager.getConditionalHeaders(cacheKey);
62
-
70
+ const conditionalHeaders =
71
+ this.cacheManager.getConditionalHeaders(cacheKey);
72
+
63
73
  // Add conditional headers to request
64
74
  const requestWithHeaders = {
65
75
  ...options,
66
76
  headers: {
67
77
  ...options.headers,
68
- ...conditionalHeaders
69
- }
78
+ ...conditionalHeaders,
79
+ },
70
80
  };
71
81
 
72
82
  try {
73
- const response = await this.executeRequestWithHeaders(requestFn, requestWithHeaders);
74
-
83
+ const response = await this.executeRequestWithHeaders(
84
+ requestFn,
85
+ requestWithHeaders,
86
+ );
87
+
75
88
  // 304 Not Modified - return cached data
76
89
  if (response.status === 304) {
77
90
  return {
78
91
  data: cachedEntry.value.data,
79
92
  status: 200,
80
93
  headers: cachedEntry.value.headers,
81
- cached: true
94
+ cached: true,
82
95
  };
83
96
  }
84
97
 
85
98
  // Content changed - update cache
86
99
  return await this.cacheAndReturn(response, cacheKey, cacheOptions);
87
-
88
100
  } catch (error) {
89
101
  // If conditional request fails, try without conditions
90
- console.warn('Conditional request failed, falling back to regular request:', error);
102
+ console.warn(
103
+ "Conditional request failed, falling back to regular request:",
104
+ error,
105
+ );
91
106
  }
92
107
  }
93
108
 
@@ -98,7 +113,7 @@ export class HttpCacheWrapper {
98
113
  data: cached.data,
99
114
  status: cached.status,
100
115
  headers: cached.headers,
101
- cached: true
116
+ cached: true,
102
117
  };
103
118
  }
104
119
 
@@ -111,7 +126,11 @@ export class HttpCacheWrapper {
111
126
  * Invalidate cache for specific endpoint
112
127
  */
113
128
  invalidate(endpoint: string, params?: any): void {
114
- const cacheKey = this.cacheManager.generateKey(this.siteId, endpoint, params);
129
+ const cacheKey = this.cacheManager.generateKey(
130
+ this.siteId,
131
+ endpoint,
132
+ params,
133
+ );
115
134
  this.cacheManager.delete(cacheKey);
116
135
  }
117
136
 
@@ -133,17 +152,27 @@ export class HttpCacheWrapper {
133
152
  /**
134
153
  * Pre-warm cache with data
135
154
  */
136
- warm<T>(endpoint: string, data: T, params?: any, cacheOptions?: HttpCacheOptions): void {
137
- const cacheKey = this.cacheManager.generateKey(this.siteId, endpoint, params);
155
+ warm<T>(
156
+ endpoint: string,
157
+ data: T,
158
+ params?: any,
159
+ cacheOptions?: HttpCacheOptions,
160
+ ): void {
161
+ const cacheKey = this.cacheManager.generateKey(
162
+ this.siteId,
163
+ endpoint,
164
+ params,
165
+ );
138
166
  const ttl = cacheOptions?.ttl || this.getDefaultTTL(endpoint);
139
-
167
+
140
168
  const cachedResponse: CachedResponse = {
141
169
  data,
142
170
  status: 200,
143
171
  headers: this.generateCacheHeaders(cacheOptions, endpoint),
144
172
  etag: this.generateETag(data),
145
173
  lastModified: new Date().toUTCString(),
146
- cacheControl: cacheOptions?.cacheControl || this.getDefaultCacheControl(endpoint)
174
+ cacheControl:
175
+ cacheOptions?.cacheControl || this.getDefaultCacheControl(endpoint),
147
176
  };
148
177
 
149
178
  this.cacheManager.set(
@@ -151,7 +180,7 @@ export class HttpCacheWrapper {
151
180
  cachedResponse,
152
181
  ttl,
153
182
  cachedResponse.etag,
154
- cachedResponse.lastModified
183
+ cachedResponse.lastModified,
155
184
  );
156
185
  }
157
186
 
@@ -170,7 +199,7 @@ export class HttpCacheWrapper {
170
199
  return this.cacheManager.generateKey(this.siteId, endpoint, {
171
200
  ...options.params,
172
201
  // Include relevant headers that affect response
173
- ...this.extractCacheableHeaders(options.headers)
202
+ ...this.extractCacheableHeaders(options.headers),
174
203
  });
175
204
  }
176
205
 
@@ -186,11 +215,13 @@ export class HttpCacheWrapper {
186
215
  /**
187
216
  * Extract headers that affect caching
188
217
  */
189
- private extractCacheableHeaders(headers?: Record<string, string>): Record<string, string> {
218
+ private extractCacheableHeaders(
219
+ headers?: Record<string, string>,
220
+ ): Record<string, string> {
190
221
  if (!headers) return {};
191
222
 
192
223
  const cacheableHeaders: Record<string, string> = {};
193
- const relevantHeaders = ['accept', 'accept-language', 'authorization'];
224
+ const relevantHeaders = ["accept", "accept-language", "authorization"];
194
225
 
195
226
  for (const header of relevantHeaders) {
196
227
  if (headers[header]) {
@@ -205,8 +236,12 @@ export class HttpCacheWrapper {
205
236
  * Execute request with modified headers
206
237
  */
207
238
  private async executeRequestWithHeaders(
208
- requestFn: () => Promise<{ data: any; status: number; headers: Record<string, string> }>,
209
- options: RequestOptions
239
+ requestFn: () => Promise<{
240
+ data: any;
241
+ status: number;
242
+ headers: Record<string, string>;
243
+ }>,
244
+ options: RequestOptions,
210
245
  ) {
211
246
  // This is a simplified approach - in practice, you'd need to modify the actual request
212
247
  // The actual implementation would depend on your HTTP client (axios, fetch, etc.)
@@ -219,9 +254,13 @@ export class HttpCacheWrapper {
219
254
  private async cacheAndReturn<T>(
220
255
  response: { data: T; status: number; headers: Record<string, string> },
221
256
  cacheKey: string,
222
- cacheOptions?: HttpCacheOptions
223
- ): Promise<{ data: T; status: number; headers: Record<string, string>; cached?: boolean }> {
224
-
257
+ cacheOptions?: HttpCacheOptions,
258
+ ): Promise<{
259
+ data: T;
260
+ status: number;
261
+ headers: Record<string, string>;
262
+ cached?: boolean;
263
+ }> {
225
264
  // Don't cache error responses (unless specifically configured)
226
265
  if (response.status >= 400) {
227
266
  return response;
@@ -229,40 +268,35 @@ export class HttpCacheWrapper {
229
268
 
230
269
  const endpoint = this.extractEndpointFromKey(cacheKey);
231
270
  const ttl = cacheOptions?.ttl || this.getDefaultTTL(endpoint);
232
-
271
+
233
272
  // Generate ETags and cache headers
234
273
  const etag = this.generateETag(response.data);
235
274
  const lastModified = new Date().toUTCString();
236
- const cacheControl = cacheOptions?.cacheControl || this.getDefaultCacheControl(endpoint);
275
+ const cacheControl =
276
+ cacheOptions?.cacheControl || this.getDefaultCacheControl(endpoint);
237
277
 
238
278
  const cachedResponse: CachedResponse = {
239
279
  data: response.data,
240
280
  status: response.status,
241
281
  headers: {
242
282
  ...response.headers,
243
- 'etag': etag,
244
- 'last-modified': lastModified,
245
- 'cache-control': cacheControl
283
+ etag: etag,
284
+ "last-modified": lastModified,
285
+ "cache-control": cacheControl,
246
286
  },
247
287
  etag,
248
288
  lastModified,
249
- cacheControl
289
+ cacheControl,
250
290
  };
251
291
 
252
292
  // Store in cache
253
- this.cacheManager.set(
254
- cacheKey,
255
- cachedResponse,
256
- ttl,
257
- etag,
258
- lastModified
259
- );
293
+ this.cacheManager.set(cacheKey, cachedResponse, ttl, etag, lastModified);
260
294
 
261
295
  return {
262
296
  data: response.data,
263
297
  status: response.status,
264
298
  headers: cachedResponse.headers,
265
- cached: false
299
+ cached: false,
266
300
  };
267
301
  }
268
302
 
@@ -271,9 +305,9 @@ export class HttpCacheWrapper {
271
305
  */
272
306
  private generateETag(data: any): string {
273
307
  const hash = crypto
274
- .createHash('md5')
308
+ .createHash("md5")
275
309
  .update(JSON.stringify(data))
276
- .digest('hex');
310
+ .digest("hex");
277
311
  return `"${hash}"`;
278
312
  }
279
313
 
@@ -285,17 +319,17 @@ export class HttpCacheWrapper {
285
319
  if (this.isStaticEndpoint(endpoint)) {
286
320
  return CachePresets.STATIC.ttl;
287
321
  }
288
-
322
+
289
323
  // Semi-static data endpoints
290
324
  if (this.isSemiStaticEndpoint(endpoint)) {
291
325
  return CachePresets.SEMI_STATIC.ttl;
292
326
  }
293
-
327
+
294
328
  // Session/auth endpoints
295
329
  if (this.isSessionEndpoint(endpoint)) {
296
330
  return CachePresets.SESSION.ttl;
297
331
  }
298
-
332
+
299
333
  // Default to dynamic for posts, comments, etc.
300
334
  return CachePresets.DYNAMIC.ttl;
301
335
  }
@@ -307,32 +341,35 @@ export class HttpCacheWrapper {
307
341
  if (this.isStaticEndpoint(endpoint)) {
308
342
  return CachePresets.STATIC.cacheControl;
309
343
  }
310
-
344
+
311
345
  if (this.isSemiStaticEndpoint(endpoint)) {
312
346
  return CachePresets.SEMI_STATIC.cacheControl;
313
347
  }
314
-
348
+
315
349
  if (this.isSessionEndpoint(endpoint)) {
316
350
  return CachePresets.SESSION.cacheControl;
317
351
  }
318
-
352
+
319
353
  return CachePresets.DYNAMIC.cacheControl;
320
354
  }
321
355
 
322
356
  /**
323
357
  * Generate cache headers
324
358
  */
325
- private generateCacheHeaders(options?: HttpCacheOptions, endpoint?: string): Record<string, string> {
359
+ private generateCacheHeaders(
360
+ options?: HttpCacheOptions,
361
+ endpoint?: string,
362
+ ): Record<string, string> {
326
363
  const headers: Record<string, string> = {};
327
-
364
+
328
365
  if (options?.cacheControl) {
329
- headers['cache-control'] = options.cacheControl;
366
+ headers["cache-control"] = options.cacheControl;
330
367
  } else if (endpoint) {
331
- headers['cache-control'] = this.getDefaultCacheControl(endpoint);
368
+ headers["cache-control"] = this.getDefaultCacheControl(endpoint);
332
369
  }
333
-
370
+
334
371
  if (options?.varyHeaders?.length) {
335
- headers['vary'] = options.varyHeaders.join(', ');
372
+ headers["vary"] = options.varyHeaders.join(", ");
336
373
  }
337
374
 
338
375
  return headers;
@@ -342,31 +379,31 @@ export class HttpCacheWrapper {
342
379
  * Check if endpoint contains static data
343
380
  */
344
381
  private isStaticEndpoint(endpoint: string): boolean {
345
- const staticEndpoints = ['settings', 'types', 'statuses'];
346
- return staticEndpoints.some(pattern => endpoint.includes(pattern));
382
+ const staticEndpoints = ["settings", "types", "statuses"];
383
+ return staticEndpoints.some((pattern) => endpoint.includes(pattern));
347
384
  }
348
385
 
349
386
  /**
350
- * Check if endpoint contains semi-static data
387
+ * Check if endpoint contains semi-static data
351
388
  */
352
389
  private isSemiStaticEndpoint(endpoint: string): boolean {
353
- const semiStaticEndpoints = ['categories', 'tags', 'users', 'taxonomies'];
354
- return semiStaticEndpoints.some(pattern => endpoint.includes(pattern));
390
+ const semiStaticEndpoints = ["categories", "tags", "users", "taxonomies"];
391
+ return semiStaticEndpoints.some((pattern) => endpoint.includes(pattern));
355
392
  }
356
393
 
357
394
  /**
358
395
  * Check if endpoint is session-related
359
396
  */
360
397
  private isSessionEndpoint(endpoint: string): boolean {
361
- const sessionEndpoints = ['users/me', 'application-passwords'];
362
- return sessionEndpoints.some(pattern => endpoint.includes(pattern));
398
+ const sessionEndpoints = ["users/me", "application-passwords"];
399
+ return sessionEndpoints.some((pattern) => endpoint.includes(pattern));
363
400
  }
364
401
 
365
402
  /**
366
403
  * Extract endpoint from cache key
367
404
  */
368
405
  private extractEndpointFromKey(cacheKey: string): string {
369
- const parts = cacheKey.split(':');
370
- return parts[1] || '';
406
+ const parts = cacheKey.split(":");
407
+ return parts[1] || "";
371
408
  }
372
409
  }