mcp-wordpress 2.6.4 → 2.7.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 (332) hide show
  1. package/README.md +1 -1
  2. package/dist/cache/CacheInvalidation.d.ts +25 -6
  3. package/dist/cache/CacheInvalidation.d.ts.map +1 -1
  4. package/dist/cache/CacheInvalidation.js +168 -16
  5. package/dist/cache/CacheInvalidation.js.map +1 -1
  6. package/dist/cache/HttpCacheWrapper.d.ts.map +1 -1
  7. package/dist/cache/HttpCacheWrapper.js +3 -4
  8. package/dist/cache/HttpCacheWrapper.js.map +1 -1
  9. package/dist/cache/SEOCacheManager.d.ts +150 -0
  10. package/dist/cache/SEOCacheManager.d.ts.map +1 -0
  11. package/dist/cache/SEOCacheManager.js +275 -0
  12. package/dist/cache/SEOCacheManager.js.map +1 -0
  13. package/dist/client/SEOWordPressClient.d.ts +164 -0
  14. package/dist/client/SEOWordPressClient.d.ts.map +1 -0
  15. package/dist/client/SEOWordPressClient.js +674 -0
  16. package/dist/client/SEOWordPressClient.js.map +1 -0
  17. package/dist/client/api.d.ts.map +1 -1
  18. package/dist/client/api.js +50 -20
  19. package/dist/client/api.js.map +1 -1
  20. package/dist/client/auth.js +19 -19
  21. package/dist/client/auth.js.map +1 -1
  22. package/dist/client/index.d.ts +11 -0
  23. package/dist/client/index.d.ts.map +1 -0
  24. package/dist/client/index.js +14 -0
  25. package/dist/client/index.js.map +1 -0
  26. package/dist/client/managers/AuthManager.d.ts +39 -0
  27. package/dist/client/managers/AuthManager.d.ts.map +1 -0
  28. package/dist/client/managers/AuthManager.js +142 -0
  29. package/dist/client/managers/AuthManager.js.map +1 -0
  30. package/dist/client/managers/AuthenticationManager.d.ts.map +1 -1
  31. package/dist/client/managers/AuthenticationManager.js +10 -9
  32. package/dist/client/managers/AuthenticationManager.js.map +1 -1
  33. package/dist/client/managers/BaseManager.d.ts.map +1 -1
  34. package/dist/client/managers/BaseManager.js +12 -0
  35. package/dist/client/managers/BaseManager.js.map +1 -1
  36. package/dist/client/managers/ComposedAuthenticationManager.d.ts +94 -0
  37. package/dist/client/managers/ComposedAuthenticationManager.d.ts.map +1 -0
  38. package/dist/client/managers/ComposedAuthenticationManager.js +340 -0
  39. package/dist/client/managers/ComposedAuthenticationManager.js.map +1 -0
  40. package/dist/client/managers/ComposedManagerFactory.d.ts +104 -0
  41. package/dist/client/managers/ComposedManagerFactory.d.ts.map +1 -0
  42. package/dist/client/managers/ComposedManagerFactory.js +180 -0
  43. package/dist/client/managers/ComposedManagerFactory.js.map +1 -0
  44. package/dist/client/managers/ComposedRequestManager.d.ts +82 -0
  45. package/dist/client/managers/ComposedRequestManager.d.ts.map +1 -0
  46. package/dist/client/managers/ComposedRequestManager.js +260 -0
  47. package/dist/client/managers/ComposedRequestManager.js.map +1 -0
  48. package/dist/client/managers/JWTAuthImplementation.d.ts +86 -0
  49. package/dist/client/managers/JWTAuthImplementation.d.ts.map +1 -0
  50. package/dist/client/managers/JWTAuthImplementation.js +240 -0
  51. package/dist/client/managers/JWTAuthImplementation.js.map +1 -0
  52. package/dist/client/managers/ManagersIndex.d.ts +6 -0
  53. package/dist/client/managers/ManagersIndex.d.ts.map +1 -0
  54. package/dist/client/managers/ManagersIndex.js +6 -0
  55. package/dist/client/managers/ManagersIndex.js.map +1 -0
  56. package/dist/client/managers/RequestManager.d.ts.map +1 -1
  57. package/dist/client/managers/RequestManager.js +5 -3
  58. package/dist/client/managers/RequestManager.js.map +1 -1
  59. package/dist/client/managers/composed/MigrationAdapter.d.ts +80 -0
  60. package/dist/client/managers/composed/MigrationAdapter.d.ts.map +1 -0
  61. package/dist/client/managers/composed/MigrationAdapter.js +214 -0
  62. package/dist/client/managers/composed/MigrationAdapter.js.map +1 -0
  63. package/dist/client/managers/composed/index.d.ts +23 -0
  64. package/dist/client/managers/composed/index.d.ts.map +1 -0
  65. package/dist/client/managers/composed/index.js +26 -0
  66. package/dist/client/managers/composed/index.js.map +1 -0
  67. package/dist/client/managers/implementations/ConfigurationProviderImpl.d.ts +27 -0
  68. package/dist/client/managers/implementations/ConfigurationProviderImpl.d.ts.map +1 -0
  69. package/dist/client/managers/implementations/ConfigurationProviderImpl.js +41 -0
  70. package/dist/client/managers/implementations/ConfigurationProviderImpl.js.map +1 -0
  71. package/dist/client/managers/implementations/ErrorHandlerImpl.d.ts +31 -0
  72. package/dist/client/managers/implementations/ErrorHandlerImpl.d.ts.map +1 -0
  73. package/dist/client/managers/implementations/ErrorHandlerImpl.js +73 -0
  74. package/dist/client/managers/implementations/ErrorHandlerImpl.js.map +1 -0
  75. package/dist/client/managers/implementations/ParameterValidatorImpl.d.ts +47 -0
  76. package/dist/client/managers/implementations/ParameterValidatorImpl.d.ts.map +1 -0
  77. package/dist/client/managers/implementations/ParameterValidatorImpl.js +141 -0
  78. package/dist/client/managers/implementations/ParameterValidatorImpl.js.map +1 -0
  79. package/dist/client/managers/interfaces/ManagerInterfaces.d.ts +147 -0
  80. package/dist/client/managers/interfaces/ManagerInterfaces.d.ts.map +1 -0
  81. package/dist/client/managers/interfaces/ManagerInterfaces.js +6 -0
  82. package/dist/client/managers/interfaces/ManagerInterfaces.js.map +1 -0
  83. package/dist/config/Config.d.ts +30 -0
  84. package/dist/config/Config.d.ts.map +1 -1
  85. package/dist/config/Config.js +30 -0
  86. package/dist/config/Config.js.map +1 -1
  87. package/dist/config/ConfigurationSchema.d.ts +75 -198
  88. package/dist/config/ConfigurationSchema.d.ts.map +1 -1
  89. package/dist/config/ConfigurationSchema.js +17 -17
  90. package/dist/config/ConfigurationSchema.js.map +1 -1
  91. package/dist/config/ServerConfiguration.d.ts +2 -2
  92. package/dist/config/ServerConfiguration.d.ts.map +1 -1
  93. package/dist/config/ServerConfiguration.js +15 -13
  94. package/dist/config/ServerConfiguration.js.map +1 -1
  95. package/dist/config/index.d.ts +8 -0
  96. package/dist/config/index.d.ts.map +1 -0
  97. package/dist/config/index.js +11 -0
  98. package/dist/config/index.js.map +1 -0
  99. package/dist/docs/DocumentationGenerator.js +2 -2
  100. package/dist/docs/DocumentationGenerator.js.map +1 -1
  101. package/dist/dxt-entry.js +3 -3
  102. package/dist/dxt-entry.js.map +1 -1
  103. package/dist/index.d.ts +1 -0
  104. package/dist/index.d.ts.map +1 -1
  105. package/dist/index.js +38 -37
  106. package/dist/index.js.map +1 -1
  107. package/dist/performance/MetricsCollector.d.ts.map +1 -1
  108. package/dist/performance/MetricsCollector.js +5 -4
  109. package/dist/performance/MetricsCollector.js.map +1 -1
  110. package/dist/security/AISecurityScanner.js +7 -7
  111. package/dist/security/AISecurityScanner.js.map +1 -1
  112. package/dist/security/AutomatedRemediation.d.ts.map +1 -1
  113. package/dist/security/AutomatedRemediation.js +11 -11
  114. package/dist/security/AutomatedRemediation.js.map +1 -1
  115. package/dist/security/InputValidator.d.ts +50 -126
  116. package/dist/security/InputValidator.d.ts.map +1 -1
  117. package/dist/security/InputValidator.js +9 -9
  118. package/dist/security/InputValidator.js.map +1 -1
  119. package/dist/security/SecurityCIPipeline.d.ts +47 -5
  120. package/dist/security/SecurityCIPipeline.d.ts.map +1 -1
  121. package/dist/security/SecurityCIPipeline.js +390 -49
  122. package/dist/security/SecurityCIPipeline.js.map +1 -1
  123. package/dist/security/SecurityConfigManager.js +10 -10
  124. package/dist/security/SecurityConfigManager.js.map +1 -1
  125. package/dist/security/SecurityMonitoring.js +4 -4
  126. package/dist/security/SecurityMonitoring.js.map +1 -1
  127. package/dist/security/SecurityReviewer.d.ts.map +1 -1
  128. package/dist/security/SecurityReviewer.js +13 -6
  129. package/dist/security/SecurityReviewer.js.map +1 -1
  130. package/dist/security/index.js +3 -3
  131. package/dist/security/index.js.map +1 -1
  132. package/dist/server/ConnectionTester.js +5 -5
  133. package/dist/server/ConnectionTester.js.map +1 -1
  134. package/dist/server/ToolRegistry.d.ts +2 -2
  135. package/dist/server/ToolRegistry.d.ts.map +1 -1
  136. package/dist/server/ToolRegistry.js +7 -6
  137. package/dist/server/ToolRegistry.js.map +1 -1
  138. package/dist/server/index.d.ts +7 -0
  139. package/dist/server/index.d.ts.map +1 -0
  140. package/dist/server/index.js +9 -0
  141. package/dist/server/index.js.map +1 -0
  142. package/dist/tools/BaseToolManager.d.ts.map +1 -1
  143. package/dist/tools/BaseToolManager.js +11 -11
  144. package/dist/tools/BaseToolManager.js.map +1 -1
  145. package/dist/tools/auth.d.ts.map +1 -1
  146. package/dist/tools/auth.js +7 -7
  147. package/dist/tools/auth.js.map +1 -1
  148. package/dist/tools/comments.d.ts.map +1 -1
  149. package/dist/tools/comments.js +14 -14
  150. package/dist/tools/comments.js.map +1 -1
  151. package/dist/tools/index.d.ts +1 -0
  152. package/dist/tools/index.d.ts.map +1 -1
  153. package/dist/tools/index.js +1 -0
  154. package/dist/tools/index.js.map +1 -1
  155. package/dist/tools/media.d.ts.map +1 -1
  156. package/dist/tools/media.js +14 -11
  157. package/dist/tools/media.js.map +1 -1
  158. package/dist/tools/pages.d.ts.map +1 -1
  159. package/dist/tools/pages.js +12 -12
  160. package/dist/tools/pages.js.map +1 -1
  161. package/dist/tools/performance.d.ts.map +1 -1
  162. package/dist/tools/performance.js +13 -11
  163. package/dist/tools/performance.js.map +1 -1
  164. package/dist/tools/posts/PostHandlers.d.ts.map +1 -1
  165. package/dist/tools/posts/PostHandlers.js +16 -16
  166. package/dist/tools/posts/PostHandlers.js.map +1 -1
  167. package/dist/tools/posts/PostToolDefinitions.d.ts.map +1 -1
  168. package/dist/tools/posts/index.d.ts.map +1 -1
  169. package/dist/tools/seo/BulkOperations.d.ts +113 -0
  170. package/dist/tools/seo/BulkOperations.d.ts.map +1 -0
  171. package/dist/tools/seo/BulkOperations.js +398 -0
  172. package/dist/tools/seo/BulkOperations.js.map +1 -0
  173. package/dist/tools/seo/SEOHandlers.d.ts +55 -0
  174. package/dist/tools/seo/SEOHandlers.d.ts.map +1 -0
  175. package/dist/tools/seo/SEOHandlers.js +255 -0
  176. package/dist/tools/seo/SEOHandlers.js.map +1 -0
  177. package/dist/tools/seo/SEOToolDefinitions.d.ts +59 -0
  178. package/dist/tools/seo/SEOToolDefinitions.d.ts.map +1 -0
  179. package/dist/tools/seo/SEOToolDefinitions.js +385 -0
  180. package/dist/tools/seo/SEOToolDefinitions.js.map +1 -0
  181. package/dist/tools/seo/SEOTools.d.ts +203 -0
  182. package/dist/tools/seo/SEOTools.d.ts.map +1 -0
  183. package/dist/tools/seo/SEOTools.js +708 -0
  184. package/dist/tools/seo/SEOTools.js.map +1 -0
  185. package/dist/tools/seo/analyzers/ContentAnalyzer.d.ts +94 -0
  186. package/dist/tools/seo/analyzers/ContentAnalyzer.d.ts.map +1 -0
  187. package/dist/tools/seo/analyzers/ContentAnalyzer.js +402 -0
  188. package/dist/tools/seo/analyzers/ContentAnalyzer.js.map +1 -0
  189. package/dist/tools/seo/auditors/SiteAuditor.d.ts +121 -0
  190. package/dist/tools/seo/auditors/SiteAuditor.d.ts.map +1 -0
  191. package/dist/tools/seo/auditors/SiteAuditor.js +600 -0
  192. package/dist/tools/seo/auditors/SiteAuditor.js.map +1 -0
  193. package/dist/tools/seo/generators/MetaGenerator.d.ts +128 -0
  194. package/dist/tools/seo/generators/MetaGenerator.d.ts.map +1 -0
  195. package/dist/tools/seo/generators/MetaGenerator.js +547 -0
  196. package/dist/tools/seo/generators/MetaGenerator.js.map +1 -0
  197. package/dist/tools/seo/generators/SchemaGenerator.d.ts +204 -0
  198. package/dist/tools/seo/generators/SchemaGenerator.d.ts.map +1 -0
  199. package/dist/tools/seo/generators/SchemaGenerator.js +670 -0
  200. package/dist/tools/seo/generators/SchemaGenerator.js.map +1 -0
  201. package/dist/tools/seo/index.d.ts +17 -0
  202. package/dist/tools/seo/index.d.ts.map +1 -0
  203. package/dist/tools/seo/index.js +18 -0
  204. package/dist/tools/seo/index.js.map +1 -0
  205. package/dist/tools/seo/optimizers/InternalLinkingSuggester.d.ts +186 -0
  206. package/dist/tools/seo/optimizers/InternalLinkingSuggester.d.ts.map +1 -0
  207. package/dist/tools/seo/optimizers/InternalLinkingSuggester.js +683 -0
  208. package/dist/tools/seo/optimizers/InternalLinkingSuggester.js.map +1 -0
  209. package/dist/tools/site.d.ts.map +1 -1
  210. package/dist/tools/site.js +12 -12
  211. package/dist/tools/site.js.map +1 -1
  212. package/dist/tools/taxonomies.d.ts.map +1 -1
  213. package/dist/tools/taxonomies.js +20 -20
  214. package/dist/tools/taxonomies.js.map +1 -1
  215. package/dist/tools/users.d.ts.map +1 -1
  216. package/dist/tools/users.js +12 -12
  217. package/dist/tools/users.js.map +1 -1
  218. package/dist/types/client.d.ts +8 -6
  219. package/dist/types/client.d.ts.map +1 -1
  220. package/dist/types/client.js.map +1 -1
  221. package/dist/types/seo.d.ts +473 -0
  222. package/dist/types/seo.d.ts.map +1 -0
  223. package/dist/types/seo.js +94 -0
  224. package/dist/types/seo.js.map +1 -0
  225. package/dist/utils/enhancedError.js +1 -1
  226. package/dist/utils/enhancedError.js.map +1 -1
  227. package/dist/utils/error.d.ts.map +1 -1
  228. package/dist/utils/error.js +0 -1
  229. package/dist/utils/error.js.map +1 -1
  230. package/dist/utils/index.d.ts +12 -0
  231. package/dist/utils/index.d.ts.map +1 -0
  232. package/dist/utils/index.js +18 -0
  233. package/dist/utils/index.js.map +1 -0
  234. package/dist/utils/logger.js +3 -3
  235. package/dist/utils/logger.js.map +1 -1
  236. package/dist/utils/toolWrapper.d.ts +2 -2
  237. package/dist/utils/toolWrapper.js +8 -8
  238. package/dist/utils/toolWrapper.js.map +1 -1
  239. package/dist/utils/validation/core.d.ts.map +1 -1
  240. package/dist/utils/validation/core.js.map +1 -1
  241. package/dist/utils/validation/index.d.ts.map +1 -1
  242. package/dist/utils/validation/index.js.map +1 -1
  243. package/dist/utils/validation/network.js +3 -3
  244. package/dist/utils/validation/network.js.map +1 -1
  245. package/dist/utils/validation/rateLimit.js.map +1 -1
  246. package/dist/utils/validation/security.js.map +1 -1
  247. package/dist/utils/validation/wordpress.js.map +1 -1
  248. package/dist/utils/version.d.ts +144 -0
  249. package/dist/utils/version.d.ts.map +1 -0
  250. package/dist/utils/version.js +318 -0
  251. package/dist/utils/version.js.map +1 -0
  252. package/package.json +21 -55
  253. package/src/cache/CacheInvalidation.ts +183 -20
  254. package/src/cache/HttpCacheWrapper.ts +8 -5
  255. package/src/cache/SEOCacheManager.ts +330 -0
  256. package/src/cache/__tests__/CacheInvalidation.test.ts +6 -11
  257. package/src/cache/__tests__/CachedWordPressClient.test.ts +37 -62
  258. package/src/client/SEOWordPressClient.ts +876 -0
  259. package/src/client/api.ts +50 -21
  260. package/src/client/auth.ts +19 -19
  261. package/src/client/index.ts +16 -0
  262. package/src/client/managers/AuthManager.ts +175 -0
  263. package/src/client/managers/AuthenticationManager.ts +16 -14
  264. package/src/client/managers/BaseManager.ts +24 -5
  265. package/src/client/managers/ComposedAuthenticationManager.ts +409 -0
  266. package/src/client/managers/ComposedManagerFactory.ts +231 -0
  267. package/src/client/managers/ComposedRequestManager.ts +336 -0
  268. package/src/client/managers/JWTAuthImplementation.ts +326 -0
  269. package/src/client/managers/ManagersIndex.ts +6 -0
  270. package/src/client/managers/RequestManager.ts +9 -7
  271. package/src/client/managers/composed/MigrationAdapter.ts +263 -0
  272. package/src/client/managers/composed/index.ts +47 -0
  273. package/src/client/managers/implementations/ConfigurationProviderImpl.ts +52 -0
  274. package/src/client/managers/implementations/ErrorHandlerImpl.ts +102 -0
  275. package/src/client/managers/implementations/ParameterValidatorImpl.ts +221 -0
  276. package/src/client/managers/interfaces/ManagerInterfaces.ts +171 -0
  277. package/src/config/Config.ts +63 -0
  278. package/src/config/ConfigurationSchema.ts +17 -17
  279. package/src/config/ServerConfiguration.ts +18 -16
  280. package/src/config/index.ts +13 -0
  281. package/src/docs/DocumentationGenerator.ts +2 -2
  282. package/src/dxt-entry.ts +3 -3
  283. package/src/index.ts +43 -43
  284. package/src/performance/MetricsCollector.ts +15 -11
  285. package/src/security/AISecurityScanner.ts +7 -7
  286. package/src/security/AutomatedRemediation.ts +13 -11
  287. package/src/security/InputValidator.ts +10 -9
  288. package/src/security/SecurityCIPipeline.ts +494 -56
  289. package/src/security/SecurityConfigManager.ts +10 -10
  290. package/src/security/SecurityMonitoring.ts +5 -5
  291. package/src/security/SecurityReviewer.ts +13 -6
  292. package/src/security/index.ts +3 -3
  293. package/src/server/ConnectionTester.ts +5 -5
  294. package/src/server/ToolRegistry.ts +9 -8
  295. package/src/server/index.ts +10 -0
  296. package/src/tools/BaseToolManager.ts +55 -83
  297. package/src/tools/auth.ts +21 -12
  298. package/src/tools/comments.ts +23 -19
  299. package/src/tools/index.ts +1 -0
  300. package/src/tools/media.ts +23 -20
  301. package/src/tools/pages.ts +20 -13
  302. package/src/tools/performance.ts +101 -32
  303. package/src/tools/posts/PostHandlers.ts +23 -23
  304. package/src/tools/posts/PostToolDefinitions.ts +1 -1
  305. package/src/tools/posts/index.ts +2 -2
  306. package/src/tools/seo/BulkOperations.ts +557 -0
  307. package/src/tools/seo/SEOHandlers.ts +296 -0
  308. package/src/tools/seo/SEOToolDefinitions.ts +402 -0
  309. package/src/tools/seo/SEOTools.ts +871 -0
  310. package/src/tools/seo/analyzers/ContentAnalyzer.ts +493 -0
  311. package/src/tools/seo/auditors/SiteAuditor.ts +787 -0
  312. package/src/tools/seo/generators/MetaGenerator.ts +694 -0
  313. package/src/tools/seo/generators/SchemaGenerator.ts +955 -0
  314. package/src/tools/seo/index.ts +47 -0
  315. package/src/tools/seo/optimizers/InternalLinkingSuggester.ts +934 -0
  316. package/src/tools/site.ts +27 -26
  317. package/src/tools/taxonomies.ts +29 -25
  318. package/src/tools/users.ts +20 -13
  319. package/src/types/client.ts +8 -6
  320. package/src/types/seo.ts +546 -0
  321. package/src/utils/enhancedError.ts +1 -1
  322. package/src/utils/error.ts +1 -2
  323. package/src/utils/index.ts +23 -0
  324. package/src/utils/logger.ts +3 -3
  325. package/src/utils/toolWrapper.ts +10 -10
  326. package/src/utils/validation/core.ts +2 -2
  327. package/src/utils/validation/index.ts +2 -2
  328. package/src/utils/validation/network.ts +5 -5
  329. package/src/utils/validation/rateLimit.ts +1 -1
  330. package/src/utils/validation/security.ts +1 -1
  331. package/src/utils/validation/wordpress.ts +1 -1
  332. package/src/utils/version.ts +402 -0
