mcp-wordpress 2.4.2 → 2.5.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 (348) hide show
  1. package/README.md +114 -48
  2. package/dist/ajv-patch.js +34 -0
  3. package/dist/cache/CacheInvalidation.d.ts +3 -1
  4. package/dist/cache/CacheInvalidation.d.ts.map +1 -1
  5. package/dist/cache/CacheInvalidation.js +10 -4
  6. package/dist/cache/CacheInvalidation.js.map +1 -1
  7. package/dist/cache/CacheManager.d.ts +3 -2
  8. package/dist/cache/CacheManager.d.ts.map +1 -1
  9. package/dist/cache/CacheManager.js +11 -3
  10. package/dist/cache/CacheManager.js.map +1 -1
  11. package/dist/cache/HttpCacheWrapper.d.ts +7 -6
  12. package/dist/cache/HttpCacheWrapper.d.ts.map +1 -1
  13. package/dist/cache/HttpCacheWrapper.js +8 -5
  14. package/dist/cache/HttpCacheWrapper.js.map +1 -1
  15. package/dist/cache/__tests__/HttpCacheWrapper.test.js +6 -5
  16. package/dist/cache/__tests__/HttpCacheWrapper.test.js.map +1 -1
  17. package/dist/cache/index.d.ts +3 -3
  18. package/dist/cache/index.d.ts.map +1 -1
  19. package/dist/cache/index.js +1 -1
  20. package/dist/cache/index.js.map +1 -1
  21. package/dist/client/CachedWordPressClient.d.ts +23 -9
  22. package/dist/client/CachedWordPressClient.d.ts.map +1 -1
  23. package/dist/client/CachedWordPressClient.js +4 -1
  24. package/dist/client/CachedWordPressClient.js.map +1 -1
  25. package/dist/client/MockWordPressClient.d.ts +2 -1
  26. package/dist/client/MockWordPressClient.d.ts.map +1 -1
  27. package/dist/client/MockWordPressClient.js +3 -1
  28. package/dist/client/MockWordPressClient.js.map +1 -1
  29. package/dist/client/api.d.ts +17 -13
  30. package/dist/client/api.d.ts.map +1 -1
  31. package/dist/client/api.js +135 -30
  32. package/dist/client/api.js.map +1 -1
  33. package/dist/client/auth.d.ts.map +1 -1
  34. package/dist/client/auth.js +2 -3
  35. package/dist/client/auth.js.map +1 -1
  36. package/dist/client/managers/AuthenticationManager.d.ts +55 -2
  37. package/dist/client/managers/AuthenticationManager.d.ts.map +1 -1
  38. package/dist/client/managers/AuthenticationManager.js +269 -71
  39. package/dist/client/managers/AuthenticationManager.js.map +1 -1
  40. package/dist/client/managers/BaseManager.d.ts +3 -3
  41. package/dist/client/managers/BaseManager.d.ts.map +1 -1
  42. package/dist/client/managers/BaseManager.js +11 -5
  43. package/dist/client/managers/BaseManager.js.map +1 -1
  44. package/dist/client/managers/RequestManager.d.ts +2 -2
  45. package/dist/client/managers/RequestManager.d.ts.map +1 -1
  46. package/dist/client/managers/RequestManager.js +25 -12
  47. package/dist/client/managers/RequestManager.js.map +1 -1
  48. package/dist/config/Config.d.ts +155 -0
  49. package/dist/config/Config.d.ts.map +1 -0
  50. package/dist/config/Config.js +215 -0
  51. package/dist/config/Config.js.map +1 -0
  52. package/dist/config/ConfigurationSchema.d.ts +21 -21
  53. package/dist/config/ConfigurationSchema.d.ts.map +1 -1
  54. package/dist/config/ConfigurationSchema.js +19 -2
  55. package/dist/config/ConfigurationSchema.js.map +1 -1
  56. package/dist/config/ServerConfiguration.d.ts +2 -1
  57. package/dist/config/ServerConfiguration.d.ts.map +1 -1
  58. package/dist/config/ServerConfiguration.js +50 -41
  59. package/dist/config/ServerConfiguration.js.map +1 -1
  60. package/dist/docs/DocumentationGenerator.d.ts +9 -8
  61. package/dist/docs/DocumentationGenerator.d.ts.map +1 -1
  62. package/dist/docs/DocumentationGenerator.js +10 -7
  63. package/dist/docs/DocumentationGenerator.js.map +1 -1
  64. package/dist/docs/MarkdownFormatter.d.ts.map +1 -1
  65. package/dist/docs/MarkdownFormatter.js +3 -2
  66. package/dist/docs/MarkdownFormatter.js.map +1 -1
  67. package/dist/dxt-entry.cjs +81 -0
  68. package/dist/dxt-entry.js +15 -14
  69. package/dist/dxt-entry.js.map +1 -1
  70. package/dist/index.d.ts +3 -1
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +37 -21
  73. package/dist/index.js.map +1 -1
  74. package/dist/performance/MetricsCollector.d.ts +13 -7
  75. package/dist/performance/MetricsCollector.d.ts.map +1 -1
  76. package/dist/performance/MetricsCollector.js +69 -27
  77. package/dist/performance/MetricsCollector.js.map +1 -1
  78. package/dist/performance/PerformanceAnalytics.d.ts +8 -2
  79. package/dist/performance/PerformanceAnalytics.d.ts.map +1 -1
  80. package/dist/performance/PerformanceAnalytics.js +17 -47
  81. package/dist/performance/PerformanceAnalytics.js.map +1 -1
  82. package/dist/performance/PerformanceMonitor.d.ts +2 -1
  83. package/dist/performance/PerformanceMonitor.d.ts.map +1 -1
  84. package/dist/performance/PerformanceMonitor.js +12 -13
  85. package/dist/performance/PerformanceMonitor.js.map +1 -1
  86. package/dist/performance/index.d.ts +2 -2
  87. package/dist/performance/index.d.ts.map +1 -1
  88. package/dist/security/AISecurityScanner.d.ts +1 -0
  89. package/dist/security/AISecurityScanner.d.ts.map +1 -1
  90. package/dist/security/AISecurityScanner.js +22 -12
  91. package/dist/security/AISecurityScanner.js.map +1 -1
  92. package/dist/security/AutomatedRemediation.d.ts +4 -3
  93. package/dist/security/AutomatedRemediation.d.ts.map +1 -1
  94. package/dist/security/AutomatedRemediation.js +46 -15
  95. package/dist/security/AutomatedRemediation.js.map +1 -1
  96. package/dist/security/InputValidator.d.ts +13 -9
  97. package/dist/security/InputValidator.d.ts.map +1 -1
  98. package/dist/security/InputValidator.js +4 -2
  99. package/dist/security/InputValidator.js.map +1 -1
  100. package/dist/security/SecurityCIPipeline.d.ts +1 -1
  101. package/dist/security/SecurityCIPipeline.d.ts.map +1 -1
  102. package/dist/security/SecurityCIPipeline.js +38 -29
  103. package/dist/security/SecurityCIPipeline.js.map +1 -1
  104. package/dist/security/SecurityConfig.d.ts +3 -3
  105. package/dist/security/SecurityConfig.d.ts.map +1 -1
  106. package/dist/security/SecurityConfig.js +13 -9
  107. package/dist/security/SecurityConfig.js.map +1 -1
  108. package/dist/security/SecurityConfigManager.d.ts +2 -2
  109. package/dist/security/SecurityConfigManager.d.ts.map +1 -1
  110. package/dist/security/SecurityConfigManager.js +20 -15
  111. package/dist/security/SecurityConfigManager.js.map +1 -1
  112. package/dist/security/SecurityMonitoring.d.ts +2 -2
  113. package/dist/security/SecurityMonitoring.d.ts.map +1 -1
  114. package/dist/security/SecurityMonitoring.js +19 -17
  115. package/dist/security/SecurityMonitoring.js.map +1 -1
  116. package/dist/security/SecurityReviewer.d.ts.map +1 -1
  117. package/dist/security/SecurityReviewer.js +10 -7
  118. package/dist/security/SecurityReviewer.js.map +1 -1
  119. package/dist/security/index.d.ts +24 -23
  120. package/dist/security/index.d.ts.map +1 -1
  121. package/dist/security/index.js +52 -23
  122. package/dist/security/index.js.map +1 -1
  123. package/dist/server/ConnectionTester.d.ts +12 -4
  124. package/dist/server/ConnectionTester.d.ts.map +1 -1
  125. package/dist/server/ConnectionTester.js +96 -22
  126. package/dist/server/ConnectionTester.js.map +1 -1
  127. package/dist/server/ToolRegistry.d.ts +2 -2
  128. package/dist/server/ToolRegistry.d.ts.map +1 -1
  129. package/dist/server/ToolRegistry.js +10 -5
  130. package/dist/server/ToolRegistry.js.map +1 -1
  131. package/dist/tools/BaseToolManager.d.ts +47 -11
  132. package/dist/tools/BaseToolManager.d.ts.map +1 -1
  133. package/dist/tools/BaseToolManager.js +168 -29
  134. package/dist/tools/BaseToolManager.js.map +1 -1
  135. package/dist/tools/auth.d.ts +16 -10
  136. package/dist/tools/auth.d.ts.map +1 -1
  137. package/dist/tools/auth.js +3 -2
  138. package/dist/tools/auth.js.map +1 -1
  139. package/dist/tools/cache.d.ts +30 -30
  140. package/dist/tools/cache.d.ts.map +1 -1
  141. package/dist/tools/cache.js +1 -6
  142. package/dist/tools/cache.js.map +1 -1
  143. package/dist/tools/comments.d.ts +20 -20
  144. package/dist/tools/comments.d.ts.map +1 -1
  145. package/dist/tools/comments.js +16 -9
  146. package/dist/tools/comments.js.map +1 -1
  147. package/dist/tools/media.d.ts +18 -16
  148. package/dist/tools/media.d.ts.map +1 -1
  149. package/dist/tools/media.js +16 -15
  150. package/dist/tools/media.js.map +1 -1
  151. package/dist/tools/pages.d.ts +19 -17
  152. package/dist/tools/pages.d.ts.map +1 -1
  153. package/dist/tools/pages.js +16 -12
  154. package/dist/tools/pages.js.map +1 -1
  155. package/dist/tools/performance.d.ts +11 -1
  156. package/dist/tools/performance.d.ts.map +1 -1
  157. package/dist/tools/performance.js +67 -34
  158. package/dist/tools/performance.js.map +1 -1
  159. package/dist/tools/posts/PostHandlers.d.ts +46 -0
  160. package/dist/tools/posts/PostHandlers.d.ts.map +1 -0
  161. package/dist/tools/posts/PostHandlers.js +400 -0
  162. package/dist/tools/posts/PostHandlers.js.map +1 -0
  163. package/dist/tools/posts/PostToolDefinitions.d.ts +37 -0
  164. package/dist/tools/posts/PostToolDefinitions.d.ts.map +1 -0
  165. package/dist/tools/posts/PostToolDefinitions.js +236 -0
  166. package/dist/tools/posts/PostToolDefinitions.js.map +1 -0
  167. package/dist/tools/posts/index.d.ts +138 -0
  168. package/dist/tools/posts/index.d.ts.map +1 -0
  169. package/dist/tools/posts/index.js +163 -0
  170. package/dist/tools/posts/index.js.map +1 -0
  171. package/dist/tools/posts.d.ts +10 -246
  172. package/dist/tools/posts.d.ts.map +1 -1
  173. package/dist/tools/posts.js +11 -723
  174. package/dist/tools/posts.js.map +1 -1
  175. package/dist/tools/site.d.ts +19 -18
  176. package/dist/tools/site.d.ts.map +1 -1
  177. package/dist/tools/site.js +14 -10
  178. package/dist/tools/site.js.map +1 -1
  179. package/dist/tools/taxonomies.d.ts +23 -24
  180. package/dist/tools/taxonomies.d.ts.map +1 -1
  181. package/dist/tools/taxonomies.js +24 -18
  182. package/dist/tools/taxonomies.js.map +1 -1
  183. package/dist/tools/users.d.ts +20 -15
  184. package/dist/tools/users.d.ts.map +1 -1
  185. package/dist/tools/users.js +12 -8
  186. package/dist/tools/users.js.map +1 -1
  187. package/dist/types/client.d.ts +48 -41
  188. package/dist/types/client.d.ts.map +1 -1
  189. package/dist/types/client.js +30 -5
  190. package/dist/types/client.js.map +1 -1
  191. package/dist/types/enhanced.d.ts +237 -0
  192. package/dist/types/enhanced.d.ts.map +1 -0
  193. package/dist/types/enhanced.js +49 -0
  194. package/dist/types/enhanced.js.map +1 -0
  195. package/dist/types/index.d.ts +15 -12
  196. package/dist/types/index.d.ts.map +1 -1
  197. package/dist/types/index.js +2 -0
  198. package/dist/types/index.js.map +1 -1
  199. package/dist/types/mcp.d.ts +12 -12
  200. package/dist/types/mcp.d.ts.map +1 -1
  201. package/dist/types/requests.d.ts +322 -0
  202. package/dist/types/requests.d.ts.map +1 -0
  203. package/dist/types/requests.js +8 -0
  204. package/dist/types/requests.js.map +1 -0
  205. package/dist/types/tools.d.ts +506 -0
  206. package/dist/types/tools.d.ts.map +1 -0
  207. package/dist/types/tools.js +8 -0
  208. package/dist/types/tools.js.map +1 -0
  209. package/dist/types/wordpress.d.ts +43 -15
  210. package/dist/types/wordpress.d.ts.map +1 -1
  211. package/dist/types/wordpress.js +8 -1
  212. package/dist/types/wordpress.js.map +1 -1
  213. package/dist/utils/debug.d.ts +19 -11
  214. package/dist/utils/debug.d.ts.map +1 -1
  215. package/dist/utils/debug.js +46 -10
  216. package/dist/utils/debug.js.map +1 -1
  217. package/dist/utils/enhancedError.d.ts +8 -8
  218. package/dist/utils/enhancedError.d.ts.map +1 -1
  219. package/dist/utils/enhancedError.js.map +1 -1
  220. package/dist/utils/error.d.ts +2 -4
  221. package/dist/utils/error.d.ts.map +1 -1
  222. package/dist/utils/error.js +42 -5
  223. package/dist/utils/error.js.map +1 -1
  224. package/dist/utils/logger.d.ts +106 -0
  225. package/dist/utils/logger.d.ts.map +1 -0
  226. package/dist/utils/logger.js +280 -0
  227. package/dist/utils/logger.js.map +1 -0
  228. package/dist/utils/streaming.d.ts +9 -9
  229. package/dist/utils/streaming.d.ts.map +1 -1
  230. package/dist/utils/streaming.js +71 -52
  231. package/dist/utils/streaming.js.map +1 -1
  232. package/dist/utils/toolWrapper.d.ts +9 -7
  233. package/dist/utils/toolWrapper.d.ts.map +1 -1
  234. package/dist/utils/toolWrapper.js.map +1 -1
  235. package/dist/utils/validation/core.d.ts +21 -0
  236. package/dist/utils/validation/core.d.ts.map +1 -0
  237. package/dist/utils/validation/core.js +71 -0
  238. package/dist/utils/validation/core.js.map +1 -0
  239. package/dist/utils/validation/index.d.ts +25 -0
  240. package/dist/utils/validation/index.d.ts.map +1 -0
  241. package/dist/utils/validation/index.js +29 -0
  242. package/dist/utils/validation/index.js.map +1 -0
  243. package/dist/utils/validation/network.d.ts +19 -0
  244. package/dist/utils/validation/network.d.ts.map +1 -0
  245. package/dist/utils/validation/network.js +93 -0
  246. package/dist/utils/validation/network.js.map +1 -0
  247. package/dist/utils/validation/rateLimit.d.ts +21 -0
  248. package/dist/utils/validation/rateLimit.d.ts.map +1 -0
  249. package/dist/utils/validation/rateLimit.js +43 -0
  250. package/dist/utils/validation/rateLimit.js.map +1 -0
  251. package/dist/utils/validation/security.d.ts +29 -0
  252. package/dist/utils/validation/security.d.ts.map +1 -0
  253. package/dist/utils/validation/security.js +327 -0
  254. package/dist/utils/validation/security.js.map +1 -0
  255. package/dist/utils/validation/wordpress.d.ts +31 -0
  256. package/dist/utils/validation/wordpress.d.ts.map +1 -0
  257. package/dist/utils/validation/wordpress.js +146 -0
  258. package/dist/utils/validation/wordpress.js.map +1 -0
  259. package/dist/utils/validation.d.ts +13 -82
  260. package/dist/utils/validation.d.ts.map +1 -1
  261. package/dist/utils/validation.js +25 -343
  262. package/dist/utils/validation.js.map +1 -1
  263. package/docs/BADGE_UPDATES.md +132 -0
  264. package/docs/CI_CD_IMPROVEMENTS.md +191 -0
  265. package/docs/INCREMENTAL_COVERAGE.md +183 -0
  266. package/docs/api/README.md +3 -1
  267. package/docs/api/openapi.json +5 -1
  268. package/docs/api/summary.json +1 -1
  269. package/docs/api/tools/wp_create_post.md +12 -14
  270. package/docs/examples/claude-desktop-config.md +1 -1
  271. package/docs/examples/docker-production.md +100 -93
  272. package/docs/examples/multi-site-setup.md +5 -4
  273. package/docs/examples/single-site-setup.md +3 -4
  274. package/docs/examples/use-case-workflows.md +4 -5
  275. package/docs/integrations/claude-desktop.md +31 -31
  276. package/docs/integrations/cline.md +4 -4
  277. package/docs/integrations/vs-code.md +9 -8
  278. package/docs/user-guides/SMITHERY_SETUP.md +10 -10
  279. package/package.json +44 -25
  280. package/src/cache/CacheInvalidation.ts +12 -5
  281. package/src/cache/CacheManager.ts +18 -15
  282. package/src/cache/HttpCacheWrapper.ts +30 -59
  283. package/src/cache/__tests__/HttpCacheWrapper.test.ts +6 -5
  284. package/src/cache/index.ts +3 -14
  285. package/src/client/CachedWordPressClient.ts +32 -30
  286. package/src/client/MockWordPressClient.ts +4 -2
  287. package/src/client/api.ts +186 -64
  288. package/src/client/auth.ts +15 -40
  289. package/src/client/managers/AuthenticationManager.ts +337 -77
  290. package/src/client/managers/BaseManager.ts +18 -30
  291. package/src/client/managers/RequestManager.ts +39 -44
  292. package/src/config/Config.ts +308 -0
  293. package/src/config/ConfigurationSchema.ts +23 -2
  294. package/src/config/ServerConfiguration.ts +51 -47
  295. package/src/docs/DocumentationGenerator.ts +50 -39
  296. package/src/docs/MarkdownFormatter.ts +19 -29
  297. package/src/dxt-entry.cjs +26 -16
  298. package/src/dxt-entry.ts +17 -27
  299. package/src/index.ts +42 -28
  300. package/src/performance/MetricsCollector.ts +108 -86
  301. package/src/performance/PerformanceAnalytics.ts +69 -164
  302. package/src/performance/PerformanceMonitor.ts +32 -47
  303. package/src/performance/index.ts +2 -10
  304. package/src/security/AISecurityScanner.ts +22 -12
  305. package/src/security/AutomatedRemediation.ts +49 -18
  306. package/src/security/InputValidator.ts +9 -6
  307. package/src/security/SecurityCIPipeline.ts +53 -37
  308. package/src/security/SecurityConfig.ts +22 -22
  309. package/src/security/SecurityConfigManager.ts +23 -19
  310. package/src/security/SecurityMonitoring.ts +24 -21
  311. package/src/security/SecurityReviewer.ts +10 -7
  312. package/src/security/index.ts +64 -29
  313. package/src/server/ConnectionTester.ts +120 -31
  314. package/src/server/ToolRegistry.ts +31 -21
  315. package/src/tools/BaseToolManager.ts +286 -33
  316. package/src/tools/auth.ts +20 -8
  317. package/src/tools/cache.ts +5 -15
  318. package/src/tools/comments.ts +34 -48
  319. package/src/tools/media.ts +41 -53
  320. package/src/tools/pages.ts +32 -54
  321. package/src/tools/performance.ts +141 -176
  322. package/src/tools/posts/PostHandlers.ts +474 -0
  323. package/src/tools/posts/PostToolDefinitions.ts +250 -0
  324. package/src/tools/posts/index.ts +192 -0
  325. package/src/tools/posts.ts +24 -780
  326. package/src/tools/site.ts +34 -19
  327. package/src/tools/taxonomies.ts +41 -57
  328. package/src/tools/users.ts +28 -16
  329. package/src/types/client.ts +114 -138
  330. package/src/types/enhanced.ts +318 -0
  331. package/src/types/index.ts +51 -30
  332. package/src/types/mcp.ts +20 -42
  333. package/src/types/requests.ts +378 -0
  334. package/src/types/tools.ts +608 -0
  335. package/src/types/wordpress.ts +56 -34
  336. package/src/utils/debug.ts +77 -59
  337. package/src/utils/enhancedError.ts +8 -8
  338. package/src/utils/error.ts +53 -31
  339. package/src/utils/logger.ts +351 -0
  340. package/src/utils/streaming.ts +86 -68
  341. package/src/utils/toolWrapper.ts +10 -12
  342. package/src/utils/validation/core.ts +108 -0
  343. package/src/utils/validation/index.ts +36 -0
  344. package/src/utils/validation/network.ts +132 -0
  345. package/src/utils/validation/rateLimit.ts +54 -0
  346. package/src/utils/validation/security.ts +361 -0
  347. package/src/utils/validation/wordpress.ts +180 -0
  348. package/src/utils/validation.ts +47 -470
