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.
- package/README.md +332 -61
- package/dist/cache/CacheInvalidation.d.ts.map +1 -1
- package/dist/cache/CacheInvalidation.js +4 -4
- package/dist/cache/CacheInvalidation.js.map +1 -1
- package/dist/client/MockWordPressClient.d.ts +55 -0
- package/dist/client/MockWordPressClient.d.ts.map +1 -0
- package/dist/client/MockWordPressClient.js +369 -0
- package/dist/client/MockWordPressClient.js.map +1 -0
- package/dist/client/api.d.ts +1 -0
- package/dist/client/api.d.ts.map +1 -1
- package/dist/client/api.js +26 -60
- package/dist/client/api.js.map +1 -1
- package/dist/client/managers/AuthenticationManager.d.ts.map +1 -1
- package/dist/client/managers/AuthenticationManager.js +4 -3
- package/dist/client/managers/AuthenticationManager.js.map +1 -1
- package/dist/config/ConfigurationSchema.d.ts +3 -3
- package/dist/config/ConfigurationSchema.d.ts.map +1 -1
- package/dist/config/ConfigurationSchema.js +7 -24
- package/dist/config/ConfigurationSchema.js.map +1 -1
- package/dist/config/ServerConfiguration.d.ts +8 -0
- package/dist/config/ServerConfiguration.d.ts.map +1 -1
- package/dist/config/ServerConfiguration.js +80 -31
- package/dist/config/ServerConfiguration.js.map +1 -1
- package/dist/docs/DocumentationGenerator.d.ts.map +1 -1
- package/dist/docs/DocumentationGenerator.js +5 -7
- package/dist/docs/DocumentationGenerator.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -29
- package/dist/index.js.map +1 -1
- package/dist/security/InputValidator.d.ts.map +1 -1
- package/dist/security/InputValidator.js +3 -11
- package/dist/security/InputValidator.js.map +1 -1
- package/dist/server/ToolRegistry.d.ts +4 -0
- package/dist/server/ToolRegistry.d.ts.map +1 -1
- package/dist/server/ToolRegistry.js +71 -8
- package/dist/server/ToolRegistry.js.map +1 -1
- package/dist/tools/auth.d.ts.map +1 -1
- package/dist/tools/auth.js +8 -3
- package/dist/tools/auth.js.map +1 -1
- package/dist/tools/posts.d.ts.map +1 -1
- package/dist/tools/posts.js +287 -20
- package/dist/tools/posts.js.map +1 -1
- package/dist/tools/site.d.ts.map +1 -1
- package/dist/tools/site.js +47 -9
- package/dist/tools/site.js.map +1 -1
- package/dist/tools/users.d.ts.map +1 -1
- package/dist/tools/users.js +113 -10
- package/dist/tools/users.js.map +1 -1
- package/dist/utils/enhancedError.d.ts +61 -0
- package/dist/utils/enhancedError.d.ts.map +1 -0
- package/dist/utils/enhancedError.js +221 -0
- package/dist/utils/enhancedError.js.map +1 -0
- package/dist/utils/streaming.d.ts +104 -0
- package/dist/utils/streaming.d.ts.map +1 -0
- package/dist/utils/streaming.js +312 -0
- package/dist/utils/streaming.js.map +1 -0
- package/dist/utils/validation.d.ts +19 -3
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +174 -24
- package/dist/utils/validation.js.map +1 -1
- package/docs/ARCHITECTURE.md +850 -0
- package/docs/CACHING.md +20 -17
- package/docs/CONFIGURATION.md +660 -0
- package/docs/DOCKER.md +61 -60
- package/docs/EVALUATION.md +397 -0
- package/docs/INSTALLATION.md +423 -0
- package/docs/PERFORMANCE_MONITORING.md +17 -15
- package/docs/SECURITY.md +621 -0
- package/docs/SECURITY_TESTING.md +22 -26
- package/docs/TEST_SITE_SETUP.md +136 -0
- package/docs/TROUBLESHOOTING.md +578 -0
- package/docs/api/README.md +76 -91
- package/docs/api/categories/auth.md +0 -2
- package/docs/api/categories/cache.md +0 -2
- package/docs/api/categories/comment.md +0 -2
- package/docs/api/categories/media.md +0 -2
- package/docs/api/categories/page.md +0 -2
- package/docs/api/categories/performance.md +0 -2
- package/docs/api/categories/post.md +0 -2
- package/docs/api/categories/site.md +0 -2
- package/docs/api/categories/taxonomy.md +0 -2
- package/docs/api/categories/user.md +0 -2
- package/docs/api/summary.json +1 -1
- package/docs/api/tools/wp_approve_comment.md +11 -3
- package/docs/api/tools/wp_cache_clear.md +14 -5
- package/docs/api/tools/wp_cache_info.md +14 -5
- package/docs/api/tools/wp_cache_stats.md +14 -5
- package/docs/api/tools/wp_cache_warm.md +14 -5
- package/docs/api/tools/wp_create_application_password.md +11 -3
- package/docs/api/tools/wp_create_category.md +11 -3
- package/docs/api/tools/wp_create_comment.md +14 -5
- package/docs/api/tools/wp_create_page.md +13 -5
- package/docs/api/tools/wp_create_post.md +14 -7
- package/docs/api/tools/wp_create_tag.md +11 -3
- package/docs/api/tools/wp_create_user.md +13 -5
- package/docs/api/tools/wp_delete_application_password.md +11 -3
- package/docs/api/tools/wp_delete_category.md +11 -3
- package/docs/api/tools/wp_delete_comment.md +11 -3
- package/docs/api/tools/wp_delete_media.md +10 -3
- package/docs/api/tools/wp_delete_page.md +10 -3
- package/docs/api/tools/wp_delete_post.md +11 -5
- package/docs/api/tools/wp_delete_tag.md +11 -3
- package/docs/api/tools/wp_delete_user.md +10 -3
- package/docs/api/tools/wp_get_application_passwords.md +11 -3
- package/docs/api/tools/wp_get_auth_status.md +11 -3
- package/docs/api/tools/wp_get_category.md +11 -3
- package/docs/api/tools/wp_get_comment.md +11 -3
- package/docs/api/tools/wp_get_current_user.md +11 -3
- package/docs/api/tools/wp_get_media.md +11 -3
- package/docs/api/tools/wp_get_page.md +11 -3
- package/docs/api/tools/wp_get_page_revisions.md +11 -3
- package/docs/api/tools/wp_get_post.md +12 -5
- package/docs/api/tools/wp_get_post_revisions.md +11 -3
- package/docs/api/tools/wp_get_site_settings.md +10 -3
- package/docs/api/tools/wp_get_tag.md +11 -3
- package/docs/api/tools/wp_get_user.md +11 -3
- package/docs/api/tools/wp_list_categories.md +11 -3
- package/docs/api/tools/wp_list_comments.md +11 -3
- package/docs/api/tools/wp_list_media.md +14 -5
- package/docs/api/tools/wp_list_pages.md +14 -5
- package/docs/api/tools/wp_list_posts.md +15 -7
- package/docs/api/tools/wp_list_tags.md +11 -3
- package/docs/api/tools/wp_list_users.md +11 -3
- package/docs/api/tools/wp_performance_alerts.md +17 -7
- package/docs/api/tools/wp_performance_benchmark.md +17 -7
- package/docs/api/tools/wp_performance_export.md +17 -7
- package/docs/api/tools/wp_performance_history.md +17 -7
- package/docs/api/tools/wp_performance_optimize.md +17 -7
- package/docs/api/tools/wp_performance_stats.md +17 -7
- package/docs/api/tools/wp_search_site.md +11 -3
- package/docs/api/tools/wp_spam_comment.md +11 -3
- package/docs/api/tools/wp_switch_auth_method.md +14 -5
- package/docs/api/tools/wp_test_auth.md +11 -3
- package/docs/api/tools/wp_update_category.md +11 -3
- package/docs/api/tools/wp_update_comment.md +14 -5
- package/docs/api/tools/wp_update_media.md +14 -5
- package/docs/api/tools/wp_update_page.md +13 -5
- package/docs/api/tools/wp_update_post.md +14 -7
- package/docs/api/tools/wp_update_site_settings.md +14 -5
- package/docs/api/tools/wp_update_tag.md +11 -3
- package/docs/api/tools/wp_update_user.md +13 -5
- package/docs/api/tools/wp_upload_media.md +13 -5
- package/docs/api/types/WordPressPost.md +2 -0
- package/docs/code-improvements.md +40 -0
- package/docs/contract-testing.md +1 -1
- package/docs/developer/API_REFERENCE.md +19 -59
- package/docs/developer/ARCHITECTURE.md +8 -11
- package/docs/developer/BUILD_SYSTEM.md +2 -2
- package/docs/developer/CONTRIBUTING.md +3 -5
- package/docs/developer/GITHUB_ACTIONS_SETUP.md +2 -2
- package/docs/developer/MIGRATION_GUIDE.md +5 -6
- package/docs/developer/README.md +2 -1
- package/docs/developer/REFACTORING.md +9 -15
- package/docs/developer/RELEASE_PROCESS.md +4 -3
- package/docs/developer/TESTING.md +2 -2
- package/docs/examples/claude-desktop-config.md +8 -0
- package/docs/integrations/claude-desktop.md +426 -0
- package/docs/integrations/cline.md +537 -0
- package/docs/integrations/vs-code.md +515 -0
- package/docs/releases/COMMUNITY_ANNOUNCEMENT_v1.1.2.md +30 -23
- package/docs/releases/RELEASE_NOTES_v1.1.2.md +7 -6
- package/docs/testing-configurations.md +11 -0
- package/docs/user-guides/DOCKER_NPM_DTX_SETUP.md +3 -2
- package/docs/user-guides/DOCKER_SETUP.md +3 -2
- package/docs/user-guides/DTX_SETUP.md +6 -5
- package/docs/user-guides/DXT_INSTALLATION.md +4 -4
- package/docs/user-guides/NPM_SETUP.md +4 -2
- package/docs/user-guides/NPX_SETUP.md +4 -2
- package/docs/user-guides/SMITHERY_SETUP.md +402 -0
- package/docs/wordpress-rest-api-authentication-troubleshooting.md +45 -42
- package/package.json +12 -2
- package/src/cache/CacheInvalidation.ts +7 -18
- package/src/client/MockWordPressClient.ts +398 -0
- package/src/client/api.ts +77 -237
- package/src/client/managers/AuthenticationManager.ts +19 -56
- package/src/config/ConfigurationSchema.ts +14 -45
- package/src/config/ServerConfiguration.ts +98 -71
- package/src/docs/DocumentationGenerator.ts +39 -123
- package/src/dxt-entry.cjs +4 -1
- package/src/index.ts +35 -54
- package/src/security/InputValidator.ts +15 -57
- package/src/server/ToolRegistry.ts +88 -17
- package/src/tools/auth.ts +15 -22
- package/src/tools/posts.ts +347 -64
- package/src/tools/site.ts +69 -46
- package/src/tools/users.ts +142 -44
- package/src/utils/enhancedError.ts +248 -0
- package/src/utils/streaming.ts +428 -0
- package/src/utils/validation.ts +253 -92
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
344
|
-
{
|
|
345
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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",
|