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,359 @@
1
+ /**
2
+ * Tests for HttpCacheWrapper
3
+ */
4
+
5
+ import { CacheManager } from '../CacheManager.js';
6
+ import { HttpCacheWrapper } from '../HttpCacheWrapper.js';
7
+
8
+ describe('HttpCacheWrapper', () => {
9
+ let cacheManager: CacheManager;
10
+ let httpCache: HttpCacheWrapper;
11
+ let mockRequestFn: jest.Mock;
12
+
13
+ beforeEach(() => {
14
+ cacheManager = new CacheManager({
15
+ maxSize: 100,
16
+ defaultTTL: 1000,
17
+ enableLRU: true,
18
+ enableStats: true
19
+ });
20
+
21
+ httpCache = new HttpCacheWrapper(cacheManager, 'test-site');
22
+
23
+ mockRequestFn = jest.fn();
24
+ });
25
+
26
+ afterEach(() => {
27
+ cacheManager.clear();
28
+ jest.clearAllMocks();
29
+ });
30
+
31
+ describe('Request Caching', () => {
32
+ test('should cache GET requests', async () => {
33
+ const mockResponse = {
34
+ data: { id: 1, title: 'Test Post' },
35
+ status: 200,
36
+ headers: {}
37
+ };
38
+
39
+ mockRequestFn.mockResolvedValue(mockResponse);
40
+
41
+ const requestOptions = {
42
+ method: 'GET',
43
+ url: 'https://example.com/wp-json/wp/v2/posts',
44
+ headers: {},
45
+ params: {}
46
+ };
47
+
48
+ // First request should hit the API
49
+ const result1 = await httpCache.request(mockRequestFn, requestOptions);
50
+ expect(mockRequestFn).toHaveBeenCalledTimes(1);
51
+ expect(result1.data).toEqual(mockResponse.data);
52
+ expect(result1.cached).toBe(false);
53
+
54
+ // Second request should use cache
55
+ const result2 = await httpCache.request(mockRequestFn, requestOptions);
56
+ expect(mockRequestFn).toHaveBeenCalledTimes(1); // No additional call
57
+ expect(result2.data).toEqual(mockResponse.data);
58
+ expect(result2.cached).toBe(true);
59
+ });
60
+
61
+ test('should not cache non-GET requests', async () => {
62
+ const mockResponse = {
63
+ data: { id: 1, title: 'Test Post' },
64
+ status: 201,
65
+ headers: {}
66
+ };
67
+
68
+ mockRequestFn.mockResolvedValue(mockResponse);
69
+
70
+ const requestOptions = {
71
+ method: 'POST',
72
+ url: 'https://example.com/wp-json/wp/v2/posts',
73
+ headers: {},
74
+ params: {},
75
+ data: { title: 'New Post' }
76
+ };
77
+
78
+ // Both requests should hit the API
79
+ const result1 = await httpCache.request(mockRequestFn, requestOptions);
80
+ const result2 = await httpCache.request(mockRequestFn, requestOptions);
81
+
82
+ expect(mockRequestFn).toHaveBeenCalledTimes(2);
83
+ expect(result1.cached).toBeUndefined();
84
+ expect(result2.cached).toBeUndefined();
85
+ });
86
+
87
+ test('should not cache error responses', async () => {
88
+ const errorResponse = {
89
+ data: { error: 'Not found' },
90
+ status: 404,
91
+ headers: {}
92
+ };
93
+
94
+ mockRequestFn.mockResolvedValue(errorResponse);
95
+
96
+ const requestOptions = {
97
+ method: 'GET',
98
+ url: 'https://example.com/wp-json/wp/v2/posts/999',
99
+ headers: {},
100
+ params: {}
101
+ };
102
+
103
+ // Both requests should hit the API (no caching of 404)
104
+ await httpCache.request(mockRequestFn, requestOptions);
105
+ await httpCache.request(mockRequestFn, requestOptions);
106
+
107
+ expect(mockRequestFn).toHaveBeenCalledTimes(2);
108
+ });
109
+
110
+ test('should generate ETags for responses', async () => {
111
+ const mockResponse = {
112
+ data: { id: 1, title: 'Test Post' },
113
+ status: 200,
114
+ headers: {}
115
+ };
116
+
117
+ mockRequestFn.mockResolvedValue(mockResponse);
118
+
119
+ const requestOptions = {
120
+ method: 'GET',
121
+ url: 'https://example.com/wp-json/wp/v2/posts/1',
122
+ headers: {},
123
+ params: {}
124
+ };
125
+
126
+ const result = await httpCache.request(mockRequestFn, requestOptions);
127
+
128
+ expect(result.headers.etag).toBeDefined();
129
+ expect(result.headers.etag).toMatch(/^"[a-f0-9]{32}"$/);
130
+ expect(result.headers['last-modified']).toBeDefined();
131
+ expect(result.headers['cache-control']).toBeDefined();
132
+ });
133
+ });
134
+
135
+ describe('Cache Invalidation', () => {
136
+ test('should invalidate specific endpoint', async () => {
137
+ // Cache a response
138
+ const mockResponse = {
139
+ data: { id: 1, title: 'Test Post' },
140
+ status: 200,
141
+ headers: {}
142
+ };
143
+
144
+ mockRequestFn.mockResolvedValue(mockResponse);
145
+
146
+ const requestOptions = {
147
+ method: 'GET',
148
+ url: 'https://example.com/wp-json/wp/v2/posts/1',
149
+ headers: {},
150
+ params: {}
151
+ };
152
+
153
+ await httpCache.request(mockRequestFn, requestOptions);
154
+ expect(mockRequestFn).toHaveBeenCalledTimes(1);
155
+
156
+ // Verify cache hit
157
+ await httpCache.request(mockRequestFn, requestOptions);
158
+ expect(mockRequestFn).toHaveBeenCalledTimes(1);
159
+
160
+ // Invalidate cache
161
+ httpCache.invalidate('posts/1');
162
+
163
+ // Should hit API again
164
+ await httpCache.request(mockRequestFn, requestOptions);
165
+ expect(mockRequestFn).toHaveBeenCalledTimes(2);
166
+ });
167
+
168
+ test('should invalidate by pattern', async () => {
169
+ // Cache multiple responses
170
+ const responses = [
171
+ { url: 'posts', data: [{ id: 1 }, { id: 2 }] },
172
+ { url: 'posts/1', data: { id: 1 } },
173
+ { url: 'pages/1', data: { id: 1 } }
174
+ ];
175
+
176
+ for (const response of responses) {
177
+ mockRequestFn.mockResolvedValueOnce({
178
+ data: response.data,
179
+ status: 200,
180
+ headers: {}
181
+ });
182
+
183
+ await httpCache.request(mockRequestFn, {
184
+ method: 'GET',
185
+ url: `https://example.com/wp-json/wp/v2/${response.url}`,
186
+ headers: {},
187
+ params: {}
188
+ });
189
+ }
190
+
191
+ expect(mockRequestFn).toHaveBeenCalledTimes(3);
192
+
193
+ // Invalidate all posts
194
+ const invalidated = httpCache.invalidatePattern('posts');
195
+ expect(invalidated).toBe(2); // Should invalidate 2 post-related entries
196
+
197
+ // Verify pages cache still works
198
+ await httpCache.request(mockRequestFn, {
199
+ method: 'GET',
200
+ url: 'https://example.com/wp-json/wp/v2/pages/1',
201
+ headers: {},
202
+ params: {}
203
+ });
204
+ expect(mockRequestFn).toHaveBeenCalledTimes(3); // No new call for pages
205
+ });
206
+
207
+ test('should invalidate all cache for site', async () => {
208
+ // Cache some responses
209
+ const mockResponse = {
210
+ data: { id: 1 },
211
+ status: 200,
212
+ headers: {}
213
+ };
214
+
215
+ mockRequestFn.mockResolvedValue(mockResponse);
216
+
217
+ await httpCache.request(mockRequestFn, {
218
+ method: 'GET',
219
+ url: 'https://example.com/wp-json/wp/v2/posts',
220
+ headers: {},
221
+ params: {}
222
+ });
223
+
224
+ await httpCache.request(mockRequestFn, {
225
+ method: 'GET',
226
+ url: 'https://example.com/wp-json/wp/v2/pages',
227
+ headers: {},
228
+ params: {}
229
+ });
230
+
231
+ expect(mockRequestFn).toHaveBeenCalledTimes(2);
232
+
233
+ // Clear all cache
234
+ const invalidated = httpCache.invalidateAll();
235
+ expect(invalidated).toBeGreaterThan(0);
236
+
237
+ // Verify cache is cleared
238
+ await httpCache.request(mockRequestFn, {
239
+ method: 'GET',
240
+ url: 'https://example.com/wp-json/wp/v2/posts',
241
+ headers: {},
242
+ params: {}
243
+ });
244
+ expect(mockRequestFn).toHaveBeenCalledTimes(3);
245
+ });
246
+ });
247
+
248
+ describe('Cache Warming', () => {
249
+ test('should pre-warm cache with data', () => {
250
+ const endpoint = 'posts';
251
+ const data = [{ id: 1, title: 'Post 1' }, { id: 2, title: 'Post 2' }];
252
+ const params = { per_page: 10 };
253
+
254
+ httpCache.warm(endpoint, data, params);
255
+
256
+ // Verify cache entry exists
257
+ const cacheKey = cacheManager.generateKey('test-site', endpoint, params);
258
+ const cached = cacheManager.get(cacheKey);
259
+
260
+ expect(cached).toBeDefined();
261
+ if (cached && typeof cached === 'object' && 'data' in cached) {
262
+ expect((cached as any).data).toEqual(data);
263
+ expect((cached as any).etag).toBeDefined();
264
+ expect((cached as any).lastModified).toBeDefined();
265
+ }
266
+ });
267
+
268
+ test('should use warmed cache for requests', async () => {
269
+ const endpoint = 'posts';
270
+ const data = [{ id: 1, title: 'Post 1' }];
271
+
272
+ httpCache.warm(endpoint, data);
273
+
274
+ const result = await httpCache.request(mockRequestFn, {
275
+ method: 'GET',
276
+ url: 'https://example.com/wp-json/wp/v2/posts',
277
+ headers: {},
278
+ params: {}
279
+ });
280
+
281
+ expect(mockRequestFn).not.toHaveBeenCalled();
282
+ expect(result.data).toEqual(data);
283
+ expect(result.cached).toBe(true);
284
+ });
285
+ });
286
+
287
+ describe('Cache Statistics', () => {
288
+ test('should return cache statistics', async () => {
289
+ const mockResponse = {
290
+ data: { id: 1 },
291
+ status: 200,
292
+ headers: {}
293
+ };
294
+
295
+ mockRequestFn.mockResolvedValue(mockResponse);
296
+
297
+ // Generate some cache activity
298
+ await httpCache.request(mockRequestFn, {
299
+ method: 'GET',
300
+ url: 'https://example.com/wp-json/wp/v2/posts/1',
301
+ headers: {},
302
+ params: {}
303
+ });
304
+
305
+ await httpCache.request(mockRequestFn, {
306
+ method: 'GET',
307
+ url: 'https://example.com/wp-json/wp/v2/posts/1',
308
+ headers: {},
309
+ params: {}
310
+ });
311
+
312
+ const stats = httpCache.getStats();
313
+ expect(stats.hits).toBe(1);
314
+ expect(stats.misses).toBe(1);
315
+ expect(stats.totalSize).toBe(1);
316
+ expect(stats.hitRate).toBe(0.5);
317
+ });
318
+ });
319
+
320
+ describe('URL and Endpoint Extraction', () => {
321
+ test('should extract endpoint from WordPress API URLs', async () => {
322
+ const testCases = [
323
+ {
324
+ url: 'https://example.com/wp-json/wp/v2/posts',
325
+ expectedEndpoint: 'posts'
326
+ },
327
+ {
328
+ url: 'https://example.com/wp-json/wp/v2/posts/123',
329
+ expectedEndpoint: 'posts/123'
330
+ },
331
+ {
332
+ url: 'https://example.com/wp-json/wp/v2/categories?per_page=10',
333
+ expectedEndpoint: 'categories'
334
+ }
335
+ ];
336
+
337
+ const mockResponse = {
338
+ data: {},
339
+ status: 200,
340
+ headers: {}
341
+ };
342
+
343
+ mockRequestFn.mockResolvedValue(mockResponse);
344
+
345
+ for (const testCase of testCases) {
346
+ await httpCache.request(mockRequestFn, {
347
+ method: 'GET',
348
+ url: testCase.url,
349
+ headers: {},
350
+ params: {}
351
+ });
352
+
353
+ // Verify cache key contains the correct endpoint
354
+ const stats = httpCache.getStats();
355
+ expect(stats.totalSize).toBeGreaterThan(0);
356
+ }
357
+ });
358
+ });
359
+ });
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Cache system exports
3
+ * Provides centralized access to all caching components
4
+ */
5
+
6
+ export { CacheManager, CachePresets } from './CacheManager.js';
7
+ export { HttpCacheWrapper } from './HttpCacheWrapper.js';
8
+ export { CacheInvalidation, WordPressCachePatterns, CacheWarmer } from './CacheInvalidation.js';
9
+ export { CachedWordPressClient } from '../client/CachedWordPressClient.js';
10
+
11
+ export type {
12
+ CacheEntry,
13
+ CacheStats,
14
+ CacheConfig
15
+ } from './CacheManager.js';
16
+
17
+ export type {
18
+ HttpCacheOptions,
19
+ CachedResponse,
20
+ RequestOptions
21
+ } from './HttpCacheWrapper.js';
22
+
23
+ export type {
24
+ InvalidationRule,
25
+ InvalidationEvent
26
+ } from './CacheInvalidation.js';