@@ -64,9 +64,7 @@ export class WordPressAuth {
64
64
  // Test the credentials by attempting to get current user
65
65
  try {
66
66
  const user = await this.client.getCurrentUser();
67
- logger.log(
68
- `✅ Application Password authentication successful for user: ${user.name} (${user.username})`,
69
- );
67
+ logger.log(`✅ Application Password authentication successful for user: ${user.name} (${user.username})`);
70
68
  return true;
71
69
  } catch (error) {
72
70
  const message =
@@ -83,20 +81,15 @@ export class WordPressAuth {
83
81
  const { username, password } = this.client.config.auth;
84
82
 
85
83
  if (!username || !password) {
86
- throw new Error(
87
- "Basic authentication requires WORDPRESS_USERNAME and WORDPRESS_PASSWORD",
88
- );
84
+ throw new Error("Basic authentication requires WORDPRESS_USERNAME and WORDPRESS_PASSWORD");
89
85
  }
90
86
 
91
87
  try {
92
88
  const user = await this.client.getCurrentUser();
93
- logger.log(
94
- `✅ Basic authentication successful for user: ${user.name} (${user.username})`,
95
- );
89
+ logger.log(`✅ Basic authentication successful for user: ${user.name} (${user.username})`);
96
90
  return true;
97
91
  } catch (error) {
98
- const message =
99
- "Basic authentication failed. Please check your username and password.";
92
+ const message = "Basic authentication failed. Please check your username and password.";
100
93
  logger.error(message, error);
101
94
  throw new Error(message);
102
95
  }
@@ -118,9 +111,7 @@ export class WordPressAuth {
118
111
  try {
119
112
  // The JWT token should be obtained during client authentication
120
113
  const user = await this.client.getCurrentUser();
121
- logger.log(
122
- `✅ JWT authentication successful for user: ${user.name} (${user.username})`,
123
- );
114
+ logger.log(`✅ JWT authentication successful for user: ${user.name} (${user.username})`);
124
115
  return true;
125
116
  } catch (error) {
126
117
  const message =
@@ -146,8 +137,7 @@ export class WordPressAuth {
146
137
  logger.log("✅ API Key authentication successful");
147
138
  return true;
148
139
  } catch (error) {
149
- const message =
150
- "API Key authentication failed. Please check your API key.";
140
+ const message = "API Key authentication failed. Please check your API key.";
151
141
  logger.error(message, error);
152
142
  throw new Error(message);
153
143
  }
@@ -160,21 +150,16 @@ export class WordPressAuth {
160
150
  const { nonce } = this.client.config.auth;
161
151
 
162
152
  if (!nonce) {
163
- logger.warn(
164
- "Cookie authentication: No nonce provided, authentication may fail for write operations",
165
- );
153
+ logger.warn("Cookie authentication: No nonce provided, authentication may fail for write operations");
166
154
  }
167
155
 
168
156
  try {
169
157
  // Test with a simple read operation
170
158
  await this.client.getSiteInfo();
171
- logger.log(
172
- "✅ Cookie authentication configured (note: write operations may require valid nonce)",
173
- );
159
+ logger.log("✅ Cookie authentication configured (note: write operations may require valid nonce)");
174
160
  return true;
175
161
  } catch (error) {
176
- const message =
177
- "Cookie authentication failed. Please ensure you are properly logged into WordPress.";
162
+ const message = "Cookie authentication failed. Please ensure you are properly logged into WordPress.";
178
163
  logger.error(message, error);
179
164
  throw new Error(message);
180
165
  }
@@ -249,7 +234,7 @@ export class WordPressAuth {
249
234
  */
250
235
  async switchAuthMethod(newConfig: AuthConfig): Promise<boolean> {
251
236
  // Update client configuration
252
- (this.client.config as any).auth = newConfig;
237
+ (this.client.config as { auth: AuthConfig }).auth = newConfig;
253
238
  this.authType = newConfig.method;
254
239
 
255
240
  // Re-authenticate with new method
@@ -295,8 +280,7 @@ export class WordPressAuth {
295
280
  * Generate random state for OAuth
296
281
  */
297
282
  private generateRandomState(length = 32): string {
298
- const chars =
299
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
283
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
300
284
  let result = "";
301
285
  for (let i = 0; i < length; i++) {
302
286
  result += chars.charAt(Math.floor(Math.random() * chars.length));
@@ -314,17 +298,13 @@ export class WordPressAuth {
314
298
  switch (this.authType) {
315
299
  case "app-password":
316
300
  if (auth.username && auth.appPassword) {
317
- const credentials = Buffer.from(
318
- `${auth.username}:${auth.appPassword}`,
319
- ).toString("base64");
301
+ const credentials = Buffer.from(`${auth.username}:${auth.appPassword}`).toString("base64");
320
302
  headers["Authorization"] = `Basic ${credentials}`;
321
303
  }
322
304
  break;
323
305
  case "basic":
324
306
  if (auth.username && auth.password) {
325
- const credentials = Buffer.from(
326
- `${auth.username}:${auth.password}`,
327
- ).toString("base64");
307
+ const credentials = Buffer.from(`${auth.username}:${auth.password}`).toString("base64");
328
308
  headers["Authorization"] = `Basic ${credentials}`;
329
309
  }
330
310
  break;
@@ -361,14 +341,9 @@ export class WordPressAuth {
361
341
  case "api-key":
362
342
  return !this.client.config.auth.apiKey;
363
343
  case "app-password":
364
- return (
365
- !this.client.config.auth.username ||
366
- !this.client.config.auth.appPassword
367
- );
344
+ return !this.client.config.auth.username || !this.client.config.auth.appPassword;
368
345
  case "basic":
369
- return (
370
- !this.client.config.auth.username || !this.client.config.auth.password
371
- );
346
+ return !this.client.config.auth.username || !this.client.config.auth.password;
372
347
  case "cookie":
373
348
  return false; // Cookie auth can work without additional setup
374
349
  default:
@@ -3,122 +3,203 @@
3
3
  * Handles all authentication methods and token management
4
4
  */
5
5
 
6
- import type { AuthConfig, AuthMethod } from "../../types/client.js";
6
+ import type {
7
+ AuthConfig,
8
+ WordPressClientConfig,
9
+ AuthStatus,
10
+ AppPasswordCredentials,
11
+ JwtCredentials,
12
+ BasicCredentials,
13
+ ApiKeyCredentials,
14
+ } from "../../types/client.js";
7
15
  import { AuthenticationError } from "../../types/client.js";
16
+ import { AUTH_METHODS, type AuthMethod } from "../../types/wordpress.js";
17
+ import { config } from "../../config/Config.js";
8
18
  import { BaseManager } from "./BaseManager.js";
9
19
  import { debug } from "../../utils/debug.js";
10
20
 
21
+ interface AuthManagerConfig extends WordPressClientConfig {
22
+ siteUrl: string; // Required based on constructor validation
23
+ authMethod: AuthMethod; // Use proper AuthMethod type
24
+ username?: string;
25
+ appPassword?: string;
26
+ password?: string;
27
+ apiKey?: string;
28
+ jwtSecret?: string;
29
+ jwtToken?: string;
30
+ tokenExpiry?: number;
31
+ }
32
+
11
33
  export class AuthenticationManager extends BaseManager {
12
34
  private jwtToken: string | null = null;
13
35
  private authenticated: boolean = false;
36
+ private authConfig: AuthManagerConfig;
37
+ public config: AuthManagerConfig; // Expose for test compatibility
38
+
39
+ constructor(config: AuthManagerConfig) {
40
+ // Validate required config fields
41
+ if (!config.siteUrl || config.siteUrl.trim() === "") {
42
+ throw new AuthenticationError("Site URL is required", AUTH_METHODS.APP_PASSWORD);
43
+ }
44
+
45
+ // Validate site URL format
46
+ try {
47
+ new URL(config.siteUrl);
48
+ } catch {
49
+ throw new AuthenticationError("Invalid site URL", AUTH_METHODS.APP_PASSWORD);
50
+ }
51
+
52
+ // Validate auth method using centralized constants
53
+ const validMethods = Object.values(AUTH_METHODS);
54
+ if (config.authMethod && !validMethods.includes(config.authMethod)) {
55
+ throw new AuthenticationError("Invalid authentication method", config.authMethod);
56
+ }
57
+
58
+ // Transform config to match expected format
59
+ const transformedConfig: WordPressClientConfig = {
60
+ baseUrl: config.siteUrl,
61
+ timeout: config.timeout || 30000,
62
+ auth: {
63
+ method: config.authMethod || AUTH_METHODS.APP_PASSWORD,
64
+ ...(config.username && { username: config.username }),
65
+ ...(config.appPassword && { appPassword: config.appPassword }),
66
+ ...(config.password && { password: config.password }),
67
+ ...(config.apiKey && { apiKey: config.apiKey }),
68
+ ...(config.jwtSecret && { secret: config.jwtSecret }),
69
+ },
70
+ };
71
+
72
+ super(transformedConfig);
73
+
74
+ // Store private config
75
+ this.authConfig = config;
76
+ // Expose config for test compatibility
77
+ this.config = config;
78
+ }
79
+
80
+ /**
81
+ * Get config for testing purposes
82
+ */
83
+ getConfig(): AuthManagerConfig {
84
+ return { ...this.authConfig };
85
+ }
14
86
 
15
87
  /**
16
88
  * Get authentication from environment variables
17
89
  */
18
90
  static getAuthFromEnv(): AuthConfig {
19
- const method: AuthMethod = (process.env.WORDPRESS_AUTH_METHOD as AuthMethod) || "app-password";
91
+ const cfg = config();
92
+ const wp = cfg.wordpress;
93
+ const method: AuthMethod = (wp.authMethod as AuthMethod) || AUTH_METHODS.APP_PASSWORD;
20
94
 
21
95
  switch (method) {
22
- case "app-password":
96
+ case AUTH_METHODS.APP_PASSWORD:
23
97
  return {
24
- method: "app-password",
25
- username: process.env.WORDPRESS_USERNAME || "",
26
- appPassword: process.env.WORDPRESS_APP_PASSWORD || "",
98
+ method: AUTH_METHODS.APP_PASSWORD,
99
+ username: wp.username || "",
100
+ appPassword: wp.appPassword || "",
27
101
  };
28
102
 
29
- case "jwt":
103
+ case AUTH_METHODS.JWT:
30
104
  return {
31
- method: "jwt",
32
- username: process.env.WORDPRESS_USERNAME || "",
33
- password: process.env.WORDPRESS_JWT_PASSWORD || process.env.WORDPRESS_PASSWORD || "",
34
- secret: process.env.WORDPRESS_JWT_SECRET || "",
105
+ method: AUTH_METHODS.JWT,
106
+ username: wp.username || "",
107
+ password: wp.jwtPassword || wp.password || "",
108
+ secret: wp.jwtSecret || "",
35
109
  };
36
110
 
37
- case "basic":
111
+ case AUTH_METHODS.BASIC:
38
112
  return {
39
- method: "basic",
40
- username: process.env.WORDPRESS_USERNAME || "",
41
- password: process.env.WORDPRESS_PASSWORD || "",
113
+ method: AUTH_METHODS.BASIC,
114
+ username: wp.username || "",
115
+ password: wp.password || "",
42
116
  };
43
117
 
44
- case "api-key":
118
+ case AUTH_METHODS.API_KEY:
45
119
  return {
46
- method: "api-key",
47
- apiKey: process.env.WORDPRESS_API_KEY || "",
120
+ method: AUTH_METHODS.API_KEY,
121
+ apiKey: wp.apiKey || "",
48
122
  };
49
123
 
50
124
  default:
51
- throw new AuthenticationError(`Unsupported authentication method: ${method}`, method);
125
+ throw new AuthenticationError(`Unsupported authentication method: ${method}`, method as AuthMethod);
52
126
  }
53
127
  }
54
128
 
55
129
  /**
56
130
  * Get authentication headers for requests
131
+ *
132
+ * Note: This method is synchronous by design for test compatibility and simplicity.
133
+ * JWT token refresh should be handled externally before calling this method,
134
+ * as automatic refresh would require RequestManager integration.
57
135
  */
58
- async getAuthHeaders(): Promise<Record<string, string>> {
59
- const auth = this.config.auth;
60
-
61
- if (!auth) {
62
- // In test environments, return empty headers instead of throwing
63
- if (
64
- process.env.NODE_ENV === "test" ||
65
- process.env.CI === "true" ||
66
- (globalThis as any).__EXECUTION_CONTEXT__ === "jest"
67
- ) {
68
- debug.log("Warning: No authentication configuration in test environment, returning empty headers");
69
- return {};
70
- }
71
- throw new AuthenticationError("Authentication configuration is required", "app-password");
72
- }
136
+ getAuthHeaders(): Record<string, string> {
137
+ const method = this.authConfig.authMethod || AUTH_METHODS.APP_PASSWORD;
73
138
 
74
- switch (auth.method) {
75
- case "app-password":
76
- if (!auth.username || !auth.appPassword) {
77
- throw new AuthenticationError("Username and app password are required", auth.method);
139
+ switch (method) {
140
+ case AUTH_METHODS.APP_PASSWORD:
141
+ if (!this.authConfig.username || !this.authConfig.appPassword) {
142
+ throw new AuthenticationError("Username and app password are required", method);
78
143
  }
79
144
 
80
- const credentials = Buffer.from(`${auth.username}:${auth.appPassword}`).toString("base64");
145
+ const credentials = Buffer.from(`${this.authConfig.username}:${this.authConfig.appPassword}`).toString(
146
+ "base64",
147
+ );
81
148
  return { Authorization: `Basic ${credentials}` };
82
149
 
83
- case "jwt":
84
- if (!this.jwtToken) {
85
- await this.authenticateJWT();
150
+ case AUTH_METHODS.JWT:
151
+ if (!this.authConfig.jwtToken) {
152
+ throw new AuthenticationError("JWT token is required", method);
86
153
  }
87
- return { Authorization: `Bearer ${this.jwtToken}` };
154
+ return { Authorization: `Bearer ${this.authConfig.jwtToken}` };
88
155
 
89
- case "basic":
90
- if (!auth.username || !auth.password) {
91
- throw new AuthenticationError("Username and password are required", auth.method);
156
+ case AUTH_METHODS.BASIC:
157
+ if (!this.authConfig.username || !this.authConfig.password) {
158
+ throw new AuthenticationError("Username and password are required", method);
92
159
  }
93
160
 
94
- const basicCredentials = Buffer.from(`${auth.username}:${auth.password}`).toString("base64");
161
+ const basicCredentials = Buffer.from(`${this.authConfig.username}:${this.authConfig.password}`).toString(
162
+ "base64",
163
+ );
95
164
  return { Authorization: `Basic ${basicCredentials}` };
96
165
 
97
- case "api-key":
98
- if (!auth.apiKey) {
99
- throw new AuthenticationError("API key is required", auth.method);
166
+ case AUTH_METHODS.API_KEY:
167
+ if (!this.authConfig.apiKey) {
168
+ throw new AuthenticationError("API key is required", method);
100
169
  }
101
- return { "X-API-Key": auth.apiKey };
170
+ return { "X-API-Key": this.authConfig.apiKey };
171
+
172
+ case AUTH_METHODS.COOKIE:
173
+ // Cookie authentication typically handled by browser
174
+ return {};
102
175
 
103
176
  default:
104
- throw new AuthenticationError(`Unsupported authentication method: ${auth.method}`, auth.method);
177
+ throw new AuthenticationError(`Unsupported authentication method: ${method}`, method as AuthMethod);
105
178
  }
106
179
  }
107
180
 
108
181
  /**
109
182
  * Authenticate using JWT
183
+ *
184
+ * Note: This method is not fully implemented as it requires integration with
185
+ * the RequestManager to make HTTP requests to the WordPress JWT endpoint.
186
+ * JWT authentication requires the JWT Authentication for WP-API plugin.
187
+ *
188
+ * @throws {AuthenticationError} - JWT auth requires external dependency injection
110
189
  */
111
190
  private async authenticateJWT(): Promise<void> {
112
- const auth = this.config.auth;
113
-
114
- if (auth.method !== "jwt" || !auth.username || !auth.password) {
115
- throw new AuthenticationError("JWT authentication requires username and password", "jwt");
191
+ if (this.authConfig.authMethod !== AUTH_METHODS.JWT || !this.authConfig.username || !this.authConfig.password) {
192
+ throw new AuthenticationError("JWT authentication requires username and password", AUTH_METHODS.JWT);
116
193
  }
117
194
 
118
195
  try {
119
- // This would need the RequestManager instance to make the request
120
- // For now, we'll throw an error indicating this needs to be implemented
121
- throw new AuthenticationError("JWT authentication requires RequestManager integration", "jwt");
196
+ // TODO: Implement JWT authentication with RequestManager integration
197
+ // This would require making a POST request to /wp-json/jwt-auth/v1/token
198
+ // with username and password to obtain a JWT token
199
+ throw new AuthenticationError(
200
+ "JWT authentication requires RequestManager integration - not yet implemented",
201
+ AUTH_METHODS.JWT,
202
+ );
122
203
  } catch (error) {
123
204
  this.handleError(error, "JWT authentication");
124
205
  }
@@ -131,7 +212,7 @@ export class AuthenticationManager extends BaseManager {
131
212
  try {
132
213
  const _headers = await this.getAuthHeaders();
133
214
  debug.log("Authentication headers prepared", {
134
- method: this.config.auth.method,
215
+ method: this.authConfig.authMethod,
135
216
  });
136
217
 
137
218
  // This would need the RequestManager to actually test the connection
@@ -164,42 +245,221 @@ export class AuthenticationManager extends BaseManager {
164
245
  * Validate authentication configuration
165
246
  */
166
247
  validateAuthConfig(): void {
167
- const auth = this.config.auth;
248
+ const method = this.authConfig.authMethod;
168
249
 
169
- if (!auth.method) {
170
- throw new AuthenticationError("Authentication method is required", "app-password");
250
+ if (!method) {
251
+ throw new AuthenticationError("Authentication method is required", AUTH_METHODS.APP_PASSWORD);
171
252
  }
172
253
 
173
- switch (auth.method) {
174
- case "app-password":
175
- if (!auth.username || !auth.appPassword) {
254
+ switch (method) {
255
+ case AUTH_METHODS.APP_PASSWORD:
256
+ if (!this.authConfig.username || !this.authConfig.appPassword) {
176
257
  throw new AuthenticationError(
177
258
  "App password authentication requires username and appPassword",
178
- "app-password",
259
+ AUTH_METHODS.APP_PASSWORD,
179
260
  );
180
261
  }
181
262
  break;
182
263
 
183
- case "jwt":
184
- if (!auth.username || !auth.password || !auth.secret) {
185
- throw new AuthenticationError("JWT authentication requires username, password, and secret", "jwt");
264
+ case AUTH_METHODS.JWT:
265
+ if (!this.authConfig.username || !this.authConfig.password || !this.authConfig.jwtSecret) {
266
+ throw new AuthenticationError("JWT authentication requires username, password, and secret", AUTH_METHODS.JWT);
186
267
  }
187
268
  break;
188
269
 
189
- case "basic":
190
- if (!auth.username || !auth.password) {
191
- throw new AuthenticationError("Basic authentication requires username and password", "basic");
270
+ case AUTH_METHODS.BASIC:
271
+ if (!this.authConfig.username || !this.authConfig.password) {
272
+ throw new AuthenticationError("Basic authentication requires username and password", AUTH_METHODS.BASIC);
192
273
  }
193
274
  break;
194
275
 
195
- case "api-key":
196
- if (!auth.apiKey) {
197
- throw new AuthenticationError("API key authentication requires apiKey", "api-key");
276
+ case AUTH_METHODS.API_KEY:
277
+ if (!this.authConfig.apiKey) {
278
+ throw new AuthenticationError("API key authentication requires apiKey", AUTH_METHODS.API_KEY);
198
279
  }
199
280
  break;
200
281
 
201
282
  default:
202
- throw new AuthenticationError(`Unsupported authentication method: ${auth.method}`, auth.method);
283
+ throw new AuthenticationError(`Unsupported authentication method: ${method}`, method);
284
+ }
285
+ }
286
+
287
+ /**
288
+ * Validate credentials for current auth method
289
+ */
290
+ validateCredentials(): void {
291
+ const method = this.authConfig.authMethod || AUTH_METHODS.APP_PASSWORD;
292
+
293
+ switch (method) {
294
+ case AUTH_METHODS.APP_PASSWORD:
295
+ if (!this.authConfig.username) {
296
+ throw new AuthenticationError("Username is required", method);
297
+ }
298
+ if (!this.authConfig.appPassword) {
299
+ throw new AuthenticationError("App password is required", method);
300
+ }
301
+ break;
302
+
303
+ case AUTH_METHODS.JWT:
304
+ if (!this.authConfig.jwtToken) {
305
+ throw new AuthenticationError("JWT token is required", method);
306
+ }
307
+ break;
308
+
309
+ case AUTH_METHODS.BASIC:
310
+ if (!this.authConfig.username) {
311
+ throw new AuthenticationError("Username is required", method);
312
+ }
313
+ if (!this.authConfig.password) {
314
+ throw new AuthenticationError("Password is required", method);
315
+ }
316
+ break;
317
+
318
+ case AUTH_METHODS.API_KEY:
319
+ if (!this.authConfig.apiKey) {
320
+ throw new AuthenticationError("API key is required", method);
321
+ }
322
+ break;
323
+
324
+ default:
325
+ throw new AuthenticationError(`Invalid authentication method: ${method}`, method);
326
+ }
327
+ }
328
+
329
+ /**
330
+ * Update authentication method and credentials
331
+ */
332
+ updateAuthMethod(
333
+ method: AuthMethod,
334
+ credentials: AppPasswordCredentials | JwtCredentials | BasicCredentials | ApiKeyCredentials,
335
+ ): void {
336
+ const validMethods = Object.values(AUTH_METHODS);
337
+ if (!validMethods.includes(method)) {
338
+ throw new AuthenticationError("Invalid authentication method", method);
339
+ }
340
+
341
+ // Clear all previous credentials to prevent leakage
342
+ delete this.authConfig.username;
343
+ delete this.authConfig.appPassword;
344
+ delete this.authConfig.jwtToken;
345
+ delete this.authConfig.password;
346
+ delete this.authConfig.apiKey;
347
+ delete this.authConfig.tokenExpiry;
348
+
349
+ // Set new auth method
350
+ this.authConfig.authMethod = method;
351
+
352
+ // Set new credentials with type safety and validation
353
+ switch (method) {
354
+ case AUTH_METHODS.APP_PASSWORD:
355
+ const appCreds = credentials as AppPasswordCredentials;
356
+ if (!appCreds.username || !appCreds.appPassword) {
357
+ throw new AuthenticationError("Username and app password are required", method);
358
+ }
359
+ this.authConfig.username = appCreds.username;
360
+ this.authConfig.appPassword = appCreds.appPassword;
361
+ break;
362
+
363
+ case AUTH_METHODS.JWT:
364
+ const jwtCreds = credentials as JwtCredentials;
365
+ if (!jwtCreds.jwtToken) {
366
+ throw new AuthenticationError("JWT token is required", method);
367
+ }
368
+ this.authConfig.jwtToken = jwtCreds.jwtToken;
369
+ if (jwtCreds.username) {
370
+ this.authConfig.username = jwtCreds.username;
371
+ }
372
+ break;
373
+
374
+ case AUTH_METHODS.BASIC:
375
+ const basicCreds = credentials as BasicCredentials;
376
+ if (!basicCreds.username || !basicCreds.password) {
377
+ throw new AuthenticationError("Username and password are required", method);
378
+ }
379
+ this.authConfig.username = basicCreds.username;
380
+ this.authConfig.password = basicCreds.password;
381
+ break;
382
+
383
+ case AUTH_METHODS.API_KEY:
384
+ const apiCreds = credentials as ApiKeyCredentials;
385
+ if (!apiCreds.apiKey) {
386
+ throw new AuthenticationError("API key is required", method);
387
+ }
388
+ this.authConfig.apiKey = apiCreds.apiKey;
389
+ break;
390
+ }
391
+ }
392
+
393
+ /**
394
+ * Refresh JWT token
395
+ *
396
+ * For testing compatibility, this method supports mock JWT refresh.
397
+ * In production, it requires RequestManager integration.
398
+ */
399
+ async refreshToken(): Promise<void> {
400
+ if (this.authConfig.authMethod !== AUTH_METHODS.JWT) {
401
+ throw new AuthenticationError(
402
+ "Token refresh not supported for non-JWT authentication methods",
403
+ this.authConfig.authMethod,
404
+ );
203
405
  }
406
+
407
+ // Check if mock refresh method is available (for testing)
408
+ const mockRefreshMethod = (this as Record<string, unknown>).refreshJwtToken;
409
+ if (typeof mockRefreshMethod === "function") {
410
+ const result = await mockRefreshMethod();
411
+ if (result && typeof result === "object" && "token" in result) {
412
+ const tokenResult = result as { token: string; expires_in?: number };
413
+ this.authConfig.jwtToken = tokenResult.token;
414
+ if (tokenResult.expires_in) {
415
+ this.authConfig.tokenExpiry = Date.now() + tokenResult.expires_in * 1000;
416
+ }
417
+ return;
418
+ }
419
+ }
420
+
421
+ // TODO: Implement JWT token refresh with RequestManager integration
422
+ // This would require making a POST request to /wp-json/jwt-auth/v1/token/validate
423
+ // and updating the stored token and expiry
424
+ throw new AuthenticationError(
425
+ "JWT refresh requires RequestManager integration - not yet implemented",
426
+ AUTH_METHODS.JWT,
427
+ );
428
+ }
429
+
430
+ /**
431
+ * Check if JWT token is expired
432
+ */
433
+ isTokenExpired(): boolean {
434
+ if (this.authConfig.authMethod !== AUTH_METHODS.JWT) {
435
+ return false;
436
+ }
437
+
438
+ if (!this.authConfig.tokenExpiry) {
439
+ return true;
440
+ }
441
+
442
+ return Date.now() >= this.authConfig.tokenExpiry;
443
+ }
444
+
445
+ /**
446
+ * Get authentication status
447
+ */
448
+ getAuthStatus(): AuthStatus {
449
+ const method = this.authConfig.authMethod || AUTH_METHODS.APP_PASSWORD;
450
+ const isExpired = this.isTokenExpired();
451
+
452
+ const status: AuthStatus = {
453
+ method,
454
+ username: this.authConfig.username,
455
+ isAuthenticated: method === AUTH_METHODS.JWT ? !isExpired : true,
456
+ tokenExpired: isExpired,
457
+ };
458
+
459
+ if (method === AUTH_METHODS.JWT && this.authConfig.tokenExpiry) {
460
+ status.tokenExpiry = this.authConfig.tokenExpiry;
461
+ }
462
+
463
+ return status;
204
464
  }
205
465
  }