mcp-wordpress 1.5.2 → 2.0.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 (190) hide show
  1. package/README.md +332 -61
  2. package/dist/cache/CacheInvalidation.d.ts.map +1 -1
  3. package/dist/cache/CacheInvalidation.js +4 -4
  4. package/dist/cache/CacheInvalidation.js.map +1 -1
  5. package/dist/client/MockWordPressClient.d.ts +55 -0
  6. package/dist/client/MockWordPressClient.d.ts.map +1 -0
  7. package/dist/client/MockWordPressClient.js +369 -0
  8. package/dist/client/MockWordPressClient.js.map +1 -0
  9. package/dist/client/api.d.ts +1 -0
  10. package/dist/client/api.d.ts.map +1 -1
  11. package/dist/client/api.js +26 -60
  12. package/dist/client/api.js.map +1 -1
  13. package/dist/client/managers/AuthenticationManager.d.ts.map +1 -1
  14. package/dist/client/managers/AuthenticationManager.js +4 -3
  15. package/dist/client/managers/AuthenticationManager.js.map +1 -1
  16. package/dist/config/ConfigurationSchema.d.ts +3 -3
  17. package/dist/config/ConfigurationSchema.d.ts.map +1 -1
  18. package/dist/config/ConfigurationSchema.js +7 -24
  19. package/dist/config/ConfigurationSchema.js.map +1 -1
  20. package/dist/config/ServerConfiguration.d.ts +8 -0
  21. package/dist/config/ServerConfiguration.d.ts.map +1 -1
  22. package/dist/config/ServerConfiguration.js +80 -31
  23. package/dist/config/ServerConfiguration.js.map +1 -1
  24. package/dist/docs/DocumentationGenerator.d.ts.map +1 -1
  25. package/dist/docs/DocumentationGenerator.js +5 -7
  26. package/dist/docs/DocumentationGenerator.js.map +1 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +33 -29
  29. package/dist/index.js.map +1 -1
  30. package/dist/security/InputValidator.d.ts.map +1 -1
  31. package/dist/security/InputValidator.js +3 -11
  32. package/dist/security/InputValidator.js.map +1 -1
  33. package/dist/server/ToolRegistry.d.ts +4 -0
  34. package/dist/server/ToolRegistry.d.ts.map +1 -1
  35. package/dist/server/ToolRegistry.js +71 -8
  36. package/dist/server/ToolRegistry.js.map +1 -1
  37. package/dist/tools/auth.d.ts.map +1 -1
  38. package/dist/tools/auth.js +8 -3
  39. package/dist/tools/auth.js.map +1 -1
  40. package/dist/tools/posts.d.ts.map +1 -1
  41. package/dist/tools/posts.js +287 -20
  42. package/dist/tools/posts.js.map +1 -1
  43. package/dist/tools/site.d.ts.map +1 -1
  44. package/dist/tools/site.js +47 -9
  45. package/dist/tools/site.js.map +1 -1
  46. package/dist/tools/users.d.ts.map +1 -1
  47. package/dist/tools/users.js +113 -10
  48. package/dist/tools/users.js.map +1 -1
  49. package/dist/utils/enhancedError.d.ts +61 -0
  50. package/dist/utils/enhancedError.d.ts.map +1 -0
  51. package/dist/utils/enhancedError.js +221 -0
  52. package/dist/utils/enhancedError.js.map +1 -0
  53. package/dist/utils/streaming.d.ts +104 -0
  54. package/dist/utils/streaming.d.ts.map +1 -0
  55. package/dist/utils/streaming.js +312 -0
  56. package/dist/utils/streaming.js.map +1 -0
  57. package/dist/utils/validation.d.ts +19 -3
  58. package/dist/utils/validation.d.ts.map +1 -1
  59. package/dist/utils/validation.js +174 -24
  60. package/dist/utils/validation.js.map +1 -1
  61. package/docs/ARCHITECTURE.md +850 -0
  62. package/docs/CACHING.md +20 -17
  63. package/docs/CONFIGURATION.md +660 -0
  64. package/docs/DOCKER.md +61 -60
  65. package/docs/EVALUATION.md +397 -0
  66. package/docs/INSTALLATION.md +423 -0
  67. package/docs/PERFORMANCE_MONITORING.md +17 -15
  68. package/docs/SECURITY.md +621 -0
  69. package/docs/SECURITY_TESTING.md +22 -26
  70. package/docs/TEST_SITE_SETUP.md +136 -0
  71. package/docs/TROUBLESHOOTING.md +578 -0
  72. package/docs/api/README.md +76 -91
  73. package/docs/api/categories/auth.md +0 -2
  74. package/docs/api/categories/cache.md +0 -2
  75. package/docs/api/categories/comment.md +0 -2
  76. package/docs/api/categories/media.md +0 -2
  77. package/docs/api/categories/page.md +0 -2
  78. package/docs/api/categories/performance.md +0 -2
  79. package/docs/api/categories/post.md +0 -2
  80. package/docs/api/categories/site.md +0 -2
  81. package/docs/api/categories/taxonomy.md +0 -2
  82. package/docs/api/categories/user.md +0 -2
  83. package/docs/api/summary.json +1 -1
  84. package/docs/api/tools/wp_approve_comment.md +11 -3
  85. package/docs/api/tools/wp_cache_clear.md +14 -5
  86. package/docs/api/tools/wp_cache_info.md +14 -5
  87. package/docs/api/tools/wp_cache_stats.md +14 -5
  88. package/docs/api/tools/wp_cache_warm.md +14 -5
  89. package/docs/api/tools/wp_create_application_password.md +11 -3
  90. package/docs/api/tools/wp_create_category.md +11 -3
  91. package/docs/api/tools/wp_create_comment.md +14 -5
  92. package/docs/api/tools/wp_create_page.md +13 -5
  93. package/docs/api/tools/wp_create_post.md +14 -7
  94. package/docs/api/tools/wp_create_tag.md +11 -3
  95. package/docs/api/tools/wp_create_user.md +13 -5
  96. package/docs/api/tools/wp_delete_application_password.md +11 -3
  97. package/docs/api/tools/wp_delete_category.md +11 -3
  98. package/docs/api/tools/wp_delete_comment.md +11 -3
  99. package/docs/api/tools/wp_delete_media.md +10 -3
  100. package/docs/api/tools/wp_delete_page.md +10 -3
  101. package/docs/api/tools/wp_delete_post.md +11 -5
  102. package/docs/api/tools/wp_delete_tag.md +11 -3
  103. package/docs/api/tools/wp_delete_user.md +10 -3
  104. package/docs/api/tools/wp_get_application_passwords.md +11 -3
  105. package/docs/api/tools/wp_get_auth_status.md +11 -3
  106. package/docs/api/tools/wp_get_category.md +11 -3
  107. package/docs/api/tools/wp_get_comment.md +11 -3
  108. package/docs/api/tools/wp_get_current_user.md +11 -3
  109. package/docs/api/tools/wp_get_media.md +11 -3
  110. package/docs/api/tools/wp_get_page.md +11 -3
  111. package/docs/api/tools/wp_get_page_revisions.md +11 -3
  112. package/docs/api/tools/wp_get_post.md +12 -5
  113. package/docs/api/tools/wp_get_post_revisions.md +11 -3
  114. package/docs/api/tools/wp_get_site_settings.md +10 -3
  115. package/docs/api/tools/wp_get_tag.md +11 -3
  116. package/docs/api/tools/wp_get_user.md +11 -3
  117. package/docs/api/tools/wp_list_categories.md +11 -3
  118. package/docs/api/tools/wp_list_comments.md +11 -3
  119. package/docs/api/tools/wp_list_media.md +14 -5
  120. package/docs/api/tools/wp_list_pages.md +14 -5
  121. package/docs/api/tools/wp_list_posts.md +15 -7
  122. package/docs/api/tools/wp_list_tags.md +11 -3
  123. package/docs/api/tools/wp_list_users.md +11 -3
  124. package/docs/api/tools/wp_performance_alerts.md +17 -7
  125. package/docs/api/tools/wp_performance_benchmark.md +17 -7
  126. package/docs/api/tools/wp_performance_export.md +17 -7
  127. package/docs/api/tools/wp_performance_history.md +17 -7
  128. package/docs/api/tools/wp_performance_optimize.md +17 -7
  129. package/docs/api/tools/wp_performance_stats.md +17 -7
  130. package/docs/api/tools/wp_search_site.md +11 -3
  131. package/docs/api/tools/wp_spam_comment.md +11 -3
  132. package/docs/api/tools/wp_switch_auth_method.md +14 -5
  133. package/docs/api/tools/wp_test_auth.md +11 -3
  134. package/docs/api/tools/wp_update_category.md +11 -3
  135. package/docs/api/tools/wp_update_comment.md +14 -5
  136. package/docs/api/tools/wp_update_media.md +14 -5
  137. package/docs/api/tools/wp_update_page.md +13 -5
  138. package/docs/api/tools/wp_update_post.md +14 -7
  139. package/docs/api/tools/wp_update_site_settings.md +14 -5
  140. package/docs/api/tools/wp_update_tag.md +11 -3
  141. package/docs/api/tools/wp_update_user.md +13 -5
  142. package/docs/api/tools/wp_upload_media.md +13 -5
  143. package/docs/api/types/WordPressPost.md +2 -0
  144. package/docs/code-improvements.md +40 -0
  145. package/docs/contract-testing.md +1 -1
  146. package/docs/developer/API_REFERENCE.md +19 -59
  147. package/docs/developer/ARCHITECTURE.md +8 -11
  148. package/docs/developer/BUILD_SYSTEM.md +2 -2
  149. package/docs/developer/CONTRIBUTING.md +3 -5
  150. package/docs/developer/GITHUB_ACTIONS_SETUP.md +2 -2
  151. package/docs/developer/MIGRATION_GUIDE.md +5 -6
  152. package/docs/developer/README.md +2 -1
  153. package/docs/developer/REFACTORING.md +9 -15
  154. package/docs/developer/RELEASE_PROCESS.md +4 -3
  155. package/docs/developer/TESTING.md +2 -2
  156. package/docs/examples/claude-desktop-config.md +8 -0
  157. package/docs/integrations/claude-desktop.md +426 -0
  158. package/docs/integrations/cline.md +537 -0
  159. package/docs/integrations/vs-code.md +515 -0
  160. package/docs/releases/COMMUNITY_ANNOUNCEMENT_v1.1.2.md +30 -23
  161. package/docs/releases/RELEASE_NOTES_v1.1.2.md +7 -6
  162. package/docs/testing-configurations.md +11 -0
  163. package/docs/user-guides/DOCKER_NPM_DTX_SETUP.md +3 -2
  164. package/docs/user-guides/DOCKER_SETUP.md +3 -2
  165. package/docs/user-guides/DTX_SETUP.md +6 -5
  166. package/docs/user-guides/DXT_INSTALLATION.md +4 -4
  167. package/docs/user-guides/NPM_SETUP.md +4 -2
  168. package/docs/user-guides/NPX_SETUP.md +4 -2
  169. package/docs/user-guides/SMITHERY_SETUP.md +402 -0
  170. package/docs/wordpress-rest-api-authentication-troubleshooting.md +45 -42
  171. package/package.json +12 -2
  172. package/src/cache/CacheInvalidation.ts +7 -18
  173. package/src/client/MockWordPressClient.ts +398 -0
  174. package/src/client/api.ts +77 -237
  175. package/src/client/managers/AuthenticationManager.ts +19 -56
  176. package/src/config/ConfigurationSchema.ts +14 -45
  177. package/src/config/ServerConfiguration.ts +98 -71
  178. package/src/docs/DocumentationGenerator.ts +39 -123
  179. package/src/dxt-entry.cjs +4 -1
  180. package/src/index.ts +35 -54
  181. package/src/security/InputValidator.ts +15 -57
  182. package/src/server/ToolRegistry.ts +88 -17
  183. package/src/tools/auth.ts +15 -22
  184. package/src/tools/posts.ts +347 -64
  185. package/src/tools/site.ts +69 -46
  186. package/src/tools/users.ts +142 -44
  187. package/src/utils/enhancedError.ts +248 -0
  188. package/src/utils/streaming.ts +428 -0
  189. package/src/utils/validation.ts +253 -92
  190. package/dist/mcp-wordpress-1.5.2.tgz +0 -0
