mcp-wordpress 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. package/README.md +210 -182
  2. package/dist/cache/CacheInvalidation.d.ts +3 -3
  3. package/dist/cache/CacheInvalidation.d.ts.map +1 -1
  4. package/dist/cache/CacheInvalidation.js +119 -119
  5. package/dist/cache/CacheInvalidation.js.map +1 -1
  6. package/dist/cache/CacheManager.d.ts +5 -0
  7. package/dist/cache/CacheManager.d.ts.map +1 -1
  8. package/dist/cache/CacheManager.js +26 -16
  9. package/dist/cache/CacheManager.js.map +1 -1
  10. package/dist/cache/HttpCacheWrapper.d.ts +1 -1
  11. package/dist/cache/HttpCacheWrapper.d.ts.map +1 -1
  12. package/dist/cache/HttpCacheWrapper.js +29 -29
  13. package/dist/cache/HttpCacheWrapper.js.map +1 -1
  14. package/dist/cache/__tests__/CacheInvalidation.test.js +96 -94
  15. package/dist/cache/__tests__/CacheInvalidation.test.js.map +1 -1
  16. package/dist/cache/__tests__/CacheManager.test.js +113 -113
  17. package/dist/cache/__tests__/CacheManager.test.js.map +1 -1
  18. package/dist/cache/__tests__/CachedWordPressClient.test.js +102 -99
  19. package/dist/cache/__tests__/CachedWordPressClient.test.js.map +1 -1
  20. package/dist/cache/__tests__/HttpCacheWrapper.test.js +98 -95
  21. package/dist/cache/__tests__/HttpCacheWrapper.test.js.map +1 -1
  22. package/dist/cache/index.d.ts +7 -7
  23. package/dist/cache/index.d.ts.map +1 -1
  24. package/dist/cache/index.js +4 -4
  25. package/dist/cache/index.js.map +1 -1
  26. package/dist/client/CachedWordPressClient.d.ts +4 -4
  27. package/dist/client/CachedWordPressClient.d.ts.map +1 -1
  28. package/dist/client/CachedWordPressClient.js +55 -51
  29. package/dist/client/CachedWordPressClient.js.map +1 -1
  30. package/dist/client/api.d.ts +10 -10
  31. package/dist/client/api.js +158 -158
  32. package/dist/client/api.js.map +1 -1
  33. package/dist/client/auth.d.ts +2 -2
  34. package/dist/client/auth.js +72 -72
  35. package/dist/client/managers/AuthenticationManager.d.ts +2 -2
  36. package/dist/client/managers/AuthenticationManager.js +46 -46
  37. package/dist/client/managers/BaseManager.d.ts +1 -1
  38. package/dist/client/managers/BaseManager.js +9 -9
  39. package/dist/client/managers/RequestManager.d.ts +5 -3
  40. package/dist/client/managers/RequestManager.d.ts.map +1 -1
  41. package/dist/client/managers/RequestManager.js +39 -19
  42. package/dist/client/managers/RequestManager.js.map +1 -1
  43. package/dist/client/managers/index.d.ts +3 -3
  44. package/dist/client/managers/index.js +3 -3
  45. package/dist/config/ConfigurationSchema.d.ts +2 -2
  46. package/dist/config/ConfigurationSchema.d.ts.map +1 -1
  47. package/dist/config/ConfigurationSchema.js +40 -40
  48. package/dist/config/ConfigurationSchema.js.map +1 -1
  49. package/dist/config/ServerConfiguration.d.ts +2 -2
  50. package/dist/config/ServerConfiguration.js +35 -35
  51. package/dist/config/ServerConfiguration.js.map +1 -1
  52. package/dist/docs/DocumentationGenerator.d.ts.map +1 -1
  53. package/dist/docs/DocumentationGenerator.js +296 -255
  54. package/dist/docs/DocumentationGenerator.js.map +1 -1
  55. package/dist/docs/MarkdownFormatter.d.ts +1 -1
  56. package/dist/docs/MarkdownFormatter.d.ts.map +1 -1
  57. package/dist/docs/MarkdownFormatter.js +60 -51
  58. package/dist/docs/MarkdownFormatter.js.map +1 -1
  59. package/dist/docs/index.d.ts +3 -3
  60. package/dist/docs/index.d.ts.map +1 -1
  61. package/dist/docs/index.js +2 -2
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +16 -16
  64. package/dist/index.js.map +1 -1
  65. package/dist/mcp-wordpress-1.3.0.tgz +0 -0
  66. package/dist/performance/MetricsCollector.d.ts +3 -3
  67. package/dist/performance/MetricsCollector.d.ts.map +1 -1
  68. package/dist/performance/MetricsCollector.js +33 -27
  69. package/dist/performance/MetricsCollector.js.map +1 -1
  70. package/dist/performance/PerformanceAnalytics.d.ts +12 -12
  71. package/dist/performance/PerformanceAnalytics.d.ts.map +1 -1
  72. package/dist/performance/PerformanceAnalytics.js +200 -154
  73. package/dist/performance/PerformanceAnalytics.js.map +1 -1
  74. package/dist/performance/PerformanceMonitor.d.ts +5 -5
  75. package/dist/performance/PerformanceMonitor.d.ts.map +1 -1
  76. package/dist/performance/PerformanceMonitor.js +53 -52
  77. package/dist/performance/PerformanceMonitor.js.map +1 -1
  78. package/dist/performance/index.d.ts +6 -6
  79. package/dist/performance/index.d.ts.map +1 -1
  80. package/dist/performance/index.js +3 -3
  81. package/dist/security/InputValidator.d.ts +1 -1
  82. package/dist/security/InputValidator.d.ts.map +1 -1
  83. package/dist/security/InputValidator.js +111 -88
  84. package/dist/security/InputValidator.js.map +1 -1
  85. package/dist/security/SecurityConfig.d.ts +5 -5
  86. package/dist/security/SecurityConfig.js +92 -92
  87. package/dist/security/SecurityConfig.js.map +1 -1
  88. package/dist/server/ConnectionTester.d.ts +1 -1
  89. package/dist/server/ConnectionTester.d.ts.map +1 -1
  90. package/dist/server/ConnectionTester.js +4 -4
  91. package/dist/server/ConnectionTester.js.map +1 -1
  92. package/dist/server/ToolRegistry.d.ts +2 -2
  93. package/dist/server/ToolRegistry.d.ts.map +1 -1
  94. package/dist/server/ToolRegistry.js +35 -32
  95. package/dist/server/ToolRegistry.js.map +1 -1
  96. package/dist/server.d.ts +2 -2
  97. package/dist/server.js +2 -2
  98. package/dist/tools/BaseToolManager.js +5 -5
  99. package/dist/tools/auth.d.ts +2 -2
  100. package/dist/tools/auth.d.ts.map +1 -1
  101. package/dist/tools/auth.js +32 -31
  102. package/dist/tools/auth.js.map +1 -1
  103. package/dist/tools/cache.d.ts +1 -1
  104. package/dist/tools/cache.d.ts.map +1 -1
  105. package/dist/tools/cache.js +71 -71
  106. package/dist/tools/cache.js.map +1 -1
  107. package/dist/tools/comments.d.ts +2 -2
  108. package/dist/tools/comments.d.ts.map +1 -1
  109. package/dist/tools/comments.js +79 -79
  110. package/dist/tools/comments.js.map +1 -1
  111. package/dist/tools/index.d.ts +10 -10
  112. package/dist/tools/index.js +10 -10
  113. package/dist/tools/media.d.ts +2 -2
  114. package/dist/tools/media.js +80 -80
  115. package/dist/tools/pages.d.ts +2 -2
  116. package/dist/tools/pages.d.ts.map +1 -1
  117. package/dist/tools/pages.js +75 -75
  118. package/dist/tools/pages.js.map +1 -1
  119. package/dist/tools/performance.d.ts +1 -1
  120. package/dist/tools/performance.d.ts.map +1 -1
  121. package/dist/tools/performance.js +311 -287
  122. package/dist/tools/performance.js.map +1 -1
  123. package/dist/tools/posts.d.ts +2 -2
  124. package/dist/tools/posts.d.ts.map +1 -1
  125. package/dist/tools/posts.js +94 -94
  126. package/dist/tools/posts.js.map +1 -1
  127. package/dist/tools/site.d.ts +2 -2
  128. package/dist/tools/site.d.ts.map +1 -1
  129. package/dist/tools/site.js +60 -60
  130. package/dist/tools/site.js.map +1 -1
  131. package/dist/tools/taxonomies.d.ts +2 -2
  132. package/dist/tools/taxonomies.js +89 -89
  133. package/dist/tools/users.d.ts +2 -2
  134. package/dist/tools/users.js +68 -68
  135. package/dist/tools/users.js.map +1 -1
  136. package/dist/types/client.d.ts +13 -13
  137. package/dist/types/client.d.ts.map +1 -1
  138. package/dist/types/client.js +12 -12
  139. package/dist/types/client.js.map +1 -1
  140. package/dist/types/index.d.ts +19 -19
  141. package/dist/types/index.d.ts.map +1 -1
  142. package/dist/types/index.js +3 -3
  143. package/dist/types/mcp.d.ts +7 -7
  144. package/dist/types/wordpress.d.ts +21 -21
  145. package/dist/types/wordpress.d.ts.map +1 -1
  146. package/dist/utils/debug.d.ts +2 -2
  147. package/dist/utils/debug.js +28 -28
  148. package/dist/utils/error.d.ts.map +1 -1
  149. package/dist/utils/error.js +13 -13
  150. package/dist/utils/error.js.map +1 -1
  151. package/dist/utils/toolWrapper.d.ts.map +1 -1
  152. package/dist/utils/toolWrapper.js +5 -5
  153. package/dist/utils/toolWrapper.js.map +1 -1
  154. package/dist/utils/validation.d.ts.map +1 -1
  155. package/dist/utils/validation.js +41 -31
  156. package/dist/utils/validation.js.map +1 -1
  157. package/docs/CACHING.md +36 -2
  158. package/docs/DOCKER.md +24 -18
  159. package/docs/PERFORMANCE_MONITORING.md +49 -1
  160. package/docs/SECURITY_TESTING.md +30 -1
  161. package/docs/api/README.md +9 -1
  162. package/docs/api/summary.json +1 -1
  163. package/docs/contract-testing.md +24 -3
  164. package/docs/developer/GITHUB_ACTIONS_SETUP.md +8 -2
  165. package/docs/developer/MAINTENANCE.md +29 -3
  166. package/docs/developer/MIGRATION_GUIDE.md +13 -1
  167. package/docs/developer/NPM_AUTH_SETUP.md +13 -2
  168. package/docs/developer/REFACTORING.md +31 -1
  169. package/docs/releases/COMMUNITY_ANNOUNCEMENT_v1.1.2.md +18 -7
  170. package/docs/releases/RELEASE_NOTES_v1.1.2.md +31 -5
  171. package/docs/user-guides/DOCKER_SETUP.md +264 -0
  172. package/docs/user-guides/DTX_SETUP.md +327 -0
  173. package/docs/user-guides/NPM_SETUP.md +109 -0
  174. package/docs/user-guides/NPX_SETUP.md +281 -0
  175. package/docs/wordpress-rest-api-authentication-troubleshooting.md +13 -2
  176. package/package.json +27 -8
  177. package/src/cache/CacheInvalidation.ts +140 -132
  178. package/src/cache/CacheManager.ts +40 -29
  179. package/src/cache/HttpCacheWrapper.ts +105 -68
  180. package/src/cache/__tests__/CacheInvalidation.test.ts +123 -118
  181. package/src/cache/__tests__/CacheManager.test.ts +156 -152
  182. package/src/cache/__tests__/CachedWordPressClient.test.ts +131 -116
  183. package/src/cache/__tests__/HttpCacheWrapper.test.ts +118 -115
  184. package/src/cache/index.ts +13 -13
  185. package/src/client/CachedWordPressClient.ts +90 -80
  186. package/src/client/api.ts +205 -205
  187. package/src/client/auth.ts +80 -80
  188. package/src/client/managers/AuthenticationManager.ts +61 -61
  189. package/src/client/managers/BaseManager.ts +11 -11
  190. package/src/client/managers/RequestManager.ts +79 -47
  191. package/src/client/managers/index.ts +3 -3
  192. package/src/config/ConfigurationSchema.ts +44 -44
  193. package/src/config/ServerConfiguration.ts +39 -39
  194. package/src/docs/DocumentationGenerator.ts +402 -295
  195. package/src/docs/MarkdownFormatter.ts +94 -69
  196. package/src/docs/index.ts +4 -4
  197. package/src/index.ts +24 -21
  198. package/src/performance/MetricsCollector.ts +90 -58
  199. package/src/performance/PerformanceAnalytics.ts +386 -262
  200. package/src/performance/PerformanceMonitor.ts +152 -118
  201. package/src/performance/index.ts +9 -9
  202. package/src/security/InputValidator.ts +148 -91
  203. package/src/security/SecurityConfig.ts +94 -94
  204. package/src/server/ConnectionTester.ts +21 -15
  205. package/src/server/ToolRegistry.ts +64 -51
  206. package/src/server.ts +2 -2
  207. package/src/tools/BaseToolManager.ts +6 -6
  208. package/src/tools/auth.ts +42 -37
  209. package/src/tools/cache.ts +85 -81
  210. package/src/tools/comments.ts +93 -91
  211. package/src/tools/index.ts +10 -10
  212. package/src/tools/media.ts +89 -89
  213. package/src/tools/pages.ts +89 -87
  214. package/src/tools/performance.ts +443 -352
  215. package/src/tools/posts.ts +109 -107
  216. package/src/tools/site.ts +86 -77
  217. package/src/tools/taxonomies.ts +102 -102
  218. package/src/tools/users.ts +77 -77
  219. package/src/types/client.ts +157 -60
  220. package/src/types/index.ts +49 -27
  221. package/src/types/mcp.ts +15 -15
  222. package/src/types/wordpress.ts +57 -29
  223. package/src/utils/debug.ts +37 -37
  224. package/src/utils/error.ts +47 -25
  225. package/src/utils/toolWrapper.ts +12 -8
  226. package/src/utils/validation.ts +116 -65
  227. package/dist/client/WordPressClient.d.ts +0 -81
  228. package/dist/client/WordPressClient.d.ts.map +0 -1
  229. package/dist/client/WordPressClient.js +0 -354
  230. package/dist/client/WordPressClient.js.map +0 -1
  231. package/dist/performance/AnomalyDetector.d.ts +0 -63
  232. package/dist/performance/AnomalyDetector.d.ts.map +0 -1
  233. package/dist/performance/AnomalyDetector.js +0 -222
  234. package/dist/performance/AnomalyDetector.js.map +0 -1
  235. package/dist/performance/BenchmarkAnalyzer.d.ts +0 -67
  236. package/dist/performance/BenchmarkAnalyzer.d.ts.map +0 -1
  237. package/dist/performance/BenchmarkAnalyzer.js +0 -301
  238. package/dist/performance/BenchmarkAnalyzer.js.map +0 -1
  239. package/dist/performance/TrendAnalyzer.d.ts +0 -69
  240. package/dist/performance/TrendAnalyzer.d.ts.map +0 -1
  241. package/dist/performance/TrendAnalyzer.js +0 -203
  242. package/dist/performance/TrendAnalyzer.js.map +0 -1
  243. package/dist/tools/BaseToolClass.d.ts +0 -76
  244. package/dist/tools/BaseToolClass.d.ts.map +0 -1
  245. package/dist/tools/BaseToolClass.js +0 -104
  246. package/dist/tools/BaseToolClass.js.map +0 -1
  247. package/dist/tools/base.d.ts +0 -37
  248. package/dist/tools/base.d.ts.map +0 -1
  249. package/dist/tools/base.js +0 -60
  250. package/dist/tools/base.js.map +0 -1
  251. package/docs/user-guides/CLAUDE_DESKTOP_SETUP.md +0 -187