@@ -0,0 +1,336 @@
1
+ /**
2
+ * Composed Request Manager
3
+ * Uses composition instead of inheritance for better testability and flexibility
4
+ */
5
+
6
+ import type { HTTPMethod, RequestOptions, ClientStats, WordPressClientConfig } from "@/types/client.js";
7
+ import { WordPressAPIError, RateLimitError } from "@/types/client.js";
8
+ import { config } from "@/config/Config.js";
9
+ import { startTimer } from "@/utils/debug.js";
10
+ import { getUserAgent } from "@/utils/version.js";
11
+
12
+ import type {
13
+ ConfigurationProvider,
14
+ ErrorHandler,
15
+ ParameterValidator,
16
+ AuthenticationProvider,
17
+ RequestHandler,
18
+ } from "./interfaces/ManagerInterfaces.js";
19
+
20
+ import { ConfigurationProviderImpl } from "./implementations/ConfigurationProviderImpl.js";
21
+ import { ErrorHandlerImpl } from "./implementations/ErrorHandlerImpl.js";
22
+ import { ParameterValidatorImpl } from "./implementations/ParameterValidatorImpl.js";
23
+
24
+ interface ComposedRequestManagerDependencies {
25
+ configProvider: ConfigurationProvider;
26
+ errorHandler: ErrorHandler;
27
+ validator: ParameterValidator;
28
+ authProvider: AuthenticationProvider;
29
+ }
30
+
31
+ export class ComposedRequestManager implements RequestHandler {
32
+ private stats: ClientStats;
33
+ private lastRequestTime: number = 0;
34
+ private requestInterval: number;
35
+ private initialized: boolean = false;
36
+
37
+ constructor(private dependencies: ComposedRequestManagerDependencies) {
38
+ this.requestInterval = 60000 / config().security.rateLimit;
39
+ this.stats = {
40
+ totalRequests: 0,
41
+ successfulRequests: 0,
42
+ failedRequests: 0,
43
+ averageResponseTime: 0,
44
+ rateLimitHits: 0,
45
+ authFailures: 0,
46
+ errors: 0,
47
+ };
48
+ }
49
+
50
+ /**
51
+ * Factory method to create ComposedRequestManager with default implementations
52
+ */
53
+ static create(clientConfig: WordPressClientConfig, authProvider: AuthenticationProvider): ComposedRequestManager {
54
+ const configProvider = new ConfigurationProviderImpl(clientConfig);
55
+ const errorHandler = new ErrorHandlerImpl(configProvider);
56
+ const validator = new ParameterValidatorImpl();
57
+
58
+ return new ComposedRequestManager({
59
+ configProvider,
60
+ errorHandler,
61
+ validator,
62
+ authProvider,
63
+ });
64
+ }
65
+
66
+ /**
67
+ * Initialize the manager
68
+ */
69
+ async initialize(): Promise<void> {
70
+ if (this.initialized) {
71
+ return;
72
+ }
73
+
74
+ try {
75
+ // Validate configuration
76
+ if (!this.dependencies.configProvider.config.baseUrl) {
77
+ throw new Error("Base URL is required");
78
+ }
79
+
80
+ // Ensure authentication is ready
81
+ await this.dependencies.authProvider.authenticate();
82
+
83
+ this.initialized = true;
84
+ } catch (error) {
85
+ this.dependencies.errorHandler.handleError(error, "initialize request manager");
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Make HTTP request with retry logic and rate limiting
91
+ */
92
+ async request<T>(method: HTTPMethod, endpoint: string, data?: unknown, options: RequestOptions = {}): Promise<T> {
93
+ this.ensureInitialized();
94
+
95
+ const timer = startTimer();
96
+ this.stats.totalRequests++;
97
+
98
+ try {
99
+ // Validate inputs
100
+ this.dependencies.validator.validateString(method, "method", { required: true });
101
+ this.dependencies.validator.validateString(endpoint, "endpoint", { required: true });
102
+
103
+ await this.enforceRateLimit();
104
+
105
+ const response = await this.makeRequestWithRetry(method, endpoint, data, options);
106
+
107
+ this.stats.successfulRequests++;
108
+ this.updateAverageResponseTime(timer.end());
109
+
110
+ this.dependencies.errorHandler.logSuccess(`${method} ${endpoint}`, { responseTime: timer.end() });
111
+
112
+ return response as T;
113
+ } catch (error) {
114
+ this.stats.failedRequests++;
115
+ this.stats.errors++;
116
+
117
+ if (error instanceof RateLimitError) {
118
+ this.stats.rateLimitHits++;
119
+ }
120
+
121
+ this.dependencies.errorHandler.handleError(error, `${method} ${endpoint}`);
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Get request statistics
127
+ */
128
+ getStats(): ClientStats {
129
+ return { ...this.stats };
130
+ }
131
+
132
+ /**
133
+ * Reset statistics
134
+ */
135
+ resetStats(): void {
136
+ this.stats = {
137
+ totalRequests: 0,
138
+ successfulRequests: 0,
139
+ failedRequests: 0,
140
+ averageResponseTime: 0,
141
+ rateLimitHits: 0,
142
+ authFailures: 0,
143
+ errors: 0,
144
+ };
145
+ }
146
+
147
+ /**
148
+ * Enforce rate limiting
149
+ */
150
+ private async enforceRateLimit(): Promise<void> {
151
+ const now = Date.now();
152
+ const timeSinceLastRequest = now - this.lastRequestTime;
153
+
154
+ if (timeSinceLastRequest < this.requestInterval) {
155
+ const delay = this.requestInterval - timeSinceLastRequest;
156
+ await new Promise((resolve) => setTimeout(resolve, delay));
157
+ }
158
+
159
+ this.lastRequestTime = Date.now();
160
+ }
161
+
162
+ /**
163
+ * Make request with retry logic
164
+ */
165
+ private async makeRequestWithRetry<T>(
166
+ method: HTTPMethod,
167
+ endpoint: string,
168
+ data?: unknown,
169
+ options: RequestOptions = {},
170
+ attempt: number = 1,
171
+ ): Promise<T> {
172
+ const maxRetries = 3; // Use default retries for composed manager
173
+
174
+ try {
175
+ return await this.makeRequest<T>(method, endpoint, data, options);
176
+ } catch (error) {
177
+ if (attempt <= maxRetries && this.shouldRetry(error)) {
178
+ const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
179
+ await new Promise((resolve) => setTimeout(resolve, delay));
180
+ return this.makeRequestWithRetry<T>(method, endpoint, data, options, attempt + 1);
181
+ }
182
+ throw error;
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Make actual HTTP request
188
+ */
189
+ private async makeRequest<T>(
190
+ method: HTTPMethod,
191
+ endpoint: string,
192
+ data?: unknown,
193
+ options: RequestOptions = {},
194
+ ): Promise<T> {
195
+ const url = this.buildUrl(endpoint);
196
+ const requestOptions = await this.buildRequestOptions(method, data, options);
197
+
198
+ const response = await fetch(url, requestOptions);
199
+
200
+ if (!response.ok) {
201
+ await this.handleHttpError(response);
202
+ }
203
+
204
+ const contentType = response.headers.get("content-type");
205
+
206
+ if (contentType && contentType.includes("application/json")) {
207
+ return (await response.json()) as T;
208
+ }
209
+
210
+ return (await response.text()) as unknown as T;
211
+ }
212
+
213
+ /**
214
+ * Build full URL for request
215
+ */
216
+ private buildUrl(endpoint: string): string {
217
+ const baseUrl = this.dependencies.configProvider.config.baseUrl;
218
+ const cleanBase = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
219
+ const cleanEndpoint = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
220
+
221
+ return `${cleanBase}/wp-json${cleanEndpoint}`;
222
+ }
223
+
224
+ /**
225
+ * Build request options with authentication
226
+ */
227
+ private async buildRequestOptions(
228
+ method: HTTPMethod,
229
+ data?: unknown,
230
+ options: RequestOptions = {},
231
+ ): Promise<RequestInit> {
232
+ const authHeaders = this.dependencies.authProvider.getAuthHeaders();
233
+ const timeout = this.dependencies.configProvider.config.timeout || 30000;
234
+
235
+ const headers = {
236
+ "Content-Type": "application/json",
237
+ Accept: "application/json",
238
+ "User-Agent": getUserAgent(),
239
+ ...authHeaders,
240
+ ...options.headers,
241
+ };
242
+
243
+ const requestOptions: RequestInit = {
244
+ method,
245
+ headers,
246
+ signal: typeof AbortSignal !== "undefined" && AbortSignal.timeout ? AbortSignal.timeout(timeout) : null,
247
+ };
248
+
249
+ if (data && (method === "POST" || method === "PUT" || method === "PATCH")) {
250
+ requestOptions.body = JSON.stringify(data);
251
+ }
252
+
253
+ return requestOptions;
254
+ }
255
+
256
+ /**
257
+ * Handle HTTP error responses
258
+ */
259
+ private async handleHttpError(response: Response): Promise<never> {
260
+ const statusCode = response.status;
261
+
262
+ if (statusCode === 401) {
263
+ this.stats.authFailures++;
264
+
265
+ // Try to refresh authentication
266
+ try {
267
+ await this.dependencies.authProvider.handleAuthFailure(new Error(`HTTP ${statusCode}`));
268
+ // If refresh succeeds, the caller should retry
269
+ throw new WordPressAPIError("Authentication refreshed, retry needed", 401, "auth_refreshed");
270
+ } catch (_authError) {
271
+ throw new WordPressAPIError("Authentication failed", 401, "auth_failed");
272
+ }
273
+ }
274
+
275
+ if (statusCode === 429) {
276
+ const retryAfter = response.headers.get("retry-after");
277
+ const delay = retryAfter ? parseInt(retryAfter, 10) : 60;
278
+ throw new RateLimitError("Rate limit exceeded", delay);
279
+ }
280
+
281
+ let errorMessage = `HTTP ${statusCode}: ${response.statusText}`;
282
+
283
+ try {
284
+ const errorBody = (await response.json()) as { message?: string };
285
+ if (errorBody.message) {
286
+ errorMessage = errorBody.message;
287
+ }
288
+ } catch {
289
+ // Ignore JSON parsing errors for non-JSON error responses
290
+ }
291
+
292
+ throw new WordPressAPIError(errorMessage, statusCode, "http_error");
293
+ }
294
+
295
+ /**
296
+ * Determine if error is retryable
297
+ */
298
+ private shouldRetry(error: unknown): boolean {
299
+ if (error instanceof WordPressAPIError) {
300
+ const nonRetryableCodes = [400, 401, 403, 404];
301
+ return !nonRetryableCodes.includes(error.statusCode || 500);
302
+ }
303
+
304
+ if (error instanceof Error) {
305
+ const retryableErrors = ["ECONNRESET", "ETIMEDOUT", "ENOTFOUND", "EAI_AGAIN"];
306
+ return retryableErrors.some((code) => error.message.includes(code));
307
+ }
308
+
309
+ return false;
310
+ }
311
+
312
+ /**
313
+ * Update average response time with new measurement
314
+ */
315
+ private updateAverageResponseTime(newTime: number): void {
316
+ const total = this.stats.averageResponseTime * (this.stats.successfulRequests - 1) + newTime;
317
+ this.stats.averageResponseTime = Math.round(total / this.stats.successfulRequests);
318
+ }
319
+
320
+ /**
321
+ * Ensure manager is initialized before operations
322
+ */
323
+ private ensureInitialized(): void {
324
+ if (!this.initialized) {
325
+ throw new Error("ComposedRequestManager not initialized. Call initialize() first.");
326
+ }
327
+ }
328
+
329
+ /**
330
+ * Cleanup resources
331
+ */
332
+ dispose(): void {
333
+ // Cleanup any resources, timers, etc.
334
+ this.initialized = false;
335
+ }
336
+ }
@@ -0,0 +1,326 @@
1
+ /**
2
+ * JWT Authentication Implementation
3
+ * Complete JWT authentication with token refresh and RequestManager integration
4
+ */
5
+
6
+ import type { AuthConfig, RequestOptions } from "@/types/client.js";
7
+ import { AuthenticationError } from "@/types/client.js";
8
+ import { AUTH_METHODS } from "@/types/wordpress.js";
9
+ import { LoggerFactory } from "@/utils/logger.js";
10
+ import type { RequestManager } from "./RequestManager.js";
11
+
12
+ export interface JWTTokenResponse {
13
+ token: string;
14
+ user_email: string;
15
+ user_nicename: string;
16
+ user_display_name: string;
17
+ expires_in?: number;
18
+ }
19
+
20
+ export interface JWTValidateResponse {
21
+ code: string;
22
+ data: {
23
+ status: number;
24
+ };
25
+ }
26
+
27
+ export interface JWTRefreshResponse {
28
+ token: string;
29
+ expires_in?: number;
30
+ }
31
+
32
+ export class JWTAuthImplementation {
33
+ private logger = LoggerFactory.api();
34
+ private jwtToken: string | null = null;
35
+ private tokenExpiry: number | null = null;
36
+ private refreshTokenValue: string | null = null;
37
+
38
+ constructor(
39
+ private requestManager: RequestManager,
40
+ private authConfig: AuthConfig
41
+ ) {}
42
+
43
+ /**
44
+ * Complete JWT authentication implementation
45
+ */
46
+ async authenticateJWT(): Promise<void> {
47
+ if (!this.authConfig.username || !this.authConfig.password) {
48
+ throw new AuthenticationError("JWT authentication requires username and password", AUTH_METHODS.JWT);
49
+ }
50
+
51
+ try {
52
+ this.logger.info("Starting JWT authentication", {
53
+ username: this.authConfig.username,
54
+ endpoint: "jwt-auth/v1/token"
55
+ });
56
+
57
+ const response = await this.requestManager.request<JWTTokenResponse>(
58
+ "POST",
59
+ "jwt-auth/v1/token",
60
+ {
61
+ username: this.authConfig.username,
62
+ password: this.authConfig.password,
63
+ },
64
+ {
65
+ skipAuth: true, // Don't use auth headers for the auth request itself
66
+ timeout: 10000,
67
+ } as RequestOptions & { skipAuth: boolean }
68
+ );
69
+
70
+ if (!response.token) {
71
+ throw new AuthenticationError("JWT token not received in response", AUTH_METHODS.JWT);
72
+ }
73
+
74
+ // Store the JWT token
75
+ this.jwtToken = response.token;
76
+
77
+ // Calculate token expiry (default to 24 hours if not provided)
78
+ const expiresInSeconds = response.expires_in || (24 * 60 * 60);
79
+ this.tokenExpiry = Date.now() + (expiresInSeconds * 1000);
80
+
81
+ this.logger.info("JWT authentication successful", {
82
+ user: response.user_nicename,
83
+ expiresAt: new Date(this.tokenExpiry).toISOString(),
84
+ });
85
+
86
+ // Test the token by validating it
87
+ await this.validateToken();
88
+
89
+ } catch (error) {
90
+ this.jwtToken = null;
91
+ this.tokenExpiry = null;
92
+ this.logger.error("JWT authentication failed", {
93
+ error: error instanceof Error ? error.message : String(error),
94
+ });
95
+
96
+ if (error instanceof Error) {
97
+ throw new AuthenticationError(`JWT authentication failed: ${error.message}`, AUTH_METHODS.JWT);
98
+ }
99
+ throw new AuthenticationError("JWT authentication failed", AUTH_METHODS.JWT);
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Validate JWT token
105
+ */
106
+ async validateToken(): Promise<boolean> {
107
+ if (!this.jwtToken) {
108
+ return false;
109
+ }
110
+
111
+ try {
112
+ const response = await this.requestManager.request<JWTValidateResponse>(
113
+ "POST",
114
+ "jwt-auth/v1/token/validate",
115
+ {},
116
+ {
117
+ headers: {
118
+ Authorization: `Bearer ${this.jwtToken}`,
119
+ },
120
+ timeout: 5000,
121
+ }
122
+ );
123
+
124
+ const isValid = response.data.status === 200;
125
+
126
+ if (!isValid) {
127
+ this.logger.warn("JWT token validation failed", { response });
128
+ this.jwtToken = null;
129
+ this.tokenExpiry = null;
130
+ }
131
+
132
+ return isValid;
133
+
134
+ } catch (error) {
135
+ this.logger.warn("JWT token validation error", {
136
+ error: error instanceof Error ? error.message : String(error),
137
+ });
138
+ return false;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Refresh JWT token
144
+ */
145
+ async refreshToken(): Promise<void> {
146
+ if (!this.jwtToken) {
147
+ throw new AuthenticationError("No JWT token to refresh", AUTH_METHODS.JWT);
148
+ }
149
+
150
+ try {
151
+ this.logger.debug("Refreshing JWT token");
152
+
153
+ // Some JWT implementations support refresh endpoints
154
+ // First try the refresh endpoint if available
155
+ try {
156
+ const refreshResponse = await this.requestManager.request<JWTRefreshResponse>(
157
+ "POST",
158
+ "jwt-auth/v1/token/refresh",
159
+ {},
160
+ {
161
+ headers: {
162
+ Authorization: `Bearer ${this.jwtToken}`,
163
+ },
164
+ timeout: 5000,
165
+ }
166
+ );
167
+
168
+ if (refreshResponse.token) {
169
+ this.jwtToken = refreshResponse.token;
170
+ const expiresInSeconds = refreshResponse.expires_in || (24 * 60 * 60);
171
+ this.tokenExpiry = Date.now() + (expiresInSeconds * 1000);
172
+
173
+ this.logger.info("JWT token refreshed successfully", {
174
+ expiresAt: new Date(this.tokenExpiry).toISOString(),
175
+ });
176
+ return;
177
+ }
178
+ } catch (_refreshError) {
179
+ this.logger.debug("JWT refresh endpoint not available, falling back to re-authentication");
180
+ }
181
+
182
+ // Fallback: Re-authenticate with original credentials
183
+ if (!this.authConfig.username || !this.authConfig.password) {
184
+ throw new AuthenticationError("Cannot refresh JWT token: original credentials not available", AUTH_METHODS.JWT);
185
+ }
186
+
187
+ this.logger.debug("Re-authenticating to refresh JWT token");
188
+ await this.authenticateJWT();
189
+
190
+ } catch (error) {
191
+ this.jwtToken = null;
192
+ this.tokenExpiry = null;
193
+ this.logger.error("JWT token refresh failed", {
194
+ error: error instanceof Error ? error.message : String(error),
195
+ });
196
+
197
+ throw new AuthenticationError(
198
+ `JWT token refresh failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
199
+ AUTH_METHODS.JWT
200
+ );
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Check if JWT token is expired
206
+ */
207
+ isTokenExpired(): boolean {
208
+ if (!this.tokenExpiry) {
209
+ return true;
210
+ }
211
+
212
+ // Consider token expired if it expires within 5 minutes (300000ms)
213
+ const buffer = 5 * 60 * 1000;
214
+ return Date.now() >= (this.tokenExpiry - buffer);
215
+ }
216
+
217
+ /**
218
+ * Get current JWT token
219
+ */
220
+ getToken(): string | null {
221
+ return this.jwtToken;
222
+ }
223
+
224
+ /**
225
+ * Get token expiry timestamp
226
+ */
227
+ getTokenExpiry(): number | null {
228
+ return this.tokenExpiry;
229
+ }
230
+
231
+ /**
232
+ * Clear JWT token and expiry
233
+ */
234
+ clearToken(): void {
235
+ this.jwtToken = null;
236
+ this.tokenExpiry = null;
237
+ this.refreshTokenValue = null;
238
+ this.logger.debug("JWT token cleared");
239
+ }
240
+
241
+ /**
242
+ * Get JWT auth headers
243
+ */
244
+ getAuthHeaders(): Record<string, string> {
245
+ if (!this.jwtToken) {
246
+ return {};
247
+ }
248
+
249
+ return {
250
+ Authorization: `Bearer ${this.jwtToken}`,
251
+ };
252
+ }
253
+
254
+ /**
255
+ * Check if we have a valid JWT token
256
+ */
257
+ hasValidToken(): boolean {
258
+ return this.jwtToken !== null && !this.isTokenExpired();
259
+ }
260
+
261
+ /**
262
+ * Automatic token refresh if needed
263
+ */
264
+ async ensureValidToken(): Promise<void> {
265
+ if (!this.jwtToken) {
266
+ // No token, need to authenticate
267
+ await this.authenticateJWT();
268
+ return;
269
+ }
270
+
271
+ if (this.isTokenExpired()) {
272
+ // Token expired, need to refresh
273
+ await this.refreshToken();
274
+ return;
275
+ }
276
+
277
+ // Token is still valid
278
+ }
279
+
280
+ /**
281
+ * Logout and invalidate token
282
+ */
283
+ async logout(): Promise<void> {
284
+ if (!this.jwtToken) {
285
+ return;
286
+ }
287
+
288
+ try {
289
+ // Try to invalidate the token on the server
290
+ await this.requestManager.request(
291
+ "POST",
292
+ "jwt-auth/v1/token/invalidate",
293
+ {},
294
+ {
295
+ headers: this.getAuthHeaders(),
296
+ timeout: 5000,
297
+ }
298
+ );
299
+
300
+ this.logger.info("JWT token invalidated on server");
301
+ } catch (error) {
302
+ this.logger.warn("Failed to invalidate JWT token on server", {
303
+ error: error instanceof Error ? error.message : String(error),
304
+ });
305
+ }
306
+
307
+ this.clearToken();
308
+ }
309
+
310
+ /**
311
+ * Get token information
312
+ */
313
+ getTokenInfo(): {
314
+ hasToken: boolean;
315
+ isExpired: boolean;
316
+ expiresAt: string | null;
317
+ expiresIn: number | null;
318
+ } {
319
+ return {
320
+ hasToken: this.jwtToken !== null,
321
+ isExpired: this.isTokenExpired(),
322
+ expiresAt: this.tokenExpiry ? new Date(this.tokenExpiry).toISOString() : null,
323
+ expiresIn: this.tokenExpiry ? Math.max(0, this.tokenExpiry - Date.now()) : null,
324
+ };
325
+ }
326
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Managers Index
3
+ * Export all manager classes
4
+ */
5
+
6
+ export { AuthManager, type JWTToken } from "./AuthManager.js";
@@ -4,12 +4,13 @@
4
4
  */
5
5
 
6
6
  // Use native fetch in Node.js 18+
7
- import type { HTTPMethod, RequestOptions, ClientStats, WordPressClientConfig } from "../../types/client.js";
8
- import { WordPressAPIError, RateLimitError } from "../../types/client.js";
9
- import { config } from "../../config/Config.js";
7
+ import type { HTTPMethod, RequestOptions, ClientStats, WordPressClientConfig } from "@/types/client.js";
8
+ import { WordPressAPIError, RateLimitError } from "@/types/client.js";
9
+ import { config } from "@/config/Config.js";
10
10
  import { BaseManager } from "./BaseManager.js";
11
11
  import { AuthenticationManager } from "./AuthenticationManager.js";
12
- import { debug, startTimer } from "../../utils/debug.js";
12
+ import { debug, startTimer } from "@/utils/debug.js";
13
+ import { getUserAgent } from "@/utils/version.js";
13
14
 
14
15
  export class RequestManager extends BaseManager {
15
16
  private stats: ClientStats;
@@ -29,6 +30,7 @@ export class RequestManager extends BaseManager {
29
30
  averageResponseTime: 0,
30
31
  rateLimitHits: 0,
31
32
  authFailures: 0,
33
+ errors: 0,
32
34
  };
33
35
  }
34
36
 
@@ -47,9 +49,9 @@ export class RequestManager extends BaseManager {
47
49
  this.updateAverageResponseTime(timer.end());
48
50
 
49
51
  return response as T;
50
- } catch (error) {
52
+ } catch (_error) {
51
53
  this.stats.failedRequests++;
52
- this.handleError(error, `${method} ${endpoint}`);
54
+ this.handleError(_error, `${method} ${endpoint}`);
53
55
  } finally {
54
56
  this.stats.totalRequests++;
55
57
  }
@@ -118,7 +120,7 @@ export class RequestManager extends BaseManager {
118
120
  method,
119
121
  headers: {
120
122
  "Content-Type": "application/json",
121
- "User-Agent": "MCP-WordPress/1.1.1",
123
+ "User-Agent": getUserAgent(),
122
124
  ...authHeaders, // Add auth headers before custom headers
123
125
  ...options.headers,
124
126
  },