package/src/client/api.ts CHANGED
@@ -16,11 +16,7 @@ import type {
16
16
  RequestOptions,
17
17
  ClientStats,
18
18
  } from "../types/client.js";
19
- import {
20
- WordPressAPIError,
21
- AuthenticationError,
22
- RateLimitError,
23
- } from "../types/client.js";
19
+ import { WordPressAPIError, AuthenticationError, RateLimitError } from "../types/client.js";
24
20
  import type {
25
21
  WordPressPost,
26
22
  WordPressPage,
@@ -68,10 +64,8 @@ export class WordPressClient implements IWordPressClient {
68
64
  constructor(options: Partial<WordPressClientConfig> = {}) {
69
65
  this.baseUrl = options.baseUrl || process.env.WORDPRESS_SITE_URL || "";
70
66
  this.apiUrl = "";
71
- this.timeout =
72
- options.timeout || parseInt(process.env.WORDPRESS_TIMEOUT || "30000");
73
- this.maxRetries =
74
- options.maxRetries || parseInt(process.env.WORDPRESS_MAX_RETRIES || "3");
67
+ this.timeout = options.timeout || parseInt(process.env.WORDPRESS_TIMEOUT || "30000");
68
+ this.maxRetries = options.maxRetries || parseInt(process.env.WORDPRESS_MAX_RETRIES || "3");
75
69
 
76
70
  // Authentication configuration
77
71
  this.auth = options.auth || this.getAuthFromEnv();
@@ -110,15 +104,15 @@ export class WordPressClient implements IWordPressClient {
110
104
  return { ...this._stats };
111
105
  }
112
106
 
107
+ getSiteUrl(): string {
108
+ return this.baseUrl;
109
+ }
110
+
113
111
  private getAuthFromEnv(): AuthConfig {
114
112
  const authMethod = process.env.WORDPRESS_AUTH_METHOD as AuthMethod;
115
113
 
116
114
  // Use explicit auth method if set
117
- if (
118
- authMethod === "app-password" &&
119
- process.env.WORDPRESS_USERNAME &&
120
- process.env.WORDPRESS_APP_PASSWORD
121
- ) {
115
+ if (authMethod === "app-password" && process.env.WORDPRESS_USERNAME && process.env.WORDPRESS_APP_PASSWORD) {
122
116
  return {
123
117
  method: "app-password",
124
118
  username: process.env.WORDPRESS_USERNAME,
@@ -136,11 +130,7 @@ export class WordPressClient implements IWordPressClient {
136
130
  }
137
131
 
138
132
  // Try JWT
139
- if (
140
- process.env.WORDPRESS_JWT_SECRET &&
141
- process.env.WORDPRESS_USERNAME &&
142
- process.env.WORDPRESS_PASSWORD
143
- ) {
133
+ if (process.env.WORDPRESS_JWT_SECRET && process.env.WORDPRESS_USERNAME && process.env.WORDPRESS_PASSWORD) {
144
134
  return {
145
135
  method: "jwt",
146
136
  secret: process.env.WORDPRESS_JWT_SECRET,
@@ -169,18 +159,13 @@ export class WordPressClient implements IWordPressClient {
169
159
  return {
170
160
  method: "basic",
171
161
  username: process.env.WORDPRESS_USERNAME || "",
172
- password:
173
- process.env.WORDPRESS_PASSWORD ||
174
- process.env.WORDPRESS_APP_PASSWORD ||
175
- "",
162
+ password: process.env.WORDPRESS_PASSWORD || process.env.WORDPRESS_APP_PASSWORD || "",
176
163
  };
177
164
  }
178
165
 
179
166
  private validateConfig(): void {
180
167
  if (!this.baseUrl) {
181
- throw new Error(
182
- "WordPress configuration is incomplete: baseUrl is required",
183
- );
168
+ throw new Error("WordPress configuration is incomplete: baseUrl is required");
184
169
  }
185
170
 
186
171
  // Ensure URL doesn't end with slash and add API path
@@ -209,17 +194,13 @@ export class WordPressClient implements IWordPressClient {
209
194
  switch (method) {
210
195
  case "app-password":
211
196
  if (this.auth.username && this.auth.appPassword) {
212
- const credentials = Buffer.from(
213
- `${this.auth.username}:${this.auth.appPassword}`,
214
- ).toString("base64");
197
+ const credentials = Buffer.from(`${this.auth.username}:${this.auth.appPassword}`).toString("base64");
215
198
  headers["Authorization"] = `Basic ${credentials}`;
216
199
  }
217
200
  break;
218
201
  case "basic":
219
202
  if (this.auth.username && this.auth.password) {
220
- const credentials = Buffer.from(
221
- `${this.auth.username}:${this.auth.password}`,
222
- ).toString("base64");
203
+ const credentials = Buffer.from(`${this.auth.username}:${this.auth.password}`).toString("base64");
223
204
  headers["Authorization"] = `Basic ${credentials}`;
224
205
  }
225
206
  break;
@@ -297,16 +278,11 @@ export class WordPressClient implements IWordPressClient {
297
278
  */
298
279
  private async authenticateWithBasic(): Promise<boolean> {
299
280
  const hasCredentials =
300
- this.auth.username &&
301
- (this.auth.method === "app-password"
302
- ? this.auth.appPassword
303
- : this.auth.password);
281
+ this.auth.username && (this.auth.method === "app-password" ? this.auth.appPassword : this.auth.password);
304
282
 
305
283
  if (!hasCredentials) {
306
- const methodName =
307
- this.auth.method === "app-password" ? "Application Password" : "Basic";
308
- const passwordField =
309
- this.auth.method === "app-password" ? "app password" : "password";
284
+ const methodName = this.auth.method === "app-password" ? "Application Password" : "Basic";
285
+ const passwordField = this.auth.method === "app-password" ? "app password" : "password";
310
286
  throw new AuthenticationError(
311
287
  `Username and ${passwordField} are required for ${methodName} authentication`,
312
288
  this.auth.method,
@@ -320,10 +296,7 @@ export class WordPressClient implements IWordPressClient {
320
296
  debug.log("Basic/Application Password authentication successful");
321
297
  return true;
322
298
  } catch (error) {
323
- throw new AuthenticationError(
324
- `Basic authentication failed: ${(error as Error).message}`,
325
- this.auth.method,
326
- );
299
+ throw new AuthenticationError(`Basic authentication failed: ${(error as Error).message}`, this.auth.method);
327
300
  }
328
301
  }
329
302
 
@@ -339,19 +312,16 @@ export class WordPressClient implements IWordPressClient {
339
312
  }
340
313
 
341
314
  try {
342
- const response = await fetch(
343
- `${this.baseUrl}/wp-json/jwt-auth/v1/token`,
344
- {
345
- method: "POST",
346
- headers: {
347
- "Content-Type": "application/json",
348
- },
349
- body: JSON.stringify({
350
- username: this.auth.username,
351
- password: this.auth.password,
352
- }),
315
+ const response = await fetch(`${this.baseUrl}/wp-json/jwt-auth/v1/token`, {
316
+ method: "POST",
317
+ headers: {
318
+ "Content-Type": "application/json",
353
319
  },
354
- );
320
+ body: JSON.stringify({
321
+ username: this.auth.username,
322
+ password: this.auth.password,
323
+ }),
324
+ });
355
325
 
356
326
  if (!response.ok) {
357
327
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
@@ -363,10 +333,7 @@ export class WordPressClient implements IWordPressClient {
363
333
  debug.log("JWT authentication successful");
364
334
  return true;
365
335
  } catch (error) {
366
- throw new AuthenticationError(
367
- `JWT authentication failed: ${(error as Error).message}`,
368
- this.auth.method,
369
- );
336
+ throw new AuthenticationError(`JWT authentication failed: ${(error as Error).message}`, this.auth.method);
370
337
  }
371
338
  }
372
339
 
@@ -375,10 +342,7 @@ export class WordPressClient implements IWordPressClient {
375
342
  */
376
343
  private async authenticateWithCookie(): Promise<boolean> {
377
344
  if (!this.auth.nonce) {
378
- throw new AuthenticationError(
379
- "Nonce is required for cookie authentication",
380
- this.auth.method,
381
- );
345
+ throw new AuthenticationError("Nonce is required for cookie authentication", this.auth.method);
382
346
  }
383
347
  this.authenticated = true;
384
348
  debug.log("Cookie authentication configured");
@@ -399,9 +363,7 @@ export class WordPressClient implements IWordPressClient {
399
363
 
400
364
  // Handle endpoint properly - remove leading slash if present to avoid double slashes
401
365
  const cleanEndpoint = endpoint.replace(/^\/+/, "");
402
- const url = endpoint.startsWith("http")
403
- ? endpoint
404
- : `${this.apiUrl}/${cleanEndpoint}`;
366
+ const url = endpoint.startsWith("http") ? endpoint : `${this.apiUrl}/${cleanEndpoint}`;
405
367
 
406
368
  const headers: Record<string, string> = {
407
369
  "Content-Type": "application/json",
@@ -426,10 +388,7 @@ export class WordPressClient implements IWordPressClient {
426
388
 
427
389
  // Add body for POST/PUT/PATCH requests
428
390
  if (data && ["POST", "PUT", "PATCH"].includes(method)) {
429
- if (
430
- data instanceof FormData ||
431
- (data && typeof data.append === "function")
432
- ) {
391
+ if (data instanceof FormData || (data && typeof data.append === "function")) {
433
392
  // For FormData, check if it has getHeaders method (form-data package)
434
393
  if (data && typeof data.getHeaders === "function") {
435
394
  // Use headers from form-data package
@@ -456,9 +415,7 @@ export class WordPressClient implements IWordPressClient {
456
415
  let lastError: Error = new Error("Unknown error");
457
416
  for (let attempt = 0; attempt < this.maxRetries; attempt++) {
458
417
  try {
459
- debug.log(
460
- `API Request: ${method} ${url}${attempt > 0 ? ` (attempt ${attempt + 1})` : ""}`,
461
- );
418
+ debug.log(`API Request: ${method} ${url}${attempt > 0 ? ` (attempt ${attempt + 1})` : ""}`);
462
419
 
463
420
  const response = await fetch(url, fetchOptions);
464
421
  clearTimeout(timeoutId);
@@ -470,11 +427,9 @@ export class WordPressClient implements IWordPressClient {
470
427
 
471
428
  try {
472
429
  const errorData = JSON.parse(errorText);
473
- errorMessage =
474
- errorData.message || errorData.error || `HTTP ${response.status}`;
430
+ errorMessage = errorData.message || errorData.error || `HTTP ${response.status}`;
475
431
  } catch {
476
- errorMessage =
477
- errorText || `HTTP ${response.status}: ${response.statusText}`;
432
+ errorMessage = errorText || `HTTP ${response.status}: ${response.statusText}`;
478
433
  }
479
434
 
480
435
  // Handle rate limiting
@@ -484,11 +439,7 @@ export class WordPressClient implements IWordPressClient {
484
439
  }
485
440
 
486
441
  // Handle permission errors specifically for uploads
487
- if (
488
- response.status === 403 &&
489
- endpoint.includes("media") &&
490
- method === "POST"
491
- ) {
442
+ if (response.status === 403 && endpoint.includes("media") && method === "POST") {
492
443
  throw new AuthenticationError(
493
444
  "Media upload blocked: WordPress REST API media uploads appear to be disabled or restricted by a plugin/security policy. " +
494
445
  `Error: ${errorMessage}. ` +
@@ -499,10 +450,7 @@ export class WordPressClient implements IWordPressClient {
499
450
  }
500
451
 
501
452
  // Handle general upload permission errors
502
- if (
503
- errorMessage.includes("Beiträge zu erstellen") &&
504
- endpoint.includes("media")
505
- ) {
453
+ if (errorMessage.includes("Beiträge zu erstellen") && endpoint.includes("media")) {
506
454
  throw new AuthenticationError(
507
455
  `WordPress REST API media upload restriction detected: ${errorMessage}. ` +
508
456
  "This typically indicates that media uploads via REST API are disabled by WordPress configuration, " +
@@ -533,9 +481,7 @@ export class WordPressClient implements IWordPressClient {
533
481
  } catch (parseError) {
534
482
  // For authentication requests, malformed JSON should be an error
535
483
  if (endpoint.includes("users/me") || endpoint.includes("jwt-auth")) {
536
- throw new WordPressAPIError(
537
- `Invalid JSON response: ${(parseError as Error).message}`,
538
- );
484
+ throw new WordPressAPIError(`Invalid JSON response: ${(parseError as Error).message}`);
539
485
  }
540
486
  this._stats.successfulRequests++;
541
487
  const duration = timer.end();
@@ -552,18 +498,11 @@ export class WordPressClient implements IWordPressClient {
552
498
  }
553
499
 
554
500
  // Handle network errors
555
- if (
556
- lastError.message.includes("socket hang up") ||
557
- lastError.message.includes("ECONNRESET")
558
- ) {
559
- lastError = new Error(
560
- `Network connection lost during upload: ${lastError.message}`,
561
- );
501
+ if (lastError.message.includes("socket hang up") || lastError.message.includes("ECONNRESET")) {
502
+ lastError = new Error(`Network connection lost during upload: ${lastError.message}`);
562
503
  }
563
504
 
564
- debug.log(
565
- `Request failed (attempt ${attempt + 1}): ${lastError.message}`,
566
- );
505
+ debug.log(`Request failed (attempt ${attempt + 1}): ${lastError.message}`);
567
506
 
568
507
  // Don't retry on authentication errors, timeouts, or critical network errors
569
508
  if (
@@ -583,16 +522,13 @@ export class WordPressClient implements IWordPressClient {
583
522
 
584
523
  this._stats.failedRequests++;
585
524
  timer.end();
586
- throw new WordPressAPIError(
587
- `Request failed after ${this.maxRetries} attempts: ${lastError.message}`,
588
- );
525
+ throw new WordPressAPIError(`Request failed after ${this.maxRetries} attempts: ${lastError.message}`);
589
526
  }
590
527
 
591
528
  private updateAverageResponseTime(duration: number): void {
592
529
  const totalSuccessful = this._stats.successfulRequests;
593
530
  this._stats.averageResponseTime =
594
- (this._stats.averageResponseTime * (totalSuccessful - 1) + duration) /
595
- totalSuccessful;
531
+ (this._stats.averageResponseTime * (totalSuccessful - 1) + duration) / totalSuccessful;
596
532
  this._stats.lastRequestTime = Date.now();
597
533
  }
598
534
 
@@ -601,34 +537,19 @@ export class WordPressClient implements IWordPressClient {
601
537
  return this.request<T>("GET", endpoint, null, options);
602
538
  }
603
539
 
604
- async post<T = any>(
605
- endpoint: string,
606
- data?: any,
607
- options?: RequestOptions,
608
- ): Promise<T> {
540
+ async post<T = any>(endpoint: string, data?: any, options?: RequestOptions): Promise<T> {
609
541
  return this.request<T>("POST", endpoint, data, options);
610
542
  }
611
543
 
612
- async put<T = any>(
613
- endpoint: string,
614
- data?: any,
615
- options?: RequestOptions,
616
- ): Promise<T> {
544
+ async put<T = any>(endpoint: string, data?: any, options?: RequestOptions): Promise<T> {
617
545
  return this.request<T>("PUT", endpoint, data, options);
618
546
  }
619
547
 
620
- async patch<T = any>(
621
- endpoint: string,
622
- data?: any,
623
- options?: RequestOptions,
624
- ): Promise<T> {
548
+ async patch<T = any>(endpoint: string, data?: any, options?: RequestOptions): Promise<T> {
625
549
  return this.request<T>("PATCH", endpoint, data, options);
626
550
  }
627
551
 
628
- async delete<T = any>(
629
- endpoint: string,
630
- options?: RequestOptions,
631
- ): Promise<T> {
552
+ async delete<T = any>(endpoint: string, options?: RequestOptions): Promise<T> {
632
553
  return this.request<T>("DELETE", endpoint, null, options);
633
554
  }
634
555
 
@@ -636,16 +557,11 @@ export class WordPressClient implements IWordPressClient {
636
557
 
637
558
  // Posts
638
559
  async getPosts(params?: PostQueryParams): Promise<WordPressPost[]> {
639
- const queryString = params
640
- ? "?" + new URLSearchParams(params as any).toString()
641
- : "";
560
+ const queryString = params ? "?" + new URLSearchParams(params as any).toString() : "";
642
561
  return this.get<WordPressPost[]>(`posts${queryString}`);
643
562
  }
644
563
 
645
- async getPost(
646
- id: number,
647
- context: "view" | "embed" | "edit" = "view",
648
- ): Promise<WordPressPost> {
564
+ async getPost(id: number, context: "view" | "embed" | "edit" = "view"): Promise<WordPressPost> {
649
565
  return this.get<WordPressPost>(`posts/${id}?context=${context}`);
650
566
  }
651
567
 
@@ -658,10 +574,7 @@ export class WordPressClient implements IWordPressClient {
658
574
  return this.put<WordPressPost>(`posts/${id}`, updateData);
659
575
  }
660
576
 
661
- async deletePost(
662
- id: number,
663
- force = false,
664
- ): Promise<{ deleted: boolean; previous?: WordPressPost }> {
577
+ async deletePost(id: number, force = false): Promise<{ deleted: boolean; previous?: WordPressPost }> {
665
578
  return this.delete(`posts/${id}?force=${force}`);
666
579
  }
667
580
 
@@ -671,16 +584,11 @@ export class WordPressClient implements IWordPressClient {
671
584
 
672
585
  // Pages
673
586
  async getPages(params?: PostQueryParams): Promise<WordPressPage[]> {
674
- const queryString = params
675
- ? "?" + new URLSearchParams(params as any).toString()
676
- : "";
587
+ const queryString = params ? "?" + new URLSearchParams(params as any).toString() : "";
677
588
  return this.get<WordPressPage[]>(`pages${queryString}`);
678
589
  }
679
590
 
680
- async getPage(
681
- id: number,
682
- context: "view" | "embed" | "edit" = "view",
683
- ): Promise<WordPressPage> {
591
+ async getPage(id: number, context: "view" | "embed" | "edit" = "view"): Promise<WordPressPage> {
684
592
  return this.get<WordPressPage>(`pages/${id}?context=${context}`);
685
593
  }
686
594
 
@@ -693,10 +601,7 @@ export class WordPressClient implements IWordPressClient {
693
601
  return this.put<WordPressPage>(`pages/${id}`, updateData);
694
602
  }
695
603
 
696
- async deletePage(
697
- id: number,
698
- force = false,
699
- ): Promise<{ deleted: boolean; previous?: WordPressPage }> {
604
+ async deletePage(id: number, force = false): Promise<{ deleted: boolean; previous?: WordPressPage }> {
700
605
  return this.delete(`pages/${id}?force=${force}`);
701
606
  }
702
607
 
@@ -706,16 +611,11 @@ export class WordPressClient implements IWordPressClient {
706
611
 
707
612
  // Media
708
613
  async getMedia(params?: MediaQueryParams): Promise<WordPressMedia[]> {
709
- const queryString = params
710
- ? "?" + new URLSearchParams(params as any).toString()
711
- : "";
614
+ const queryString = params ? "?" + new URLSearchParams(params as any).toString() : "";
712
615
  return this.get<WordPressMedia[]>(`media${queryString}`);
713
616
  }
714
617
 
715
- async getMediaItem(
716
- id: number,
717
- context: "view" | "embed" | "edit" = "view",
718
- ): Promise<WordPressMedia> {
618
+ async getMediaItem(id: number, context: "view" | "embed" | "edit" = "view"): Promise<WordPressMedia> {
719
619
  return this.get<WordPressMedia>(`media/${id}?context=${context}`);
720
620
  }
721
621
 
@@ -736,16 +636,9 @@ export class WordPressClient implements IWordPressClient {
736
636
  );
737
637
  }
738
638
 
739
- debug.log(
740
- `Uploading file: ${filename} (${(stats.size / 1024).toFixed(2)}KB)`,
741
- );
639
+ debug.log(`Uploading file: ${filename} (${(stats.size / 1024).toFixed(2)}KB)`);
742
640
 
743
- return this.uploadFile(
744
- fileBuffer,
745
- filename,
746
- this.getMimeType(data.file_path),
747
- data,
748
- );
641
+ return this.uploadFile(fileBuffer, filename, this.getMimeType(data.file_path), data);
749
642
  }
750
643
 
751
644
  async uploadFile(
@@ -775,8 +668,7 @@ export class WordPressClient implements IWordPressClient {
775
668
  if (meta.post) formData.append("post", meta.post.toString());
776
669
 
777
670
  // Use longer timeout for file uploads
778
- const uploadTimeout =
779
- options?.timeout !== undefined ? options.timeout : 600000; // 10 minutes default
671
+ const uploadTimeout = options?.timeout !== undefined ? options.timeout : 600000; // 10 minutes default
780
672
  const uploadOptions: RequestOptions = {
781
673
  ...options,
782
674
  timeout: uploadTimeout,
@@ -793,25 +685,17 @@ export class WordPressClient implements IWordPressClient {
793
685
  return this.put<WordPressMedia>(`media/${id}`, updateData);
794
686
  }
795
687
 
796
- async deleteMedia(
797
- id: number,
798
- force = false,
799
- ): Promise<{ deleted: boolean; previous?: WordPressMedia }> {
688
+ async deleteMedia(id: number, force = false): Promise<{ deleted: boolean; previous?: WordPressMedia }> {
800
689
  return this.delete(`media/${id}?force=${force}`);
801
690
  }
802
691
 
803
692
  // Users
804
693
  async getUsers(params?: UserQueryParams): Promise<WordPressUser[]> {
805
- const queryString = params
806
- ? "?" + new URLSearchParams(params as any).toString()
807
- : "";
694
+ const queryString = params ? "?" + new URLSearchParams(params as any).toString() : "";
808
695
  return this.get<WordPressUser[]>(`users${queryString}`);
809
696
  }
810
697
 
811
- async getUser(
812
- id: number | "me",
813
- context: "view" | "embed" | "edit" = "view",
814
- ): Promise<WordPressUser> {
698
+ async getUser(id: number | "me", context: "view" | "embed" | "edit" = "view"): Promise<WordPressUser> {
815
699
  return this.get<WordPressUser>(`users/${id}?context=${context}`);
816
700
  }
817
701
 
@@ -824,13 +708,8 @@ export class WordPressClient implements IWordPressClient {
824
708
  return this.put<WordPressUser>(`users/${id}`, updateData);
825
709
  }
826
710
 
827
- async deleteUser(
828
- id: number,
829
- reassign?: number,
830
- ): Promise<{ deleted: boolean; previous?: WordPressUser }> {
831
- const params = reassign
832
- ? `?reassign=${reassign}&force=true`
833
- : "?force=true";
711
+ async deleteUser(id: number, reassign?: number): Promise<{ deleted: boolean; previous?: WordPressUser }> {
712
+ const params = reassign ? `?reassign=${reassign}&force=true` : "?force=true";
834
713
  return this.delete(`users/${id}${params}`);
835
714
  }
836
715
 
@@ -840,16 +719,11 @@ export class WordPressClient implements IWordPressClient {
840
719
 
841
720
  // Comments
842
721
  async getComments(params?: CommentQueryParams): Promise<WordPressComment[]> {
843
- const queryString = params
844
- ? "?" + new URLSearchParams(params as any).toString()
845
- : "";
722
+ const queryString = params ? "?" + new URLSearchParams(params as any).toString() : "";
846
723
  return this.get<WordPressComment[]>(`comments${queryString}`);
847
724
  }
848
725
 
849
- async getComment(
850
- id: number,
851
- context: "view" | "embed" | "edit" = "view",
852
- ): Promise<WordPressComment> {
726
+ async getComment(id: number, context: "view" | "embed" | "edit" = "view"): Promise<WordPressComment> {
853
727
  return this.get<WordPressComment>(`comments/${id}?context=${context}`);
854
728
  }
855
729
 
@@ -862,10 +736,7 @@ export class WordPressClient implements IWordPressClient {
862
736
  return this.put<WordPressComment>(`comments/${id}`, updateData);
863
737
  }
864
738
 
865
- async deleteComment(
866
- id: number,
867
- force = false,
868
- ): Promise<{ deleted: boolean; previous?: WordPressComment }> {
739
+ async deleteComment(id: number, force = false): Promise<{ deleted: boolean; previous?: WordPressComment }> {
869
740
  return this.delete(`comments/${id}?force=${force}`);
870
741
  }
871
742
 
@@ -885,9 +756,7 @@ export class WordPressClient implements IWordPressClient {
885
756
 
886
757
  // Taxonomies
887
758
  async getCategories(params?: any): Promise<WordPressCategory[]> {
888
- const queryString = params
889
- ? "?" + new URLSearchParams(params).toString()
890
- : "";
759
+ const queryString = params ? "?" + new URLSearchParams(params).toString() : "";
891
760
  return this.get<WordPressCategory[]>(`categories${queryString}`);
892
761
  }
893
762
 
@@ -895,30 +764,21 @@ export class WordPressClient implements IWordPressClient {
895
764
  return this.get<WordPressCategory>(`categories/${id}`);
896
765
  }
897
766
 
898
- async createCategory(
899
- data: CreateCategoryRequest,
900
- ): Promise<WordPressCategory> {
767
+ async createCategory(data: CreateCategoryRequest): Promise<WordPressCategory> {
901
768
  return this.post<WordPressCategory>("categories", data);
902
769
  }
903
770
 
904
- async updateCategory(
905
- data: UpdateCategoryRequest,
906
- ): Promise<WordPressCategory> {
771
+ async updateCategory(data: UpdateCategoryRequest): Promise<WordPressCategory> {
907
772
  const { id, ...updateData } = data;
908
773
  return this.put<WordPressCategory>(`categories/${id}`, updateData);
909
774
  }
910
775
 
911
- async deleteCategory(
912
- id: number,
913
- force = false,
914
- ): Promise<{ deleted: boolean; previous?: WordPressCategory }> {
776
+ async deleteCategory(id: number, force = false): Promise<{ deleted: boolean; previous?: WordPressCategory }> {
915
777
  return this.delete(`categories/${id}?force=${force}`);
916
778
  }
917
779
 
918
780
  async getTags(params?: any): Promise<WordPressTag[]> {
919
- const queryString = params
920
- ? "?" + new URLSearchParams(params).toString()
921
- : "";
781
+ const queryString = params ? "?" + new URLSearchParams(params).toString() : "";
922
782
  return this.get<WordPressTag[]>(`tags${queryString}`);
923
783
  }
924
784
 
@@ -935,10 +795,7 @@ export class WordPressClient implements IWordPressClient {
935
795
  return this.put<WordPressTag>(`tags/${id}`, updateData);
936
796
  }
937
797
 
938
- async deleteTag(
939
- id: number,
940
- force = false,
941
- ): Promise<{ deleted: boolean; previous?: WordPressTag }> {
798
+ async deleteTag(id: number, force = false): Promise<{ deleted: boolean; previous?: WordPressTag }> {
942
799
  return this.delete(`tags/${id}?force=${force}`);
943
800
  }
944
801
 
@@ -947,9 +804,7 @@ export class WordPressClient implements IWordPressClient {
947
804
  return this.get<WordPressSiteSettings>("settings");
948
805
  }
949
806
 
950
- async updateSiteSettings(
951
- settings: Partial<WordPressSiteSettings>,
952
- ): Promise<WordPressSiteSettings> {
807
+ async updateSiteSettings(settings: Partial<WordPressSiteSettings>): Promise<WordPressSiteSettings> {
953
808
  return this.post<WordPressSiteSettings>("settings", settings);
954
809
  }
955
810
 
@@ -958,12 +813,8 @@ export class WordPressClient implements IWordPressClient {
958
813
  }
959
814
 
960
815
  // Application Passwords
961
- async getApplicationPasswords(
962
- userId: number | "me" = "me",
963
- ): Promise<WordPressApplicationPassword[]> {
964
- return this.get<WordPressApplicationPassword[]>(
965
- `users/${userId}/application-passwords`,
966
- );
816
+ async getApplicationPasswords(userId: number | "me" = "me"): Promise<WordPressApplicationPassword[]> {
817
+ return this.get<WordPressApplicationPassword[]>(`users/${userId}/application-passwords`);
967
818
  }
968
819
 
969
820
  async createApplicationPassword(
@@ -973,25 +824,15 @@ export class WordPressClient implements IWordPressClient {
973
824
  ): Promise<WordPressApplicationPassword> {
974
825
  const data: any = { name };
975
826
  if (appId) data.app_id = appId;
976
- return this.post<WordPressApplicationPassword>(
977
- `users/${userId}/application-passwords`,
978
- data,
979
- );
827
+ return this.post<WordPressApplicationPassword>(`users/${userId}/application-passwords`, data);
980
828
  }
981
829
 
982
- async deleteApplicationPassword(
983
- userId: number | "me",
984
- uuid: string,
985
- ): Promise<{ deleted: boolean }> {
830
+ async deleteApplicationPassword(userId: number | "me", uuid: string): Promise<{ deleted: boolean }> {
986
831
  return this.delete(`users/${userId}/application-passwords/${uuid}`);
987
832
  }
988
833
 
989
834
  // Search
990
- async search(
991
- query: string,
992
- types?: string[],
993
- subtype?: string,
994
- ): Promise<any[]> {
835
+ async search(query: string, types?: string[], subtype?: string): Promise<any[]> {
995
836
  const params = new URLSearchParams({ search: query });
996
837
  if (types) params.append("type", types.join(","));
997
838
  if (subtype) params.append("subtype", subtype);
@@ -1037,8 +878,7 @@ export class WordPressClient implements IWordPressClient {
1037
878
  ".svg": "image/svg+xml",
1038
879
  ".pdf": "application/pdf",
1039
880
  ".doc": "application/msword",
1040
- ".docx":
1041
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
881
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
1042
882
  ".txt": "text/plain",
1043
883
  ".mp4": "video/mp4",
1044
884
  ".mp3": "audio/mpeg",