package/src/client/api.ts CHANGED
@@ -3,10 +3,10 @@
3
3
  * Handles all REST API communication with WordPress
4
4
  */
5
5
 
6
- import fetch from 'node-fetch';
7
- import FormData from 'form-data';
8
- import * as fs from 'fs';
9
- import * as path from 'path';
6
+ import fetch from "node-fetch";
7
+ import FormData from "form-data";
8
+ import * as fs from "fs";
9
+ import * as path from "path";
10
10
  import type {
11
11
  IWordPressClient,
12
12
  WordPressClientConfig,
@@ -14,13 +14,13 @@ import type {
14
14
  AuthMethod,
15
15
  HTTPMethod,
16
16
  RequestOptions,
17
- ClientStats
18
- } from '../types/client.js';
17
+ ClientStats,
18
+ } from "../types/client.js";
19
19
  import {
20
20
  WordPressAPIError,
21
21
  AuthenticationError,
22
- RateLimitError
23
- } from '../types/client.js';
22
+ RateLimitError,
23
+ } from "../types/client.js";
24
24
  import type {
25
25
  WordPressPost,
26
26
  WordPressPage,
@@ -48,9 +48,9 @@ import type {
48
48
  CreateTagRequest,
49
49
  UpdateTagRequest,
50
50
  UploadMediaRequest,
51
- UpdateMediaRequest
52
- } from '../types/wordpress.js';
53
- import { debug, logError, startTimer } from '../utils/debug.js';
51
+ UpdateMediaRequest,
52
+ } from "../types/wordpress.js";
53
+ import { debug, logError, startTimer } from "../utils/debug.js";
54
54
 
55
55
  export class WordPressClient implements IWordPressClient {
56
56
  private baseUrl: string;
@@ -66,18 +66,18 @@ export class WordPressClient implements IWordPressClient {
66
66
  private _stats: ClientStats;
67
67
 
68
68
  constructor(options: Partial<WordPressClientConfig> = {}) {
69
- this.baseUrl = options.baseUrl || process.env.WORDPRESS_SITE_URL || '';
70
- this.apiUrl = '';
69
+ this.baseUrl = options.baseUrl || process.env.WORDPRESS_SITE_URL || "";
70
+ this.apiUrl = "";
71
71
  this.timeout =
72
- options.timeout || parseInt(process.env.WORDPRESS_TIMEOUT || '30000');
72
+ options.timeout || parseInt(process.env.WORDPRESS_TIMEOUT || "30000");
73
73
  this.maxRetries =
74
- options.maxRetries || parseInt(process.env.WORDPRESS_MAX_RETRIES || '3');
74
+ options.maxRetries || parseInt(process.env.WORDPRESS_MAX_RETRIES || "3");
75
75
 
76
76
  // Authentication configuration
77
77
  this.auth = options.auth || this.getAuthFromEnv();
78
78
 
79
79
  // Rate limiting
80
- this.requestInterval = 60000 / parseInt(process.env.RATE_LIMIT || '60');
80
+ this.requestInterval = 60000 / parseInt(process.env.RATE_LIMIT || "60");
81
81
 
82
82
  // Initialize stats
83
83
  this._stats = {
@@ -86,7 +86,7 @@ export class WordPressClient implements IWordPressClient {
86
86
  failedRequests: 0,
87
87
  averageResponseTime: 0,
88
88
  rateLimitHits: 0,
89
- authFailures: 0
89
+ authFailures: 0,
90
90
  };
91
91
 
92
92
  // Validate configuration
@@ -98,7 +98,7 @@ export class WordPressClient implements IWordPressClient {
98
98
  baseUrl: this.baseUrl,
99
99
  auth: this.auth,
100
100
  timeout: this.timeout,
101
- maxRetries: this.maxRetries
101
+ maxRetries: this.maxRetries,
102
102
  };
103
103
  }
104
104
 
@@ -115,23 +115,23 @@ export class WordPressClient implements IWordPressClient {
115
115
 
116
116
  // Use explicit auth method if set
117
117
  if (
118
- authMethod === 'app-password' &&
118
+ authMethod === "app-password" &&
119
119
  process.env.WORDPRESS_USERNAME &&
120
120
  process.env.WORDPRESS_APP_PASSWORD
121
121
  ) {
122
122
  return {
123
- method: 'app-password',
123
+ method: "app-password",
124
124
  username: process.env.WORDPRESS_USERNAME,
125
- appPassword: process.env.WORDPRESS_APP_PASSWORD
125
+ appPassword: process.env.WORDPRESS_APP_PASSWORD,
126
126
  };
127
127
  }
128
128
 
129
129
  // Try Application Password first (fallback)
130
130
  if (process.env.WORDPRESS_USERNAME && process.env.WORDPRESS_APP_PASSWORD) {
131
131
  return {
132
- method: 'app-password',
132
+ method: "app-password",
133
133
  username: process.env.WORDPRESS_USERNAME,
134
- appPassword: process.env.WORDPRESS_APP_PASSWORD
134
+ appPassword: process.env.WORDPRESS_APP_PASSWORD,
135
135
  };
136
136
  }
137
137
 
@@ -142,49 +142,49 @@ export class WordPressClient implements IWordPressClient {
142
142
  process.env.WORDPRESS_PASSWORD
143
143
  ) {
144
144
  return {
145
- method: 'jwt',
145
+ method: "jwt",
146
146
  secret: process.env.WORDPRESS_JWT_SECRET,
147
147
  username: process.env.WORDPRESS_USERNAME,
148
- password: process.env.WORDPRESS_PASSWORD
148
+ password: process.env.WORDPRESS_PASSWORD,
149
149
  };
150
150
  }
151
151
 
152
152
  // Try API Key
153
153
  if (process.env.WORDPRESS_API_KEY) {
154
154
  return {
155
- method: 'api-key',
156
- apiKey: process.env.WORDPRESS_API_KEY
155
+ method: "api-key",
156
+ apiKey: process.env.WORDPRESS_API_KEY,
157
157
  };
158
158
  }
159
159
 
160
160
  // Try Cookie
161
161
  if (process.env.WORDPRESS_COOKIE_NONCE) {
162
162
  return {
163
- method: 'cookie',
164
- nonce: process.env.WORDPRESS_COOKIE_NONCE
163
+ method: "cookie",
164
+ nonce: process.env.WORDPRESS_COOKIE_NONCE,
165
165
  };
166
166
  }
167
167
 
168
168
  // Default to basic authentication
169
169
  return {
170
- method: 'basic',
171
- username: process.env.WORDPRESS_USERNAME || '',
170
+ method: "basic",
171
+ username: process.env.WORDPRESS_USERNAME || "",
172
172
  password:
173
173
  process.env.WORDPRESS_PASSWORD ||
174
174
  process.env.WORDPRESS_APP_PASSWORD ||
175
- ''
175
+ "",
176
176
  };
177
177
  }
178
178
 
179
179
  private validateConfig(): void {
180
180
  if (!this.baseUrl) {
181
181
  throw new Error(
182
- 'WordPress configuration is incomplete: baseUrl is required'
182
+ "WordPress configuration is incomplete: baseUrl is required",
183
183
  );
184
184
  }
185
185
 
186
186
  // Ensure URL doesn't end with slash and add API path
187
- this.baseUrl = this.baseUrl.replace(/\/$/, '');
187
+ this.baseUrl = this.baseUrl.replace(/\/$/, "");
188
188
  this.apiUrl = `${this.baseUrl}/wp-json/wp/v2`;
189
189
 
190
190
  debug.log(`WordPress API Client initialized for: ${this.apiUrl}`);
@@ -197,7 +197,7 @@ export class WordPressClient implements IWordPressClient {
197
197
  async disconnect(): Promise<void> {
198
198
  this.authenticated = false;
199
199
  this.jwtToken = null;
200
- debug.log('WordPress client disconnected');
200
+ debug.log("WordPress client disconnected");
201
201
  }
202
202
 
203
203
  /**
@@ -207,38 +207,38 @@ export class WordPressClient implements IWordPressClient {
207
207
  const method = this.auth.method?.toLowerCase() as AuthMethod;
208
208
 
209
209
  switch (method) {
210
- case 'app-password':
210
+ case "app-password":
211
211
  if (this.auth.username && this.auth.appPassword) {
212
212
  const credentials = Buffer.from(
213
- `${this.auth.username}:${this.auth.appPassword}`
214
- ).toString('base64');
215
- headers['Authorization'] = `Basic ${credentials}`;
213
+ `${this.auth.username}:${this.auth.appPassword}`,
214
+ ).toString("base64");
215
+ headers["Authorization"] = `Basic ${credentials}`;
216
216
  }
217
217
  break;
218
- case 'basic':
218
+ case "basic":
219
219
  if (this.auth.username && this.auth.password) {
220
220
  const credentials = Buffer.from(
221
- `${this.auth.username}:${this.auth.password}`
222
- ).toString('base64');
223
- headers['Authorization'] = `Basic ${credentials}`;
221
+ `${this.auth.username}:${this.auth.password}`,
222
+ ).toString("base64");
223
+ headers["Authorization"] = `Basic ${credentials}`;
224
224
  }
225
225
  break;
226
226
 
227
- case 'jwt':
227
+ case "jwt":
228
228
  if (this.jwtToken) {
229
- headers['Authorization'] = `Bearer ${this.jwtToken}`;
229
+ headers["Authorization"] = `Bearer ${this.jwtToken}`;
230
230
  }
231
231
  break;
232
232
 
233
- case 'api-key':
233
+ case "api-key":
234
234
  if (this.auth.apiKey) {
235
- headers['X-API-Key'] = this.auth.apiKey;
235
+ headers["X-API-Key"] = this.auth.apiKey;
236
236
  }
237
237
  break;
238
238
 
239
- case 'cookie':
239
+ case "cookie":
240
240
  if (this.auth.nonce) {
241
- headers['X-WP-Nonce'] = this.auth.nonce;
241
+ headers["X-WP-Nonce"] = this.auth.nonce;
242
242
  }
243
243
  break;
244
244
  }
@@ -271,14 +271,14 @@ export class WordPressClient implements IWordPressClient {
271
271
 
272
272
  try {
273
273
  switch (method) {
274
- case 'app-password':
275
- case 'basic':
274
+ case "app-password":
275
+ case "basic":
276
276
  return await this.authenticateWithBasic();
277
- case 'jwt':
277
+ case "jwt":
278
278
  return await this.authenticateWithJWT();
279
- case 'cookie':
279
+ case "cookie":
280
280
  return await this.authenticateWithCookie();
281
- case 'api-key':
281
+ case "api-key":
282
282
  // API key auth doesn't require separate authentication step
283
283
  this.authenticated = true;
284
284
  return true;
@@ -298,31 +298,31 @@ export class WordPressClient implements IWordPressClient {
298
298
  private async authenticateWithBasic(): Promise<boolean> {
299
299
  const hasCredentials =
300
300
  this.auth.username &&
301
- (this.auth.method === 'app-password'
301
+ (this.auth.method === "app-password"
302
302
  ? this.auth.appPassword
303
303
  : this.auth.password);
304
304
 
305
305
  if (!hasCredentials) {
306
306
  const methodName =
307
- this.auth.method === 'app-password' ? 'Application Password' : 'Basic';
307
+ this.auth.method === "app-password" ? "Application Password" : "Basic";
308
308
  const passwordField =
309
- this.auth.method === 'app-password' ? 'app password' : 'password';
309
+ this.auth.method === "app-password" ? "app password" : "password";
310
310
  throw new AuthenticationError(
311
311
  `Username and ${passwordField} are required for ${methodName} authentication`,
312
- this.auth.method
312
+ this.auth.method,
313
313
  );
314
314
  }
315
315
 
316
316
  try {
317
317
  // Test authentication by getting current user
318
- await this.request<WordPressUser>('GET', 'users/me');
318
+ await this.request<WordPressUser>("GET", "users/me");
319
319
  this.authenticated = true;
320
- debug.log('Basic/Application Password authentication successful');
320
+ debug.log("Basic/Application Password authentication successful");
321
321
  return true;
322
322
  } catch (error) {
323
323
  throw new AuthenticationError(
324
324
  `Basic authentication failed: ${(error as Error).message}`,
325
- this.auth.method
325
+ this.auth.method,
326
326
  );
327
327
  }
328
328
  }
@@ -333,8 +333,8 @@ export class WordPressClient implements IWordPressClient {
333
333
  private async authenticateWithJWT(): Promise<boolean> {
334
334
  if (!this.auth.secret || !this.auth.username || !this.auth.password) {
335
335
  throw new AuthenticationError(
336
- 'JWT secret, username, and password are required for JWT authentication',
337
- this.auth.method
336
+ "JWT secret, username, and password are required for JWT authentication",
337
+ this.auth.method,
338
338
  );
339
339
  }
340
340
 
@@ -342,15 +342,15 @@ export class WordPressClient implements IWordPressClient {
342
342
  const response = await fetch(
343
343
  `${this.baseUrl}/wp-json/jwt-auth/v1/token`,
344
344
  {
345
- method: 'POST',
345
+ method: "POST",
346
346
  headers: {
347
- 'Content-Type': 'application/json'
347
+ "Content-Type": "application/json",
348
348
  },
349
349
  body: JSON.stringify({
350
350
  username: this.auth.username,
351
- password: this.auth.password
352
- })
353
- }
351
+ password: this.auth.password,
352
+ }),
353
+ },
354
354
  );
355
355
 
356
356
  if (!response.ok) {
@@ -360,12 +360,12 @@ export class WordPressClient implements IWordPressClient {
360
360
  const data = (await response.json()) as { token: string };
361
361
  this.jwtToken = data.token;
362
362
  this.authenticated = true;
363
- debug.log('JWT authentication successful');
363
+ debug.log("JWT authentication successful");
364
364
  return true;
365
365
  } catch (error) {
366
366
  throw new AuthenticationError(
367
367
  `JWT authentication failed: ${(error as Error).message}`,
368
- this.auth.method
368
+ this.auth.method,
369
369
  );
370
370
  }
371
371
  }
@@ -376,12 +376,12 @@ export class WordPressClient implements IWordPressClient {
376
376
  private async authenticateWithCookie(): Promise<boolean> {
377
377
  if (!this.auth.nonce) {
378
378
  throw new AuthenticationError(
379
- 'Nonce is required for cookie authentication',
380
- this.auth.method
379
+ "Nonce is required for cookie authentication",
380
+ this.auth.method,
381
381
  );
382
382
  }
383
383
  this.authenticated = true;
384
- debug.log('Cookie authentication configured');
384
+ debug.log("Cookie authentication configured");
385
385
  return true;
386
386
  }
387
387
 
@@ -392,21 +392,21 @@ export class WordPressClient implements IWordPressClient {
392
392
  method: HTTPMethod,
393
393
  endpoint: string,
394
394
  data: any = null,
395
- options: RequestOptions = {}
395
+ options: RequestOptions = {},
396
396
  ): Promise<T> {
397
397
  const timer = startTimer();
398
398
  this._stats.totalRequests++;
399
399
 
400
400
  // Handle endpoint properly - remove leading slash if present to avoid double slashes
401
- const cleanEndpoint = endpoint.replace(/^\/+/, '');
402
- const url = endpoint.startsWith('http')
401
+ const cleanEndpoint = endpoint.replace(/^\/+/, "");
402
+ const url = endpoint.startsWith("http")
403
403
  ? endpoint
404
404
  : `${this.apiUrl}/${cleanEndpoint}`;
405
405
 
406
406
  const headers: Record<string, string> = {
407
- 'Content-Type': 'application/json',
408
- 'User-Agent': 'MCP-WordPress/1.0.0',
409
- ...options.headers
407
+ "Content-Type": "application/json",
408
+ "User-Agent": "MCP-WordPress/1.0.0",
409
+ ...options.headers,
410
410
  };
411
411
 
412
412
  // Add authentication headers
@@ -418,25 +418,25 @@ export class WordPressClient implements IWordPressClient {
418
418
  const timeoutId = setTimeout(() => controller.abort(), requestTimeout);
419
419
 
420
420
  const fetchOptions: any = {
421
+ ...options, // Spread options first
421
422
  method,
422
- headers,
423
+ headers, // Headers come after to ensure auth headers aren't overridden
423
424
  signal: controller.signal,
424
- ...options
425
425
  };
426
426
 
427
427
  // Add body for POST/PUT/PATCH requests
428
- if (data && ['POST', 'PUT', 'PATCH'].includes(method)) {
428
+ if (data && ["POST", "PUT", "PATCH"].includes(method)) {
429
429
  if (
430
430
  data instanceof FormData ||
431
- (data && typeof data.append === 'function')
431
+ (data && typeof data.append === "function")
432
432
  ) {
433
433
  // For FormData, don't set Content-Type (let fetch set it with boundary)
434
- delete headers['Content-Type'];
434
+ delete headers["Content-Type"];
435
435
  fetchOptions.body = data;
436
436
  } else if (Buffer.isBuffer(data)) {
437
437
  // For Buffer data (manual multipart), keep Content-Type from headers
438
438
  fetchOptions.body = data;
439
- } else if (typeof data === 'string') {
439
+ } else if (typeof data === "string") {
440
440
  fetchOptions.body = data;
441
441
  } else {
442
442
  fetchOptions.body = JSON.stringify(data);
@@ -446,11 +446,11 @@ export class WordPressClient implements IWordPressClient {
446
446
  // Rate limiting
447
447
  await this.rateLimit();
448
448
 
449
- let lastError: Error = new Error('Unknown error');
449
+ let lastError: Error = new Error("Unknown error");
450
450
  for (let attempt = 0; attempt < this.maxRetries; attempt++) {
451
451
  try {
452
452
  debug.log(
453
- `API Request: ${method} ${url}${attempt > 0 ? ` (attempt ${attempt + 1})` : ''}`
453
+ `API Request: ${method} ${url}${attempt > 0 ? ` (attempt ${attempt + 1})` : ""}`,
454
454
  );
455
455
 
456
456
  const response = await fetch(url, fetchOptions);
@@ -479,29 +479,29 @@ export class WordPressClient implements IWordPressClient {
479
479
  // Handle permission errors specifically for uploads
480
480
  if (
481
481
  response.status === 403 &&
482
- endpoint.includes('media') &&
483
- method === 'POST'
482
+ endpoint.includes("media") &&
483
+ method === "POST"
484
484
  ) {
485
485
  throw new AuthenticationError(
486
- 'Media upload blocked: WordPress REST API media uploads appear to be disabled or restricted by a plugin/security policy. ' +
486
+ "Media upload blocked: WordPress REST API media uploads appear to be disabled or restricted by a plugin/security policy. " +
487
487
  `Error: ${errorMessage}. ` +
488
- 'Common causes: W3 Total Cache, security plugins, or custom REST API restrictions. ' +
489
- 'Please check WordPress admin settings or contact your system administrator.',
490
- this.auth.method
488
+ "Common causes: W3 Total Cache, security plugins, or custom REST API restrictions. " +
489
+ "Please check WordPress admin settings or contact your system administrator.",
490
+ this.auth.method,
491
491
  );
492
492
  }
493
493
 
494
494
  // Handle general upload permission errors
495
495
  if (
496
- errorMessage.includes('Beiträge zu erstellen') &&
497
- endpoint.includes('media')
496
+ errorMessage.includes("Beiträge zu erstellen") &&
497
+ endpoint.includes("media")
498
498
  ) {
499
499
  throw new AuthenticationError(
500
500
  `WordPress REST API media upload restriction detected: ${errorMessage}. ` +
501
- 'This typically indicates that media uploads via REST API are disabled by WordPress configuration, ' +
502
- 'a security plugin (like W3 Total Cache, Borlabs Cookie), or server policy. ' +
503
- 'User has sufficient permissions but WordPress/plugins are blocking the upload.',
504
- this.auth.method
501
+ "This typically indicates that media uploads via REST API are disabled by WordPress configuration, " +
502
+ "a security plugin (like W3 Total Cache, Borlabs Cookie), or server policy. " +
503
+ "User has sufficient permissions but WordPress/plugins are blocking the upload.",
504
+ this.auth.method,
505
505
  );
506
506
  }
507
507
 
@@ -525,9 +525,9 @@ export class WordPressClient implements IWordPressClient {
525
525
  return result as T;
526
526
  } catch (parseError) {
527
527
  // For authentication requests, malformed JSON should be an error
528
- if (endpoint.includes('users/me') || endpoint.includes('jwt-auth')) {
528
+ if (endpoint.includes("users/me") || endpoint.includes("jwt-auth")) {
529
529
  throw new WordPressAPIError(
530
- `Invalid JSON response: ${(parseError as Error).message}`
530
+ `Invalid JSON response: ${(parseError as Error).message}`,
531
531
  );
532
532
  }
533
533
  this._stats.successfulRequests++;
@@ -540,30 +540,30 @@ export class WordPressClient implements IWordPressClient {
540
540
  lastError = error as Error;
541
541
 
542
542
  // Handle timeout errors
543
- if ((error as any).name === 'AbortError') {
543
+ if ((error as any).name === "AbortError") {
544
544
  lastError = new Error(`Request timeout after ${requestTimeout}ms`);
545
545
  }
546
546
 
547
547
  // Handle network errors
548
548
  if (
549
- lastError.message.includes('socket hang up') ||
550
- lastError.message.includes('ECONNRESET')
549
+ lastError.message.includes("socket hang up") ||
550
+ lastError.message.includes("ECONNRESET")
551
551
  ) {
552
552
  lastError = new Error(
553
- `Network connection lost during upload: ${lastError.message}`
553
+ `Network connection lost during upload: ${lastError.message}`,
554
554
  );
555
555
  }
556
556
 
557
557
  debug.log(
558
- `Request failed (attempt ${attempt + 1}): ${lastError.message}`
558
+ `Request failed (attempt ${attempt + 1}): ${lastError.message}`,
559
559
  );
560
560
 
561
561
  // Don't retry on authentication errors, timeouts, or critical network errors
562
562
  if (
563
- lastError.message.includes('401') ||
564
- lastError.message.includes('403') ||
565
- lastError.message.includes('timeout') ||
566
- lastError.message.includes('Network connection lost')
563
+ lastError.message.includes("401") ||
564
+ lastError.message.includes("403") ||
565
+ lastError.message.includes("timeout") ||
566
+ lastError.message.includes("Network connection lost")
567
567
  ) {
568
568
  break;
569
569
  }
@@ -577,7 +577,7 @@ export class WordPressClient implements IWordPressClient {
577
577
  this._stats.failedRequests++;
578
578
  timer.end();
579
579
  throw new WordPressAPIError(
580
- `Request failed after ${this.maxRetries} attempts: ${lastError.message}`
580
+ `Request failed after ${this.maxRetries} attempts: ${lastError.message}`,
581
581
  );
582
582
  }
583
583
 
@@ -591,38 +591,38 @@ export class WordPressClient implements IWordPressClient {
591
591
 
592
592
  // HTTP method helpers
593
593
  async get<T = any>(endpoint: string, options?: RequestOptions): Promise<T> {
594
- return this.request<T>('GET', endpoint, null, options);
594
+ return this.request<T>("GET", endpoint, null, options);
595
595
  }
596
596
 
597
597
  async post<T = any>(
598
598
  endpoint: string,
599
599
  data?: any,
600
- options?: RequestOptions
600
+ options?: RequestOptions,
601
601
  ): Promise<T> {
602
- return this.request<T>('POST', endpoint, data, options);
602
+ return this.request<T>("POST", endpoint, data, options);
603
603
  }
604
604
 
605
605
  async put<T = any>(
606
606
  endpoint: string,
607
607
  data?: any,
608
- options?: RequestOptions
608
+ options?: RequestOptions,
609
609
  ): Promise<T> {
610
- return this.request<T>('PUT', endpoint, data, options);
610
+ return this.request<T>("PUT", endpoint, data, options);
611
611
  }
612
612
 
613
613
  async patch<T = any>(
614
614
  endpoint: string,
615
615
  data?: any,
616
- options?: RequestOptions
616
+ options?: RequestOptions,
617
617
  ): Promise<T> {
618
- return this.request<T>('PATCH', endpoint, data, options);
618
+ return this.request<T>("PATCH", endpoint, data, options);
619
619
  }
620
620
 
621
621
  async delete<T = any>(
622
622
  endpoint: string,
623
- options?: RequestOptions
623
+ options?: RequestOptions,
624
624
  ): Promise<T> {
625
- return this.request<T>('DELETE', endpoint, null, options);
625
+ return this.request<T>("DELETE", endpoint, null, options);
626
626
  }
627
627
 
628
628
  // WordPress API Methods
@@ -630,20 +630,20 @@ export class WordPressClient implements IWordPressClient {
630
630
  // Posts
631
631
  async getPosts(params?: PostQueryParams): Promise<WordPressPost[]> {
632
632
  const queryString = params
633
- ? '?' + new URLSearchParams(params as any).toString()
634
- : '';
633
+ ? "?" + new URLSearchParams(params as any).toString()
634
+ : "";
635
635
  return this.get<WordPressPost[]>(`posts${queryString}`);
636
636
  }
637
637
 
638
638
  async getPost(
639
639
  id: number,
640
- context: 'view' | 'embed' | 'edit' = 'view'
640
+ context: "view" | "embed" | "edit" = "view",
641
641
  ): Promise<WordPressPost> {
642
642
  return this.get<WordPressPost>(`posts/${id}?context=${context}`);
643
643
  }
644
644
 
645
645
  async createPost(data: CreatePostRequest): Promise<WordPressPost> {
646
- return this.post<WordPressPost>('posts', data);
646
+ return this.post<WordPressPost>("posts", data);
647
647
  }
648
648
 
649
649
  async updatePost(data: UpdatePostRequest): Promise<WordPressPost> {
@@ -653,7 +653,7 @@ export class WordPressClient implements IWordPressClient {
653
653
 
654
654
  async deletePost(
655
655
  id: number,
656
- force = false
656
+ force = false,
657
657
  ): Promise<{ deleted: boolean; previous?: WordPressPost }> {
658
658
  return this.delete(`posts/${id}?force=${force}`);
659
659
  }
@@ -665,20 +665,20 @@ export class WordPressClient implements IWordPressClient {
665
665
  // Pages
666
666
  async getPages(params?: PostQueryParams): Promise<WordPressPage[]> {
667
667
  const queryString = params
668
- ? '?' + new URLSearchParams(params as any).toString()
669
- : '';
668
+ ? "?" + new URLSearchParams(params as any).toString()
669
+ : "";
670
670
  return this.get<WordPressPage[]>(`pages${queryString}`);
671
671
  }
672
672
 
673
673
  async getPage(
674
674
  id: number,
675
- context: 'view' | 'embed' | 'edit' = 'view'
675
+ context: "view" | "embed" | "edit" = "view",
676
676
  ): Promise<WordPressPage> {
677
677
  return this.get<WordPressPage>(`pages/${id}?context=${context}`);
678
678
  }
679
679
 
680
680
  async createPage(data: CreatePageRequest): Promise<WordPressPage> {
681
- return this.post<WordPressPage>('pages', data);
681
+ return this.post<WordPressPage>("pages", data);
682
682
  }
683
683
 
684
684
  async updatePage(data: UpdatePageRequest): Promise<WordPressPage> {
@@ -688,7 +688,7 @@ export class WordPressClient implements IWordPressClient {
688
688
 
689
689
  async deletePage(
690
690
  id: number,
691
- force = false
691
+ force = false,
692
692
  ): Promise<{ deleted: boolean; previous?: WordPressPage }> {
693
693
  return this.delete(`pages/${id}?force=${force}`);
694
694
  }
@@ -700,14 +700,14 @@ export class WordPressClient implements IWordPressClient {
700
700
  // Media
701
701
  async getMedia(params?: MediaQueryParams): Promise<WordPressMedia[]> {
702
702
  const queryString = params
703
- ? '?' + new URLSearchParams(params as any).toString()
704
- : '';
703
+ ? "?" + new URLSearchParams(params as any).toString()
704
+ : "";
705
705
  return this.get<WordPressMedia[]>(`media${queryString}`);
706
706
  }
707
707
 
708
708
  async getMediaItem(
709
709
  id: number,
710
- context: 'view' | 'embed' | 'edit' = 'view'
710
+ context: "view" | "embed" | "edit" = "view",
711
711
  ): Promise<WordPressMedia> {
712
712
  return this.get<WordPressMedia>(`media/${id}?context=${context}`);
713
713
  }
@@ -725,19 +725,19 @@ export class WordPressClient implements IWordPressClient {
725
725
  const maxSize = 10 * 1024 * 1024; // 10MB reasonable limit
726
726
  if (stats.size > maxSize) {
727
727
  throw new Error(
728
- `File too large: ${(stats.size / 1024 / 1024).toFixed(2)}MB. Maximum allowed: ${maxSize / 1024 / 1024}MB`
728
+ `File too large: ${(stats.size / 1024 / 1024).toFixed(2)}MB. Maximum allowed: ${maxSize / 1024 / 1024}MB`,
729
729
  );
730
730
  }
731
731
 
732
732
  debug.log(
733
- `Uploading file: ${filename} (${(stats.size / 1024).toFixed(2)}KB)`
733
+ `Uploading file: ${filename} (${(stats.size / 1024).toFixed(2)}KB)`,
734
734
  );
735
735
 
736
736
  return this.uploadFile(
737
737
  fileBuffer,
738
738
  filename,
739
739
  this.getMimeType(data.file_path),
740
- data
740
+ data,
741
741
  );
742
742
  }
743
743
 
@@ -746,7 +746,7 @@ export class WordPressClient implements IWordPressClient {
746
746
  filename: string,
747
747
  mimeType: string,
748
748
  meta: Partial<UploadMediaRequest> = {},
749
- options?: RequestOptions
749
+ options?: RequestOptions,
750
750
  ): Promise<WordPressMedia> {
751
751
  debug.log(`Uploading file: ${filename} (${fileData.length} bytes)`);
752
752
 
@@ -755,30 +755,30 @@ export class WordPressClient implements IWordPressClient {
755
755
  formData.setMaxListeners(20);
756
756
 
757
757
  // Add file with correct options
758
- formData.append('file', fileData, {
758
+ formData.append("file", fileData, {
759
759
  filename,
760
- contentType: mimeType
760
+ contentType: mimeType,
761
761
  });
762
762
 
763
763
  // Add metadata
764
- if (meta.title) formData.append('title', meta.title);
765
- if (meta.alt_text) formData.append('alt_text', meta.alt_text);
766
- if (meta.caption) formData.append('caption', meta.caption);
767
- if (meta.description) formData.append('description', meta.description);
768
- if (meta.post) formData.append('post', meta.post.toString());
764
+ if (meta.title) formData.append("title", meta.title);
765
+ if (meta.alt_text) formData.append("alt_text", meta.alt_text);
766
+ if (meta.caption) formData.append("caption", meta.caption);
767
+ if (meta.description) formData.append("description", meta.description);
768
+ if (meta.post) formData.append("post", meta.post.toString());
769
769
 
770
770
  // Use longer timeout for file uploads
771
771
  const uploadTimeout =
772
772
  options?.timeout !== undefined ? options.timeout : 600000; // 10 minutes default
773
773
  const uploadOptions: RequestOptions = {
774
774
  ...options,
775
- timeout: uploadTimeout
775
+ timeout: uploadTimeout,
776
776
  };
777
777
 
778
778
  debug.log(`Upload prepared with FormData, timeout: ${uploadTimeout}ms`);
779
779
 
780
780
  // Use the regular post method which handles FormData correctly
781
- return this.post<WordPressMedia>('media', formData, uploadOptions);
781
+ return this.post<WordPressMedia>("media", formData, uploadOptions);
782
782
  }
783
783
 
784
784
  async updateMedia(data: UpdateMediaRequest): Promise<WordPressMedia> {
@@ -788,7 +788,7 @@ export class WordPressClient implements IWordPressClient {
788
788
 
789
789
  async deleteMedia(
790
790
  id: number,
791
- force = false
791
+ force = false,
792
792
  ): Promise<{ deleted: boolean; previous?: WordPressMedia }> {
793
793
  return this.delete(`media/${id}?force=${force}`);
794
794
  }
@@ -796,20 +796,20 @@ export class WordPressClient implements IWordPressClient {
796
796
  // Users
797
797
  async getUsers(params?: UserQueryParams): Promise<WordPressUser[]> {
798
798
  const queryString = params
799
- ? '?' + new URLSearchParams(params as any).toString()
800
- : '';
799
+ ? "?" + new URLSearchParams(params as any).toString()
800
+ : "";
801
801
  return this.get<WordPressUser[]>(`users${queryString}`);
802
802
  }
803
803
 
804
804
  async getUser(
805
- id: number | 'me',
806
- context: 'view' | 'embed' | 'edit' = 'view'
805
+ id: number | "me",
806
+ context: "view" | "embed" | "edit" = "view",
807
807
  ): Promise<WordPressUser> {
808
808
  return this.get<WordPressUser>(`users/${id}?context=${context}`);
809
809
  }
810
810
 
811
811
  async createUser(data: CreateUserRequest): Promise<WordPressUser> {
812
- return this.post<WordPressUser>('users', data);
812
+ return this.post<WordPressUser>("users", data);
813
813
  }
814
814
 
815
815
  async updateUser(data: UpdateUserRequest): Promise<WordPressUser> {
@@ -819,35 +819,35 @@ export class WordPressClient implements IWordPressClient {
819
819
 
820
820
  async deleteUser(
821
821
  id: number,
822
- reassign?: number
822
+ reassign?: number,
823
823
  ): Promise<{ deleted: boolean; previous?: WordPressUser }> {
824
824
  const params = reassign
825
825
  ? `?reassign=${reassign}&force=true`
826
- : '?force=true';
826
+ : "?force=true";
827
827
  return this.delete(`users/${id}${params}`);
828
828
  }
829
829
 
830
830
  async getCurrentUser(): Promise<WordPressUser> {
831
- return this.getUser('me');
831
+ return this.getUser("me");
832
832
  }
833
833
 
834
834
  // Comments
835
835
  async getComments(params?: CommentQueryParams): Promise<WordPressComment[]> {
836
836
  const queryString = params
837
- ? '?' + new URLSearchParams(params as any).toString()
838
- : '';
837
+ ? "?" + new URLSearchParams(params as any).toString()
838
+ : "";
839
839
  return this.get<WordPressComment[]>(`comments${queryString}`);
840
840
  }
841
841
 
842
842
  async getComment(
843
843
  id: number,
844
- context: 'view' | 'embed' | 'edit' = 'view'
844
+ context: "view" | "embed" | "edit" = "view",
845
845
  ): Promise<WordPressComment> {
846
846
  return this.get<WordPressComment>(`comments/${id}?context=${context}`);
847
847
  }
848
848
 
849
849
  async createComment(data: CreateCommentRequest): Promise<WordPressComment> {
850
- return this.post<WordPressComment>('comments', data);
850
+ return this.post<WordPressComment>("comments", data);
851
851
  }
852
852
 
853
853
  async updateComment(data: UpdateCommentRequest): Promise<WordPressComment> {
@@ -857,30 +857,30 @@ export class WordPressClient implements IWordPressClient {
857
857
 
858
858
  async deleteComment(
859
859
  id: number,
860
- force = false
860
+ force = false,
861
861
  ): Promise<{ deleted: boolean; previous?: WordPressComment }> {
862
862
  return this.delete(`comments/${id}?force=${force}`);
863
863
  }
864
864
 
865
865
  async approveComment(id: number): Promise<WordPressComment> {
866
- return this.put<WordPressComment>(`comments/${id}`, { status: 'approved' });
866
+ return this.put<WordPressComment>(`comments/${id}`, { status: "approved" });
867
867
  }
868
868
 
869
869
  async rejectComment(id: number): Promise<WordPressComment> {
870
870
  return this.put<WordPressComment>(`comments/${id}`, {
871
- status: 'unapproved'
871
+ status: "unapproved",
872
872
  });
873
873
  }
874
874
 
875
875
  async spamComment(id: number): Promise<WordPressComment> {
876
- return this.put<WordPressComment>(`comments/${id}`, { status: 'spam' });
876
+ return this.put<WordPressComment>(`comments/${id}`, { status: "spam" });
877
877
  }
878
878
 
879
879
  // Taxonomies
880
880
  async getCategories(params?: any): Promise<WordPressCategory[]> {
881
881
  const queryString = params
882
- ? '?' + new URLSearchParams(params).toString()
883
- : '';
882
+ ? "?" + new URLSearchParams(params).toString()
883
+ : "";
884
884
  return this.get<WordPressCategory[]>(`categories${queryString}`);
885
885
  }
886
886
 
@@ -889,13 +889,13 @@ export class WordPressClient implements IWordPressClient {
889
889
  }
890
890
 
891
891
  async createCategory(
892
- data: CreateCategoryRequest
892
+ data: CreateCategoryRequest,
893
893
  ): Promise<WordPressCategory> {
894
- return this.post<WordPressCategory>('categories', data);
894
+ return this.post<WordPressCategory>("categories", data);
895
895
  }
896
896
 
897
897
  async updateCategory(
898
- data: UpdateCategoryRequest
898
+ data: UpdateCategoryRequest,
899
899
  ): Promise<WordPressCategory> {
900
900
  const { id, ...updateData } = data;
901
901
  return this.put<WordPressCategory>(`categories/${id}`, updateData);
@@ -903,15 +903,15 @@ export class WordPressClient implements IWordPressClient {
903
903
 
904
904
  async deleteCategory(
905
905
  id: number,
906
- force = false
906
+ force = false,
907
907
  ): Promise<{ deleted: boolean; previous?: WordPressCategory }> {
908
908
  return this.delete(`categories/${id}?force=${force}`);
909
909
  }
910
910
 
911
911
  async getTags(params?: any): Promise<WordPressTag[]> {
912
912
  const queryString = params
913
- ? '?' + new URLSearchParams(params).toString()
914
- : '';
913
+ ? "?" + new URLSearchParams(params).toString()
914
+ : "";
915
915
  return this.get<WordPressTag[]>(`tags${queryString}`);
916
916
  }
917
917
 
@@ -920,7 +920,7 @@ export class WordPressClient implements IWordPressClient {
920
920
  }
921
921
 
922
922
  async createTag(data: CreateTagRequest): Promise<WordPressTag> {
923
- return this.post<WordPressTag>('tags', data);
923
+ return this.post<WordPressTag>("tags", data);
924
924
  }
925
925
 
926
926
  async updateTag(data: UpdateTagRequest): Promise<WordPressTag> {
@@ -930,51 +930,51 @@ export class WordPressClient implements IWordPressClient {
930
930
 
931
931
  async deleteTag(
932
932
  id: number,
933
- force = false
933
+ force = false,
934
934
  ): Promise<{ deleted: boolean; previous?: WordPressTag }> {
935
935
  return this.delete(`tags/${id}?force=${force}`);
936
936
  }
937
937
 
938
938
  // Site Management
939
939
  async getSiteSettings(): Promise<WordPressSiteSettings> {
940
- return this.get<WordPressSiteSettings>('settings');
940
+ return this.get<WordPressSiteSettings>("settings");
941
941
  }
942
942
 
943
943
  async updateSiteSettings(
944
- settings: Partial<WordPressSiteSettings>
944
+ settings: Partial<WordPressSiteSettings>,
945
945
  ): Promise<WordPressSiteSettings> {
946
- return this.post<WordPressSiteSettings>('settings', settings);
946
+ return this.post<WordPressSiteSettings>("settings", settings);
947
947
  }
948
948
 
949
949
  async getSiteInfo(): Promise<any> {
950
- return this.get('');
950
+ return this.get("");
951
951
  }
952
952
 
953
953
  // Application Passwords
954
954
  async getApplicationPasswords(
955
- userId: number | 'me' = 'me'
955
+ userId: number | "me" = "me",
956
956
  ): Promise<WordPressApplicationPassword[]> {
957
957
  return this.get<WordPressApplicationPassword[]>(
958
- `users/${userId}/application-passwords`
958
+ `users/${userId}/application-passwords`,
959
959
  );
960
960
  }
961
961
 
962
962
  async createApplicationPassword(
963
- userId: number | 'me',
963
+ userId: number | "me",
964
964
  name: string,
965
- appId?: string
965
+ appId?: string,
966
966
  ): Promise<WordPressApplicationPassword> {
967
967
  const data: any = { name };
968
968
  if (appId) data.app_id = appId;
969
969
  return this.post<WordPressApplicationPassword>(
970
970
  `users/${userId}/application-passwords`,
971
- data
971
+ data,
972
972
  );
973
973
  }
974
974
 
975
975
  async deleteApplicationPassword(
976
- userId: number | 'me',
977
- uuid: string
976
+ userId: number | "me",
977
+ uuid: string,
978
978
  ): Promise<{ deleted: boolean }> {
979
979
  return this.delete(`users/${userId}/application-passwords/${uuid}`);
980
980
  }
@@ -983,11 +983,11 @@ export class WordPressClient implements IWordPressClient {
983
983
  async search(
984
984
  query: string,
985
985
  types?: string[],
986
- subtype?: string
986
+ subtype?: string,
987
987
  ): Promise<any[]> {
988
988
  const params = new URLSearchParams({ search: query });
989
- if (types) params.append('type', types.join(','));
990
- if (subtype) params.append('subtype', subtype);
989
+ if (types) params.append("type", types.join(","));
990
+ if (subtype) params.append("subtype", subtype);
991
991
 
992
992
  return this.get<any[]>(`search?${params.toString()}`);
993
993
  }
@@ -995,7 +995,7 @@ export class WordPressClient implements IWordPressClient {
995
995
  // Utility Methods
996
996
  async ping(): Promise<boolean> {
997
997
  try {
998
- await this.get('');
998
+ await this.get("");
999
999
  return true;
1000
1000
  } catch {
1001
1001
  return false;
@@ -1003,7 +1003,7 @@ export class WordPressClient implements IWordPressClient {
1003
1003
  }
1004
1004
 
1005
1005
  async getServerInfo(): Promise<Record<string, any>> {
1006
- return this.get('');
1006
+ return this.get("");
1007
1007
  }
1008
1008
 
1009
1009
  validateEndpoint(endpoint: string): boolean {
@@ -1011,7 +1011,7 @@ export class WordPressClient implements IWordPressClient {
1011
1011
  }
1012
1012
 
1013
1013
  buildUrl(endpoint: string, params?: Record<string, any>): string {
1014
- const url = `${this.apiUrl}/${endpoint.replace(/^\/+/, '')}`;
1014
+ const url = `${this.apiUrl}/${endpoint.replace(/^\/+/, "")}`;
1015
1015
  if (params) {
1016
1016
  const searchParams = new URLSearchParams(params);
1017
1017
  return `${url}?${searchParams.toString()}`;
@@ -1022,22 +1022,22 @@ export class WordPressClient implements IWordPressClient {
1022
1022
  private getMimeType(filePath: string): string {
1023
1023
  const ext = path.extname(filePath).toLowerCase();
1024
1024
  const mimeTypes: Record<string, string> = {
1025
- '.jpg': 'image/jpeg',
1026
- '.jpeg': 'image/jpeg',
1027
- '.png': 'image/png',
1028
- '.gif': 'image/gif',
1029
- '.webp': 'image/webp',
1030
- '.svg': 'image/svg+xml',
1031
- '.pdf': 'application/pdf',
1032
- '.doc': 'application/msword',
1033
- '.docx':
1034
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
1035
- '.txt': 'text/plain',
1036
- '.mp4': 'video/mp4',
1037
- '.mp3': 'audio/mpeg',
1038
- '.wav': 'audio/wav'
1025
+ ".jpg": "image/jpeg",
1026
+ ".jpeg": "image/jpeg",
1027
+ ".png": "image/png",
1028
+ ".gif": "image/gif",
1029
+ ".webp": "image/webp",
1030
+ ".svg": "image/svg+xml",
1031
+ ".pdf": "application/pdf",
1032
+ ".doc": "application/msword",
1033
+ ".docx":
1034
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
1035
+ ".txt": "text/plain",
1036
+ ".mp4": "video/mp4",
1037
+ ".mp3": "audio/mpeg",
1038
+ ".wav": "audio/wav",
1039
1039
  };
1040
1040
 
1041
- return mimeTypes[ext] || 'application/octet-stream';
1041
+ return mimeTypes[ext] || "application/octet-stream";
1042
1042
  }
1043
1043
  }